IRCbot
Publicado por Perfil removido 25/01/2004
[ Hits: 8.940 ]
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>
Nenhum comentário foi encontrado.
IA Turbina o Desktop Linux enquanto distros renovam forças
Como extrair chaves TOTP 2FA a partir de QRCODE (Google Authenticator)
Linux em 2025: Segurança prática para o usuário
Desktop Linux em alta: novos apps, distros e privacidade marcam o sábado
Atualizando o Fedora 42 para 43
Como saber se o seu e-mail já teve a senha vazada?
Como descobrir se a sua senha já foi vazada na internet?
E aí? O Warsaw já está funcionando no Debian 13? [RESOLVIDO] (15)
Secure boot, artigo interessante, nada técnico. (4)
copiar library para diretorio /usr/share/..... su com Falha na a... (1)









