IRCbot
Publicado por Perfil removido 25/01/2004
[ Hits: 8.702 ]
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>
Classe com método para inserir vídeos Vimeo e YouTube
Whois Buscando dominios nacionais e internacionais
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
Criando uma VPC na AWS via CLI
Multifuncional HP imprime mas não digitaliza
Dica básica para escrever um Artigo.
Como Exibir Imagens Aleatórias no Neofetch para Personalizar seu Terminal
Melhorando a precisão de valores flutuantes em python[AJUDA] (11)
GLPI - Configuração de destinatário com conta Microsoft Exchange (0)
Vou voltar moderar conteúdos de Dicas e Artigos (3)
OpenVPN no MACBOOK conecta mas não pinga pastas de rede compartilhada ... (1)