IRCbot
Publicado por Perfil removido 25/01/2004
[ Hits: 8.712 ]
O IRCbot 1.1 é um bot para IRC criado por Matheus Meira utilizando linguagem PHP. O
IRCbot tem funções básicas como op, deop, voice, devoice, ban, kick, etc.
O código está todo comentado, detalhando como funciona todas as inúmeras funções. Ideal
para quem deseja aprender o funcionamento de um bot em PHP.
<? /***************************************/ /************* IRCbot 1.1 **************/ /** por infos (infos@superig.com.br) ***/ /***************************************/ /***** idéia original por ShadowMan ****/ /***************************************/ /* Futuras adesões: */ /* Melhoramento nos Timers */ /* Melhoramento no tratamento das RAWS */ /* Sistema de usuários em Mysql */ /* Comando !ping */ /* Tratamento aos CTCPs */ /***************************************/ /* Adesões 1.1 - Feito comando timer (não ficou bom, mas foi o melhor que deu para fazer) - Opção para exibir log no browser ou não (se exibir log no browser o bot só se mantém conectado enquanto o browser estiver aberto, bom para ver erros, se não exibir o log, o bot fica conectado mesmo depois de feixar o browser) - Melhorado o sistema visual (agora com cores) 1.0 - Feito todos os sistemas básicos - Feito comando para adicionar ativadores - Adicionado funções básicas como op, deop, kick, etc. - Feito sistema visual (tanto no navegador quanto nos logs) À corrigir: - comando emote(); */ // os comandos prontos são para voces se familiarizarem com o bot e estão prontos para serem utilizados // ps: altere a linha nº 207 com o Nick!User_Name@end correto do nickserv da sua rede. // Tirando timeout set_time_limit(0); ?><font face="Verdana" size="2"><? // Criando a classe e setando as variaveis $bot=@new bot; $bot->senha = "uma_senha"; // Senha do nickserv. deixe vazio ("") para não identificar $bot->server = "irc.servidor.com.br"; // Servidor $bot->porta = 6667; // porta $bot->owner = "owner"; // nick do owner $bot->me = "bot"; // nick do bot $bot->username = "phpbot"; // username do bot (nick!username@end) $bot->realname = "PHPbot por infos"; // nome do bot $bot->canais = ""; // canais para entrar ao conectar $bot->quitmsg = "Requested."; // mensagem padrão de quit $bot->modes = "+p"; // Modos postos pelo bot ao conectar.. deixe vazio ("") para não setar $bot->reconectar = true; // reconectar ao perder conexão? $bot->visual = false; // Bot com visual? // quando true: o navegador mostrará o log de tudo que o bot recebe do servidor/do que o bot envia para o servidor, o bot só permanece conectado enquanto o navegador estiver aberto. o bot também loga tudo no arquivo bot.log. ideal para ser utilizado ao fazer alterações no bot (ver erros). // quando false: o log das ações enviadas para o servidor e recebidas pelo mesmo só são postas no arquivo bot.log. o bot é executado mesmo quando o navegador está fechado. class bot { function conectar() { // abre o socket, dá erro de falhar $this->fp=@fsockopen($this->server ,$this->porta,$erro,$ermsg) or die("Erro ao abrir o socket. Erro $erro: $ermsg ".$this->server.":".$this->porta."</font>"); if ($this->visual) { echo "Conectado..."; flush(); } } function logar() { // seta o username, modo de usuário e realname $this->enviar("USER ".$this->username." 0 * :".$this->realname); // seta o nick $this->enviar("NICK ".$this->me); // identifica o nick if ($this->senha != "") $this->enviar("nickserv identify ".$this->senha); // se foi especificado algum modo, ele seta if ($this->modes != "") $this->enviar("MODE ".$this->me." ".$this->modes); } function desconectar() { // Fui desconectado // Tira a flags pra reconectar (?) exibe desconectar no log e no navegador $this->log("-> Desconectado", "","<br>"); fclose($this->fp); fclose($this->log); } function quit($q = null) { // idem ao de cima, porém ele aqui solicita a desconexão.. e exibe a mensagem de quit padrão se não for especificada.. $this->reconectar=false; if ($q != null) $this->enviar("QUIT :".$q); else $this->enviar("QUIT :".$this->quitmsg); sleep(1); fclose($this->fp); fclose($this->log); die("</font>"); } function enviar($texto) { // envia um comando ao servidor, e chama o comando pra logar a mensagem fputs($this->fp, $texto."\r\n"); $this->log("-> ".$texto); } function log($texto, $pre = "", $suf = "") { // exibe o parametro no log e no navegador // $pre eh para ser utilizado coisas como, cores, etc.. // $suf para fechar as tags fwrite($this->log,$texto."\n"); if ($this->visual) { echo "<br>".$pre."(".date("H:i:s").") ".$texto.$suf; flush(); } } function rodar() { // enquanto tiver setado para permanecer o bot conectado while ($this->reconectar) { // abre o log $this->log=fopen('Bot.log','a'); // conecta $this->conectar(); sleep(1); // envia os parametros da conexão $this->logar(); // entra nos canais especificados automaticamente $this->join($this->canais); $timea=time(); // para o timer (leia sobre ele mais em baixo) // Seta o timeout da conexão pra 5 minutos (se ele não receber nada do servidor em 5 minutos ele desconecta o socket). o default é 1 minuto (ele recebe o PING do servidor pelo menos 1 vez a cada 5 minutos com certeza, por isso setei um valor alto) stream_set_timeout($this->fp,300); // enquanto a conexão estiver ativa, pega o texto recebido while (!feof($this->fp)) { $t=fgets($this->fp); // limpa as quebras de linha $t=trim($t); // divide ele num array para tratamento $q=explode(" ",$t); // pega o host do user (user!username@address) $host=substr($q[0],1); // pega o host $nick=explode("!",$host); $nick=$nick[0]; // seta vazio para não pegar valores passados $msg=""; // se o parametro for notice ou privmsg (mensagem) if (($q[1] == "NOTICE") || ($q[1] == "PRIVMSG")) { // se for canal, seta o nome do canal if (substr($q[2],0,1) == "#") $onde=$q[2]; // se for pvt, seta pvt else $onde="PVT"; } // se nao for mensagem ou notice, seta NONE pra não chamar o evento que vai ver se tem algum comando "chamado" else $onde="NONE"; // limpa a string (?) $q[3]=trim($q[3]); // se a string tiver : no início, ele tira (parametros com mais de 1 palavra vem precedidos de ":") if (substr($q[3],0,1) == ":") $q[3]=substr($q[3],1); // $q[3] no caso seria !join em "!join canal balblabla" // para x=4 (início dos parametros) até o fim dele, seta tudo numa variavel for ($x=4;$x <= count($q);$x++) $msg .= " ".$q[$x]; // limpa a mensagem de espaços e quebras de linha (eles ocorrerão) $msg=trim($msg); // mensagem total.. $msgt = trim($q[3]." ".$msg); // INÍCIO DO TIMER (leia abaixo nos comandos sobre ele..) // $timea é a ultima vez que eu recebi um pacote! (se voce leu sobre ele abaixo, saberá do que se trata) // entao eu vou testando segundo por segundo o $timea até o time() atual // buscando ver todos os timers (inclusive os atrazados..) for($time=time();$timea <= $time; $timea++) { // como todo array tem que começar com uma letra, a + tempo_procurado é o valor do array que eu vou buscar $timeb="a".$timea; // Para cada valor do array foreach($this->vtimer as $chave => $ok) { // se o nome da chave for igual ao tempo procurado if ($chave == $timeb) { // executamos os comandos pedidos... foreach ($ok as $comando) { $this->$comando(); } } } // apagamos a variavel para não gastar memoria atoa.. unset($this->vtimer[$timeb]); } // tempo do ultimo pacote para usar no timer $timea=time(); // Início da parte de logs (no navegador e arquivo) // EVENTO JOIN if ($q[1] == "JOIN") $this->log("--> Entrou ".substr($q[2],1).": ".$nick." (".$host.")","<font color=\"red\">","</font>"); // EVENTO PART elseif ($q[1] == "PART") $this->log("--> Saiu ".$q[2].": ".$nick." (".$host.")","<font color=\"red\">","</font>"); // O servidor manda eventos "NOTICE" simples.. como NOTICE :*** AUTH blablabla.. // loga normalmente como vem do servidor elseif ($q[0] == "NOTICE") $this->log($t); // Se for setado algum modo elseif ($q[1] == "MODE") $this->log("---> MODE ".$q[2]." ".$q[3]." ".$msg); // Se alguém muda de nick elseif ($q[1] == "NICK") $this->log("---> ".$nick." mudou o nick para: ".substr($q[2],1)); // Se alguém desconectou elseif ($q[1] == "QUIT") $this->log("---> QUIT ".$nick.": ".substr($t,strpos($t,"QUIT")+6),"<font color=\"gray\">","</font>"); // Se foi mudado o topico elseif ($q[1] == "TOPIC") $this->log("---> ".$nick." mudou o topico de ".$q[2]." para: ".$msgt); // Se foi recebida alguma mensagem (sintaxe: [nick\onde] texto) onde "onde" é PVT ou o nome do canal elseif ($q[1] == "PRIVMSG") $this->log("(".$nick."\\".$onde.") ".$msgt,"<font color=\"blue\">","</font>"); // Se foi recebido algum notice (sintaxe: [nick\onde] texto) onde "onde" é PVT ou o nome do canal elseif ($q[1] == "NOTICE") $this->log("[".$nick."\\".$onde."] ".$msgt,"<font color=\"blue\">","</font>"); // Se mensagem total for vazia [lembrem-se que mensagemT é setado quando agente recebe uma mensagem ou notice, tendo a mensagem completa (e somente ela)] ele joga no log como uma função do server não catalogada.. elseif (trim($msgt) == "") $this->log("-SERVER- ".$t); // mensagens do servidor normais (outras raws, motd, etc) else $this->log("-SERVER- ".$msgt); // se recebi um PING (mensagem do servidor pra ver se o cliente esta ativo e não caiu) ele manda sua resposta if ($q[0] == "PING") $this->enviar("PONG ".$q[1]); // Identifique o nick, caso o nickserv peça if (($host == "NickServ!services@brasnet.org") && ($this->senha != "") && (strtoupper($msgt) == strtoupper("Este nick esta registrado e protegido. Se o nick pertence"))) $this->enviar("nickserv identify ".$this->senha); // se $ONDE for diferente de none (onde eh none quando o texto recebido não é de mensagem ou notice) if ($onde != "NONE") { // verifica aqui se o comando "pego" ($q[3]) existe na lista de comandos a executar uma função.. $array=$this->comandos[strtoupper($q[3])]; $ondec=$this->comandos[strtoupper("onde".$q[3])]; if ((strtoupper($onde) == strtoupper($ondec)) || (substr(strtoupper($onde),0,1) == strtoupper($ondec)) || (strtoupper($ondec) == "ALL")) $this->$array($nick, $host, $msg, $msgt, $onde); // (acima) se para o comando, existir uma função, ela é chamada } // Seta o timeout da conexão pra 5 minutos (se ele não receber nada do servidor em 5 minutos ele desconecta o socket). o default é 1 minuto (ele recebe o PING do servidor pelo menos 1 vez a cada 5 minutos com certeza, por isso setei um valor alto) stream_set_timeout($this->fp,300); } // Fui desconectado! $this->desconectar(); } } function novocmd($cmd = null, $ativ = null, $onde = "all") { // Função que adiciona os comandos à "lista de comandos a executar uma função" // se existir um comando E um ativador if (($cmd != null) && ($ativ != null)) { // $x recebe $this (objeto, @new bot) e o comando $x=array($this,$cmd); // se a função existe (para evitar futuros erros..) ele adiciona no array da lista de funções if (is_callable($x,false)) $this->comandos=array_merge($this->comandos, array(strtoupper($ativ) => strtoupper($cmd), strtoupper("onde".$ativ) => strtoupper($onde))); // Se não existir, ele cancela o processo pra evitar erros futuros else die("Você não pode definir um comando com uma função inexistente! (função: ".$cmd.")</font>"); } else $this->log("Erro na adição de um novo comando! -COMANDO IGNORADO- Comando a ser executado: ".$cmd." Ativador: ".$ativ); } function timer($cmd = null, $tempo = null) { if (($cmd != null) && ($tempo != null) && (is_int($tempo))) { $x=array($this,$cmd); $tempo = (string) "a".intval($tempo+time()); if (is_callable($x,false)) { $this->vtimer=array_merge($this->vtimer, array($tempo => array_merge($this->vtime[$tempo], array($cmd)))); } else die("Você não pode definir um comando com uma função inexistente! (função: ".$cmd.")</font>"); } else $this->log("Erro no timer! -TIMER IGNORADO- Comando a ser executado: ".$cmd); } // funções básicas.. // Sintaxe delas: $onde $quem/$msg/$host/$nick/$canais $modo $tipo // nem todas recebem todas as variaveis.. function msg($onde = null, $msg = null) { // se existir um lugar e existir uma mensagem // envia a mensagem para o lugar if (($onde != null) && ($msg != null)) $this->enviar("PRIVMSG ".$onde." :".$msg); } function emote($onde = null, $msg = null) { // se existir um lugar e existir uma mensagem // envia a ação para o lugar if (($onde != null) && ($msg != null)) $this->enviar("PRIVMSG ".$onde." :ACTION".$msg); } function notice($onde = null, $msg = null) { // se existir um lugar e existir uma mensagem // envia a mensagem para o lugar if (($onde != null) && ($msg != null)) $this->enviar("NOTICE ".$onde." :".$msg); } function op($onde = null, $quem = null) { // se existir o lugar e alguém // dá op para o usuário no canal especificado if (($onde != null) && ($quem != null)) $this->mode($onde, $quem, "-v"); } function deop($onde = null, $quem = null) { // se existir o lugar e alguém // tira o op do usuario no canal especificado if (($onde != null) && ($quem != null)) $this->mode($onde, $quem, "-v"); } function voice($onde = null, $quem = null) { // se existir o lugar e alguém // dá voice para o usuário no canal especificado if (($onde != null) && ($quem != null)) $this->mode($onde, $quem, "-v"); } function devoice($onde = null, $quem = null) { // se existir o lugar e alguém // tira o voice do usuario no canal especificado if (($onde != null) && ($quem != null)) $this->mode($onde, $quem, "-v"); } function ban($onde = null, $host = null) { // se existir o lugar e alguém // bane a !!MASCARA!! do canal if (($onde != null) && ($quem != null)) $this->mode($onde, $quem, "+b"); } function nick($nick) { // se o nick desejado for diferente do atual, muda.. if (($nick != null) && (strtoupper($nick) != strtoupper($this->me))) $this->enviar("NICK ".$nick); } function kick($onde = null, $quem = null, $motivo = "Requested") { // se existir o local e a pessoa // kicka ela do canal com o motivo solicitado (ou o padrao) if (($onde != null) && ($quem != null)) $this->enviar("KICK ".$onde." ".$quem." :".$motivo); } function join($canais = "") { // se existir os canais // entra em todos os canais separados por um " " (espaço) if ($canais != "") { $canais=explode(" ",$canais); foreach($canais as $x) $this->enviar("JOIN ".$x); } } function part($canais = "") { // se existir os canais // sai de todos os canais separados por um " " (espaço) if ($canais != "") { $canais=explode(" ",$canais); foreach($canais as $x) $this->enviar("PART ".$x); } } function mode($onde = null, $quem = null, $modo = null, $tipo = 0) { // $tipo = 0 quando eu vou setar todos os "+b-x+z" pela variavel $modo // $tipo = 1 (default) eu vou utilizar $modo = "+b" // e $quem = "eu1 eu2 eu3" // e a funcao vai, automaticamente, ir setando os outros "+b" para todos da lista.. (soh funciona pra setar um unico modo..) // se existir lugar, alguem e modo if (($onde != null) && ($quem != null) && ($modo != null)) { // se os modos ja estao setados pela variavel $modo, seta os modos if ($tipo == 0) $this->enviar("MODE ".$onde." ".$modo." ".$quem); // se nao, ele ve quantos usuarios sao, e executa o modo em todos.. else { $qtd=explode(" ",$quem); $qtd=count($qtd); $this->enviar("MODE ".$onde." ".$modo.str_repeat(substr($modo,1,1), $qtd-1)." ".$quem); } } } // comandos pré-definidos, veja abaixo do que se trata function _mensagem($nick, $host, $msg, $msgt) { if (strtoupper($nick) == strtoupper($this->owner)) $this->msg("#aow_shard",$msg); } function _emote($nick, $host, $msg, $msgt) { if (strtoupper($nick) == strtoupper($this->owner)) $this->emote("#aow_shard",$msg); } function _op($nick, $host, $msg, $msgt, $onde) { if (strtoupper($nick) == strtoupper($this->owner)) $this->mode($onde, $nick, "+o"); } function _part($nick, $host, $msg, $msgt) { if (strtoupper($nick) == strtoupper($this->owner)) $this->part($msg); } function _join($nick, $host, $msg, $msgt) { if (strtoupper($nick) == strtoupper($this->owner)) $this->join($msg); } function _nick($nick, $host, $msg, $msgt) { if (strtoupper($nick) == strtoupper($this->owner)) $this->nick($msg); } function _quit($nick, $host, $msg = null, $msgt) { if (strtoupper($nick) == strtoupper($this->owner)) { if ($msg != "") $this->quit($msg); else $this->quit($this->quitmsg); } } function __msg1() { return "msg1; } function __msg2() { return "msg2; } function __msg3() { return "msg3"; } function __msg4() { return "msg4"; } function __msg5() { return "msg5"; } function __msg6() { return "msg6"; } function __msg7() { return "msg7"; } function _taow() { $cmd="__msg".rand(1,7); $this->msg("#canal", $this->$cmd()); $this->timer("_taow", 300); } } // Adiciona novos comandos // sintaxe novocmd(funcao a ser chamada, ativador, onde); // se onde nao for especificado, é chamado em todos os lugares (canais e pvts) // se onde = pvt, só é chamado no pvt // se onde = #canal, só é chamado no canal em questão // se onde = #, é chamado em qualquer canal // a funcao deve ser criada na classe BOT para que funcione corretamente // e deve ser declarada antes da função rodar() // TODAS as funcoes devem receber como parâmetros: // $nick, $host, $msg, $msgt, $onde // ex: function _funcao($nick, $host, $msg, $msgt, $onde) $bot->novocmd("_mensagem","!msg","pvt"); $bot->novocmd("_emote","!me","#canal"); $bot->novocmd("_quit","!quit"); $bot->novocmd("_part","!part"); $bot->novocmd("_nick","!nick"); $bot->novocmd("_op","!op","#"); $bot->novocmd("_join","!join"); // Breve descrição sobre o timer: // O timer PERFEITO em php neste caso é algo meio impossível de se fazer // Pois o PHP não suporta threads e não posso fazer 2 whiles rodar em paralelo... // Um, no caso fazendo o papel do timer e o outro o papel do bot // Porquê não fez tudo junto e deu certo? // Simples! A função utilizada para receber um dado (socket) pára a execução do script // até receber algum dado.. Ou seja, ele pode demorar 1 segundo para receber um dado // do servidor, assim como pode demorar 5 minutos... // Felizmente eu utilizei o artifício do servidor mandar em intervalos de cerca de 2 minutos // o dado "PING" (pelo tempo que eu verifiquei na ocasiao era isto, agora verificando melhor, // pode ser muito maior que 5 segundos, bem variavel) para verificar se o cliente // está conectado e assim consigo fazer um timer "que atraza" // Então eu fiz uma simulação de timer.. Como funciona? // Depois de X -SEGUNDOS-, assim que o BOT receber um dado do servidor, ele VAI // executar o comando desejado no timer.. Sendo esse tempo de, no máximo, o valor de // intervalo entre 2 "PING"s enviados pelo servidor.. esse tempo varia, mas não muito // Ainda não foi implementado algo que faça o timer rodar por X vezes (ou infinitamente).. // mas é algo facilmente adicionavel.. é só fazer que a função chamada no timer chame // outro timer.... // IMPORTANTE: o timer é chamado -ANTES- de verificar se a mensagem tem algum comando.. // Assim, se o timer atrazar, e você tiver um timer que cancele um comando, poderá // faze-lo normalmente.. // neste exemplo, depois de 60 segundos ele ativa um timer que fala // algo aleatorio no canal a cada 5 minutos $bot->timer("_taow", 60); $bot->rodar(); $bot->desconectar(); ?></font>
Busca por Dominio .com .net e .org
Pegando tweets de forma simples
Geração de códigos captcha em formulários HTML com PHP e PostgreSQL
Nenhum comentário foi encontrado.
Enviar mensagem ao usuário trabalhando com as opções do php.ini
Meu Fork do Plugin de Integração do CVS para o KDevelop
Compartilhando a tela do Computador no Celular via Deskreen
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
Compartilhamento de Rede com samba em modo Público/Anônimo de forma simples, rápido e fácil
Cups: Mapear/listar todas as impressoras de outro Servidor CUPS de forma rápida e fácil
Criando uma VPC na AWS via CLI
Tem como instalar o gerenciador AMD Adrenalin no Ubuntu 24.04? (16)
Arch Linux - Guia para Iniciantes (2)
Problemas ao instalar o PHP (11)
Tenho dois Link's ( IP VÁLIDOS ), estou tentando fazer o failover... (0)