Guest User

Untitled

a guest
Jul 21st, 2018
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.70 KB | None | 0 0
  1. <? /***************************************/
  2. /************* IRCbot 1.1 **************/
  3. /** por infos (infos@superig.com.br) ***/
  4. /***************************************/
  5. /***** idéia original por ShadowMan ****/
  6. /***************************************/
  7. /* Futuras adesões: */
  8. /* Melhoramento nos Timers */
  9. /* Melhoramento no tratamento das RAWS */
  10. /* Sistema de usuários em Mysql */
  11. /* Comando !ping */
  12. /* Tratamento aos CTCPs */
  13. /***************************************/
  14.  
  15. /*
  16. Adesões
  17.  
  18. 1.1
  19. - Feito comando timer (não ficou bom, mas foi o melhor que deu para fazer)
  20. - 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)
  21. - Melhorado o sistema visual (agora com cores)
  22.  
  23. 1.0
  24. - Feito todos os sistemas básicos
  25. - Feito comando para adicionar ativadores
  26. - Adicionado funções básicas como op, deop, kick, etc.
  27. - Feito sistema visual (tanto no navegador quanto nos logs)
  28.  
  29. À corrigir:
  30. - comando emote();
  31. */
  32.  
  33. // os comandos prontos são para voces se familiarizarem com o bot e estão prontos para serem utilizados
  34.  
  35. // Tirando timeout
  36. set_time_limit(0); ?><font face="Verdana" size="2"><?
  37. // Criando a classe e setando as variaveis
  38. $bot=@new bot;
  39. $bot->senha = "chester1"; // Senha do nickserv. deixe vazio ("") para não identificar
  40. $bot->server = "irc.freenode.net"; // Servidor
  41. $bot->porta = 6667; // porta
  42. $bot->owner = "owner"; // nick do owner
  43. $bot->me = "bot"; // nick do bot
  44. $bot->username = "phpbot"; // username do bot (nick!username@end)
  45. $bot->realname = "PHPbot por infos"; // nome do bot
  46. $bot->canais = "#ecart"; // canais para entrar ao conectar
  47. $bot->quitmsg = "Requested."; // mensagem padrão de quit
  48. $bot->modes = "+p"; // Modos postos pelo bot ao conectar.. deixe vazio ("") para não setar
  49. $bot->reconectar = true; // reconectar ao perder conexão?
  50. $bot->visual = true; // Bot com visual?
  51. // 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).
  52. // 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.
  53. class bot {
  54. function conectar() {
  55. // abre o socket, dá erro de falhar
  56. $this->fp=@fsockopen($this->server ,$this->porta,$erro,$ermsg) or die("Erro ao abrir o socket. Erro $erro: $ermsg ".$this->server.":".$this->porta."</font>");
  57. if ($this->visual) {
  58. echo "Conectado...";
  59. flush();
  60. }
  61. }
  62. function logar() {
  63. // seta o username, modo de usuário e realname
  64. $this->enviar("USER ".$this->username." 0 * :".$this->realname);
  65. // seta o nick
  66. $this->enviar("NICK ".$this->me);
  67. // identifica o nick
  68. if ($this->senha != "") $this->enviar("nickserv identify ".$this->senha);
  69. // se foi especificado algum modo, ele seta
  70. if ($this->modes != "") $this->enviar("MODE ".$this->me." ".$this->modes);
  71. }
  72. function desconectar() {
  73. // Fui desconectado
  74. // Tira a flags pra reconectar (?) exibe desconectar no log e no navegador
  75. $this->log("-> Desconectado", "","<br>");
  76. fclose($this->fp); fclose($this->log);
  77. }
  78. function quit($q = null) {
  79. // 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..
  80. $this->reconectar=false;
  81. if ($q != null) $this->enviar("QUIT :".$q);
  82. else $this->enviar("QUIT :".$this->quitmsg);
  83. sleep(1);
  84. fclose($this->fp); fclose($this->log); die("</font>");
  85. }
  86. function enviar($texto) {
  87. // envia um comando ao servidor, e chama o comando pra logar a mensagem
  88. fputs($this->fp, $texto."\r\n");
  89. $this->log("-> ".$texto);
  90. }
  91. function log($texto, $pre = "", $suf = "") {
  92. // exibe o parametro no log e no navegador
  93. // $pre eh para ser utilizado coisas como, cores, etc..
  94. // $suf para fechar as tags
  95. fwrite($this->log,$texto."\n");
  96. if ($this->visual) {
  97. echo "<br>".$pre."(".date("H:i:s").") ".$texto.$suf;
  98. flush();
  99. }
  100. }
  101. function rodar() {
  102. // enquanto tiver setado para permanecer o bot conectado
  103. while ($this->reconectar) {
  104. // abre o log
  105. $this->log=fopen('Bot.log','a');
  106. // conecta
  107. $this->conectar();
  108. sleep(1);
  109. // envia os parametros da conexão
  110. $this->logar();
  111. // entra nos canais especificados automaticamente
  112. $this->join($this->canais);
  113. $timea=time(); // para o timer (leia sobre ele mais em baixo)
  114.  
  115. // 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)
  116. stream_set_timeout($this->fp,300);
  117.  
  118. // enquanto a conexão estiver ativa, pega o texto recebido
  119. while (!feof($this->fp)) {
  120. $t=fgets($this->fp);
  121. // limpa as quebras de linha
  122. $t=trim($t);
  123. // divide ele num array para tratamento
  124. $q=explode(" ",$t);
  125. // pega o host do user (user!username@address)
  126. $host=substr($q[0],1);
  127. // pega o host
  128. $nick=explode("!",$host);
  129. $nick=$nick[0];
  130. // seta vazio para não pegar valores passados
  131. $msg="";
  132. // se o parametro for notice ou privmsg (mensagem)
  133. if (($q[1] == "NOTICE") || ($q[1] == "PRIVMSG")) {
  134. // se for canal, seta o nome do canal
  135. if (substr($q[2],0,1) == "#") $onde=$q[2];
  136. // se for pvt, seta pvt
  137. else $onde="PVT";
  138. }
  139. // se nao for mensagem ou notice, seta NONE pra não chamar o evento que vai ver se tem algum comando "chamado"
  140. else $onde="NONE";
  141. // limpa a string (?)
  142. $q[3]=trim($q[3]);
  143. // se a string tiver : no início, ele tira (parametros com mais de 1 palavra vem precedidos de ":")
  144. if (substr($q[3],0,1) == ":") $q[3]=substr($q[3],1);
  145. // $q[3] no caso seria !join em "!join canal balblabla"
  146.  
  147. // para x=4 (início dos parametros) até o fim dele, seta tudo numa variavel
  148. for ($x=4;$x <= count($q);$x++) $msg .= " ".$q[$x];
  149. // limpa a mensagem de espaços e quebras de linha (eles ocorrerão)
  150. $msg=trim($msg);
  151. // mensagem total..
  152. $msgt = trim($q[3]." ".$msg);
  153.  
  154. // INÍCIO DO TIMER (leia abaixo nos comandos sobre ele..)
  155. // $timea é a ultima vez que eu recebi um pacote! (se voce leu sobre ele abaixo, saberá do que se trata)
  156. // entao eu vou testando segundo por segundo o $timea até o time() atual
  157. // buscando ver todos os timers (inclusive os atrazados..)
  158. for($time=time();$timea <= $time; $timea++) {
  159. // como todo array tem que começar com uma letra, a + tempo_procurado é o valor do array que eu vou buscar
  160. $timeb="a".$timea;
  161. // Para cada valor do array
  162. foreach($this->vtimer as $chave => $ok) {
  163. // se o nome da chave for igual ao tempo procurado
  164. if ($chave == $timeb) {
  165. // executamos os comandos pedidos...
  166. foreach ($ok as $comando) {
  167. $this->$comando();
  168. }
  169. }
  170. }
  171. // apagamos a variavel para não gastar memoria atoa..
  172. unset($this->vtimer[$timeb]);
  173. }
  174. // tempo do ultimo pacote para usar no timer
  175. $timea=time();
  176.  
  177. // Início da parte de logs (no navegador e arquivo)
  178.  
  179. // EVENTO JOIN
  180. if ($q[1] == "JOIN") $this->log("--> Entrou ".substr($q[2],1).": ".$nick." (".$host.")","<font color=\"red\">","</font>");
  181.  
  182. // EVENTO PART
  183. elseif ($q[1] == "PART") $this->log("--> Saiu ".$q[2].": ".$nick." (".$host.")","<font color=\"red\">","</font>");
  184.  
  185. // O servidor manda eventos "NOTICE" simples.. como NOTICE :*** AUTH blablabla..
  186. // loga normalmente como vem do servidor
  187. elseif ($q[0] == "NOTICE") $this->log($t);
  188. // Se for setado algum modo
  189. elseif ($q[1] == "MODE") $this->log("---> MODE ".$q[2]." ".$q[3]." ".$msg);
  190. // Se alguém muda de nick
  191. elseif ($q[1] == "NICK") $this->log("---> ".$nick." mudou o nick para: ".substr($q[2],1));
  192. // Se alguém desconectou
  193. elseif ($q[1] == "QUIT") $this->log("---> QUIT ".$nick.": ".substr($t,strpos($t,"QUIT")+6),"<font color=\"gray\">","</font>");
  194. // Se foi mudado o topico
  195. elseif ($q[1] == "TOPIC") $this->log("---> ".$nick." mudou o topico de ".$q[2]." para: ".$msgt);
  196. // Se foi recebida alguma mensagem (sintaxe: [nick\onde] texto) onde "onde" é PVT ou o nome do canal
  197. elseif ($q[1] == "PRIVMSG") $this->log("(".$nick."\\".$onde.") ".$msgt,"<font color=\"blue\">","</font>");
  198. // Se foi recebido algum notice (sintaxe: [nick\onde] texto) onde "onde" é PVT ou o nome do canal
  199. elseif ($q[1] == "NOTICE") $this->log("[".$nick."\\".$onde."] ".$msgt,"<font color=\"blue\">","</font>");
  200. // 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..
  201. elseif (trim($msgt) == "") $this->log("-SERVER- ".$t);
  202. // mensagens do servidor normais (outras raws, motd, etc)
  203. else $this->log("-SERVER- ".$msgt);
  204. // se recebi um PING (mensagem do servidor pra ver se o cliente esta ativo e não caiu) ele manda sua resposta
  205. if ($q[0] == "PING") $this->enviar("PONG ".$q[1]);
  206. // Identifique o nick, caso o nickserv peça
  207. 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);
  208. // se $ONDE for diferente de none (onde eh none quando o texto recebido não é de mensagem ou notice)
  209. if ($onde != "NONE") {
  210. // verifica aqui se o comando "pego" ($q[3]) existe na lista de comandos a executar uma função..
  211. $array=$this->comandos[strtoupper($q[3])];
  212. $ondec=$this->comandos[strtoupper("onde".$q[3])];
  213. if ((strtoupper($onde) == strtoupper($ondec)) || (substr(strtoupper($onde),0,1) == strtoupper($ondec)) || (strtoupper($ondec) == "ALL")) $this->$array($nick, $host, $msg, $msgt, $onde);
  214. // (acima) se para o comando, existir uma função, ela é chamada
  215. }
  216. // 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)
  217. stream_set_timeout($this->fp,300);
  218. }
  219.  
  220. // Fui desconectado!
  221. $this->desconectar();
  222. }
  223. }
  224. function novocmd($cmd = null, $ativ = null, $onde = "all") {
  225. // Função que adiciona os comandos à "lista de comandos a executar uma função"
  226. // se existir um comando E um ativador
  227. if (($cmd != null) && ($ativ != null)) {
  228. // $x recebe $this (objeto, @new bot) e o comando
  229. $x=array($this,$cmd);
  230. // se a função existe (para evitar futuros erros..) ele adiciona no array da lista de funções
  231. if (is_callable($x,false)) $this->comandos=array_merge($this->comandos, array(strtoupper($ativ) => strtoupper($cmd), strtoupper("onde".$ativ) => strtoupper($onde)));
  232. // Se não existir, ele cancela o processo pra evitar erros futuros
  233. else die("Você não pode definir um comando com uma função inexistente! (função: ".$cmd.")</font>");
  234. }
  235. else $this->log("Erro na adição de um novo comando! -COMANDO IGNORADO- Comando a ser executado: ".$cmd." Ativador: ".$ativ);
  236. }
  237. function timer($cmd = null, $tempo = null) {
  238. if (($cmd != null) && ($tempo != null) && (is_int($tempo))) {
  239. $x=array($this,$cmd);
  240. $tempo = (string) "a".intval($tempo+time());
  241. if (is_callable($x,false)) {
  242. $this->vtimer=array_merge($this->vtimer, array($tempo => array_merge($this->vtime[$tempo], array($cmd))));
  243. }
  244. else die("Você não pode definir um comando com uma função inexistente! (função: ".$cmd.")</font>");
  245. }
  246. else $this->log("Erro no timer! -TIMER IGNORADO- Comando a ser executado: ".$cmd);
  247. }
  248.  
  249. // funções básicas..
  250. // Sintaxe delas: $onde $quem/$msg/$host/$nick/$canais $modo $tipo
  251. // nem todas recebem todas as variaveis..
  252. function msg($onde = null, $msg = null) {
  253. // se existir um lugar e existir uma mensagem
  254. // envia a mensagem para o lugar
  255. if (($onde != null) && ($msg != null)) $this->enviar("PRIVMSG ".$onde." :".$msg);
  256. }
  257. function emote($onde = null, $msg = null) {
  258. // se existir um lugar e existir uma mensagem
  259. // envia a ação para o lugar
  260. if (($onde != null) && ($msg != null)) $this->enviar("PRIVMSG ".$onde." :ACTION".$msg);
  261. }
  262. function notice($onde = null, $msg = null) {
  263. // se existir um lugar e existir uma mensagem
  264. // envia a mensagem para o lugar
  265. if (($onde != null) && ($msg != null)) $this->enviar("NOTICE ".$onde." :".$msg);
  266. }
  267. function op($onde = null, $quem = null) {
  268. // se existir o lugar e alguém
  269. // dá op para o usuário no canal especificado
  270. if (($onde != null) && ($quem != null)) $this->mode($onde, $quem, "-v");
  271. }
  272. function deop($onde = null, $quem = null) {
  273. // se existir o lugar e alguém
  274. // tira o op do usuario no canal especificado
  275. if (($onde != null) && ($quem != null)) $this->mode($onde, $quem, "-v");
  276. }
  277. function voice($onde = null, $quem = null) {
  278. // se existir o lugar e alguém
  279. // dá voice para o usuário no canal especificado
  280. if (($onde != null) && ($quem != null)) $this->mode($onde, $quem, "-v");
  281. }
  282. function devoice($onde = null, $quem = null) {
  283. // se existir o lugar e alguém
  284. // tira o voice do usuario no canal especificado
  285. if (($onde != null) && ($quem != null)) $this->mode($onde, $quem, "-v");
  286. }
  287. function ban($onde = null, $host = null) {
  288. // se existir o lugar e alguém
  289. // bane a !!MASCARA!! do canal
  290. if (($onde != null) && ($quem != null)) $this->mode($onde, $quem, "+b");
  291. }
  292. function nick($nick) {
  293. // se o nick desejado for diferente do atual, muda..
  294. if (($nick != null) && (strtoupper($nick) != strtoupper($this->me))) $this->enviar("NICK ".$nick);
  295. }
  296. function kick($onde = null, $quem = null, $motivo = "Requested") {
  297. // se existir o local e a pessoa
  298. // kicka ela do canal com o motivo solicitado (ou o padrao)
  299. if (($onde != null) && ($quem != null)) $this->enviar("KICK ".$onde." ".$quem." :".$motivo);
  300. }
  301. function join($canais = "") {
  302. // se existir os canais
  303. // entra em todos os canais separados por um " " (espaço)
  304. if ($canais != "") {
  305. $canais=explode(" ",$canais);
  306. foreach($canais as $x) $this->enviar("JOIN ".$x);
  307. }
  308. }
  309. function part($canais = "") {
  310. // se existir os canais
  311. // sai de todos os canais separados por um " " (espaço)
  312. if ($canais != "") {
  313. $canais=explode(" ",$canais);
  314. foreach($canais as $x) $this->enviar("PART ".$x);
  315. }
  316. }
  317. function mode($onde = null, $quem = null, $modo = null, $tipo = 0) {
  318. // $tipo = 0 quando eu vou setar todos os "+b-x+z" pela variavel $modo
  319. // $tipo = 1 (default) eu vou utilizar $modo = "+b"
  320. // e $quem = "eu1 eu2 eu3"
  321. // e a funcao vai, automaticamente, ir setando os outros "+b" para todos da lista.. (soh funciona pra setar um unico modo..)
  322. // se existir lugar, alguem e modo
  323. if (($onde != null) && ($quem != null) && ($modo != null)) {
  324. // se os modos ja estao setados pela variavel $modo, seta os modos
  325. if ($tipo == 0) $this->enviar("MODE ".$onde." ".$modo." ".$quem);
  326. // se nao, ele ve quantos usuarios sao, e executa o modo em todos..
  327. else {
  328. $qtd=explode(" ",$quem);
  329. $qtd=count($qtd);
  330. $this->enviar("MODE ".$onde." ".$modo.str_repeat(substr($modo,1,1), $qtd-1)." ".$quem);
  331. }
  332. }
  333. }
  334.  
  335. // comandos pré-definidos, veja abaixo do que se trata
  336. function _mensagem($nick, $host, $msg, $msgt) {
  337. if (strtoupper($nick) == strtoupper($this->owner)) $this->msg("#aow_shard",$msg);
  338. }
  339. function _emote($nick, $host, $msg, $msgt) {
  340. if (strtoupper($nick) == strtoupper($this->owner)) $this->emote("#aow_shard",$msg);
  341. }
  342. function _op($nick, $host, $msg, $msgt, $onde) {
  343. if (strtoupper($nick) == strtoupper($this->owner)) $this->mode($onde, $nick, "+o");
  344. }
  345. function _part($nick, $host, $msg, $msgt) {
  346. if (strtoupper($nick) == strtoupper($this->owner)) $this->part($msg);
  347. }
  348. function _join($nick, $host, $msg, $msgt) {
  349. if (strtoupper($nick) == strtoupper($this->owner)) $this->join($msg);
  350. }
  351. function _nick($nick, $host, $msg, $msgt) {
  352. if (strtoupper($nick) == strtoupper($this->owner)) $this->nick($msg);
  353. }
  354. function _quit($nick, $host, $msg = null, $msgt) {
  355. if (strtoupper($nick) == strtoupper($this->owner)) {
  356. if ($msg != "") $this->quit($msg);
  357. else $this->quit($this->quitmsg); }
  358. }
  359. function __msg1() {
  360. return "msg1;
  361. }
  362. function __msg2() {
  363. return "msg2;
  364. }
  365. function __msg3() {
  366. return "msg3";
  367. }
  368. function __msg4() {
  369. return "msg4";
  370. }
  371. function __msg5() {
  372. return "msg5";
  373. }
  374. function __msg6() {
  375. return "msg6";
  376. }
  377. function __msg7() {
  378. return "msg7";
  379. }
  380. function _taow() {
  381. $cmd="__msg".rand(1,7);
  382. $this->msg("#canal", $this->$cmd());
  383. $this->timer("_taow", 300);
  384. }
  385. }
  386. // Adiciona novos comandos
  387. // sintaxe novocmd(funcao a ser chamada, ativador, onde);
  388. // se onde nao for especificado, é chamado em todos os lugares (canais e pvts)
  389. // se onde = pvt, só é chamado no pvt
  390. // se onde = #canal, só é chamado no canal em questão
  391. // se onde = #, é chamado em qualquer canal
  392. // a funcao deve ser criada na classe BOT para que funcione corretamente
  393. // e deve ser declarada antes da função rodar()
  394. // TODAS as funcoes devem receber como parâmetros:
  395. // $nick, $host, $msg, $msgt, $onde
  396. // ex: function _funcao($nick, $host, $msg, $msgt, $onde)
  397. $bot->novocmd("_mensagem","!msg","pvt");
  398. $bot->novocmd("_emote","!me","#canal");
  399. $bot->novocmd("_quit","!quit");
  400. $bot->novocmd("_part","!part");
  401. $bot->novocmd("_nick","!nick");
  402. $bot->novocmd("_op","!op","#");
  403. $bot->novocmd("_join","!join");
  404.  
  405. // Breve descrição sobre o timer:
  406. // O timer PERFEITO em php neste caso é algo meio impossível de se fazer
  407. // Pois o PHP não suporta threads e não posso fazer 2 whiles rodar em paralelo...
  408. // Um, no caso fazendo o papel do timer e o outro o papel do bot
  409. // Porquê não fez tudo junto e deu certo?
  410. // Simples! A função utilizada para receber um dado (socket) pára a execução do script
  411. // até receber algum dado.. Ou seja, ele pode demorar 1 segundo para receber um dado
  412. // do servidor, assim como pode demorar 5 minutos...
  413. // Felizmente eu utilizei o artifício do servidor mandar em intervalos de cerca de 2 minutos
  414. // o dado "PING" (pelo tempo que eu verifiquei na ocasiao era isto, agora verificando melhor,
  415. // pode ser muito maior que 5 segundos, bem variavel) para verificar se o cliente
  416. // está conectado e assim consigo fazer um timer "que atraza"
  417. // Então eu fiz uma simulação de timer.. Como funciona?
  418. // Depois de X -SEGUNDOS-, assim que o BOT receber um dado do servidor, ele VAI
  419. // executar o comando desejado no timer.. Sendo esse tempo de, no máximo, o valor de
  420. // intervalo entre 2 "PING"s enviados pelo servidor.. esse tempo varia, mas não muito
  421. // Ainda não foi implementado algo que faça o timer rodar por X vezes (ou infinitamente)..
  422. // mas é algo facilmente adicionavel.. é só fazer que a função chamada no timer chame
  423. // outro timer....
  424. // IMPORTANTE: o timer é chamado -ANTES- de verificar se a mensagem tem algum comando..
  425. // Assim, se o timer atrazar, e você tiver um timer que cancele um comando, poderá
  426. // faze-lo normalmente..
  427.  
  428. // neste exemplo, depois de 60 segundos ele ativa um timer que fala
  429. // algo aleatorio no canal a cada 5 minutos
  430. $bot->timer("_taow", 60);
  431.  
  432.  
  433. $bot->rodar();
  434. $bot->desconectar();
  435. ?></font>
Add Comment
Please, Sign In to add comment