UOLbot - interface Perl para bate-papo do UOL
Teoricamente, todos onde roda o perl. Oficialmente, foi testado em:
Linux (perl 5.6.1)
Windows (ActivePerl 5.6.1 Build 632)
#!/usr/bin/perl
use UOLbot;
my $bot = new UOLbot (Nick => 'uolbot');
$bot->login ('batepapo4.uol.com.br:3999');
$bot->send ("Hello World!");
$bot->logout;
exit;
O UOLbot
é um módulo Perl que implementa interface para webchat (batepapo) do UOL (http://www.uol.com.br/). Basicamente, a idéia é poder acessar as funções comunicativas do chat de fora do navegador. No caso, à partir de um programa escrito em Perl. Um detalhe em destaque: a intenção é implementar interface completa. Por exemplo, clientes tais como Jane, UOLME e Chat-Nóia 666 implementam só um pouco à mais do que parte interativa. "O grosso" do trabalho em tais clientes é feito pelas DLLs do Internet Explorer
. Já o UOLbot
é independente de Internet Explorer
assim como é independente do Windows
como todo.
Então, conforme o próprio nome diz, você pode escrever bots de propaganda (robôs de propaganda que andam de sala em sala enchendo o saco das pessoas) utilizando UOLbot
. Você também pode fazer algo útil como o primeiro cliente de batepapo UOL que seja cross-platform. Fiz de tudo para tais tarefas sejam mais simplificadas possíveis, apenas repare no exemplo acima ;)
Bom, qualquer coisa, esse projeto está quase sempre em expansão. Comecei aplicando uma engenharia reversa para saber como o Microsoft Internet Explorer 6.0 interage com servidores do UOL (sim, a lógica de operação é do IE do começo ao fim), e atualmente tenho em mãos um módulo orientado à objetos (híbrido, para ser honesto) que faz virtualmente tudo o que você faria num webchat.
Obs: antes que me pergunte, "eu estou lendo em português aqui, então por que send
e não enviar, ou logout
ao invés de sair?" A razão é simples: o "resto" do perl está em inglês, certo? Por mim, fica estranho ler e entender o que faz algo como
next if $bot->enviar and not scalar $bot->usuarios;
Agora, o princípio ativo. Antes de tudo, você deve criar uma instância do bot:
my $bot = new UOLbot (Nick => 'uolbot');
O parâmetro Nick especifica o nickname do bot. Você pode passar outros, que serão descritos posteriormente. Você também pode não passar nenhum, aí o seu bot será um discreto "unnamed". Você pode ter várias instâncias, só não sei qual o sentido disso. Vários robôs para várias salas em um só programa?
Pronto, você criou o seu bot... E agora? Ele deve entrar numa sala, né?
$bot->login ('batepapo4.uol.com.br:3999');
(ótima sala para propaganda, eheheh) Aí você passa a URL da sala. É o único parâmetro necessário. É claro que ter que saber essa URL é um pé no saco, você pode entrar na sala só sabendo o seu nome/número. Mas isso é para depois.
Opa, mas espere um pouco. Você já deve ter percebido aqueles códigos de verificação anti-spam, né (antes não existia isso não)... O que fazer agora? NADA. Lhes apresento orgulhosamente o UOL::OCR
!!! É um sub-componente composto por filtros digitais de imagem e um programa de OCR (Optical Character Recognition), atualmente o jocr
(http://jocr.sourceforge.net). Tal componente trata dos códigos de verificação para você, e aparentemente muito bem ;)
Bom, e estando na sala, o que fazer? Falar!
$bot->send ("Hello World!");
"Oi mundo" :P
Sem comentários aqui.
Quando você "falou" tudo o que quis, tchau para todos!
$bot->logout;
Isso é o básico. Se não entendeu, pare por aqui.
LWP - The World-Wide Web library for Perl (libwww-perl)
Image::Magick (opcional)
new ([ARGS])
-
Construtor para o bot. Retorna a referência para objeto
UOL::bot
. ArgumentosARGS
devem ser passados em forma:new (Chave1 => 'valor1', Chave2 => 2);
Note que alguns dos argumentos você poderá alterar posteriormente com métodos apropriados, e outros não. Argumentos válidos (todos opcionais):
- UA
-
referência para objeto
LWP::UserAgent
externo (é criada instância interna por default) - Nick
-
o nickname (valor default é "unnamed")
- Color
-
a cor do nickname (valor default é 0)
Obs: valores possíveis são:
0 - Preto 1 - Vermelho 2 - Verde 3 - Azul 4 - Laranja 5 - Cinza 6 - Roxo
- Avatar
-
define "carinha" na frente do nick (número inteiro, para ser descoberto na tentativa e erro :(
Obs: a "carinha" só vai aparecer se você for autenticado com
auth
!Obs2: pra tirar a "carinha" já definida, chame
$bot->avatar (-1)
. - Fast
-
se setado em 1 faz
UOLbot
pular passos desnecessários de autenticação/login na sala. Pode fazer diferença em conexões lentas, porém pode gerar incompatibilidades, cuidado ao usar! - Tries
-
número de tentativas para processar/reentrar código de verificação. Tenha em mente que o OCR embutido pode errar para algum tipo de fonte/fundo/texto, porém quem sabe se na próxima ele acerta? Default é 3.
- Auth_Magic
-
preconfigura o cookie mágico que UOL utiliza para saber se o usuário é registrado. Uma boa idéia é não tocar nisso, se quiser experimentar, primeiro dê um
auth
com login/senha válidos, depois dê umprint $bot->auth_magic, "\n";
depois copie o que for impresso e cole no
my $bot = new UOLbot (Auth_Magic => ...);
- ImgCode_Handler
-
referência para a rotina que vai processar a imagem com código de verificação. A minha sugestão é que você não toque nisso. O default é tentar carregar um OCR aqui, se falhar, então a URL da imagem com código de verificação é impressa e você (usuário) tem que ler/digitar... Argh. De qualquer forma, a sintaxe é:
ImgCode_Handler => \&my_imgcode_handler ... sub my_imgcode_handler { my ($req, $ua) = @_; # $req é istância HTTP::Request # $ua é instância LWP::UserAgent my $resp = $ua->request ($req); ... return $code; }
No caso:
$req é instância
HTTP::Request
da imagem-código $ua é instânciaLWP::UserAgent
atualmente usada peloUOLbot
$code é código de 4 caracteres [a-z0-9] - Listen_Handler
-
referência para a rotina que vai processar as informações recebidas da sala (indefinido por default). Por exemplo:
Listen_Handler => sub { print $_[0] }
imprime qualquer coisa recebida e
Listen_Handler => \&listen_handler ... sub listen_handler { my $data = shift; ... return; }
define a sub-rotina listen_handler como handler de 'escuta'. Nesse caso, variável $data recebe pacotes com código HTML recebidos.
Obs: lembre que nem sempre há uma mensagem em um pacote. O servidor (ou buffer do sistema operacional) pode juntar vários pacotes num só.
Os métodos do UOLbot
são:
ua
nick
color
avatar
fast
tries
auth_magic
imgcode_handler
listen_handler
-
Métodos para ler/definir os parâmetros definidos pelo
new
.Obs: Você pode ler os valores a qualquer momento, mas só poderá definir quando a instância não estiver logada com
login
! list_subgrp (SUBGRP)
-
Enumera as salas de bate-papo de um sub-grupo
SUBGRP
. O tal sub-grupo é o documento onde nomes das salas, suas URLs e suas lotações são fornecidos.list_subgrp
é simplesmente uma interface para esse documento. ParâmetroSUBGRP
é uma string com URL de formato 'http://batepapo.uol.com.br/bp/excgi/salas_new.cgi?ID=idim_he.conf' ou então simplesmente 'idim_he.conf'. Os dois são equivalentes. Quando você usalist_subgrp
antes delogin
,SUBGRP
é salvo e utilizado comoREF
delogin
automaticamente. O método retorna um array de hashes se tiver sucesso e () se houver falha. O array retornado pode ser expandido com:my @room = $bot->list_subgrp ('idim_he.conf'); foreach $room (@room) { print $room->{URL}, "\n", $room->{Title}, "\n", $room->{Load}, "\n\n"; }
onde
URL
é a URL da sala de bate-papo,Title
é o título dela eLoad
é o número de pessoas na sala (0-40, -1 significa "sala lotada"). search (STRING)
-
Busca por usuário com
STRING
contido no nickname em todas as salas. Retorna () caso nenhum seja encontrado ou array semelhante ao dolist_subgrp
:my @room = $bot->search ('uolbot'); foreach $room (@room) { print $room->{Nick}, "\n", $room->{URL}, "\n", $room->{Title}, "\n", $room->{Load}, "\n\n"; }
Onde Nick refere o nickname completo do usuário encontrado, URL é o endereço da sala onde o usuário atualmente se encontra, Title é o título da mesma (cortado, foi mal) e Load é quantidade de pessoas presentes na mesma sala.
brief (ROOM)
-
"Espia" na sala sem entrar nela. Retorna 0 se falha. Caso tiver sucesso,
guarda a lista com nomes de usuários para depois ser vista com
users
passa o fragmento da conversa para rotina definida em
Listen_Handler
retorna 1
auth ([USER, PASS])
-
Autentica usuário registrado. Permite entrar nas salas com mais de 30 pessoas e usar "carinha" na frente do nick.
USER
é o nome de usuário em forma '[email protected]' ePASS
é a senha. Agora, o mais velho hack de sistema de chat... OmitaUSER
ePASS
e terás todos os privilégios de um usuário registrado sem ser um ;)Retorna 0 se houver falha (username/senha inválidos) e 1 se tiver sucesso.
Obs: você deve autenticar antes de efetuar
login
!Obs2:
auth
utiliza conexão encriptada via SSL automaticamente quando o móduloCrypt::SSLeay
é encontrado no sistema. Sem esse módulo, a conexão efetuada é insegura e a senha pode ser vista por pessoas mal-intencionadas! Duvido muito, mas o que custa fazer direito?! login (ROOM [, REF])
-
Efetua login na sala
ROOM
de bate-papo. Chama internamente imgcode_handler. ParâmetroROOM
consiste de uma string de formato"http://batepapo4.uol.com.br:3999/"
. Se você for preguiçoso como eu, pode usar"batepapo4.uol.com.br:3999"
apenas. ParâmetroREF
, opcional, é o Referer, o documento que continha o link paraROOM
. Se você omitir oREF
, valor 'http://batepapo.uol.com.br/bp/excgi/salas_new.shl' será usado automaticamente. Se você estiver usadolist_subgrp
ousearch
antes delogin
, a URL de sub-grupo listado será usada comoREF
. Leia mais sobrelist_subgrp
/search
.Retorna 0 se houver falha e 1 se tiver sucesso. A "falha" mais provável é que a sala esteja cheia. Utilize o
login_error
para obter mais detalhes sobre a falha ocorrida. is_logged
-
Retorna não-0 se o bot estiver atualmente numa sala de bate-papo e 0 caso contrário.
Detalhes Técnicos: Para ser exato, retorna o número de tentativas de efetuar a verificação.
encode
-
Retorna a parte "encriptada" da URL da última imagem processada contendo código de verificação.
decode
-
Retorna o código lido.
is_auth
-
Retorna 1 se o bot estiver autenticado como usuário registrado do UOL.
login_error
-
Retorna o código do erro durante login:
0 - sucesso 1 - nickname já foi utilizado 2 - sala está cheia 3 - código de verificação incorreto undef - erro desconhecido (ver valor de $!)
users
-
Retorna array de nicknames de usuários atualmente presentes na sala de bate-papo. Os dados são atualizados toda vez que você efetua
login
,send
oubrief
. Desculpe, não fui eu quem inventou isso... Retorna no mínimo o próprio nickname (a sala não está vazia se você está lá;)
ou () no caso de falha. Detalhe: se você usoubrief
, a sala pode estar vazia portando () não significa erro. send ([MSG] [, ATTR])
-
Envia mensagem
MSG
para sala de bate-papo. Possui 4 sintaxes:-
$bot->send ('mensagem 1');
a mais simples, envia string 'mensagem 1'
-
$bot->send ('mensagem 2', To => 'TODOS', Action => 15);
envia string 'mensagem 2' com atributos
To
eAction
explicados abaixo -
$bot->send (Msg => 'mensagem 3', To => 'TODOS', Action => 15);
o mesmo de cima para 'mensagem 3'
-
$bot->send ();
sintaxe mais obscura, não envia nada, apenas atualiza a lista que pode ser obtida com método
users
. De novo, não fui eu quem inventou!
Agora, sobre atributos
ATTR
. São todos opcionais (formaChave => 'Valor'
), aqui está a lista com uma breve explicação:- Msg
-
a mensagem em si, string (só pode ser usado com sintaxe 3, ignorado na sintaxe 2!)
- Action
-
ação, valor inteiro. Ações possíveis:
0 - fala para (default) 1 - pergunta para 2 - responde para 3 - concorda com 4 - discorda de 5 - desculpa-se com 6 - surpreende-se com 7 - murmura para 8 - sorri para 9 - suspira por 10 - flerta com 11 - entusiasma-se com 12 - ri de 13 - dá um fora em 14 - briga com 15 - grita com 16 - xinga 18 - IGNORAR mensagens de 19 - só receber mensagens de 20 - não IGNORAR mais
- To
-
o nickname do receptor da ação Action, string. Valor default é 'TODOS'.
Obs1: não necessariamente é alguém que esteja na sala. Isto é, você pode fazer:
$bot->send ('bots do UOL, uní-vos!', To => 'bots renegados');
desde que não seja uma mensagem reservada (
Reserved => 1
)!Obs2: independentemente do valor do To, todos os usuários da sala irão ler a mensagem. Para mensagens privadas, use Reserved.
- Reserved
-
pode ser 1 ou 0. Quando 1, a mensagem é enviada reservadamente para nickname To. Valor default é 0.
- Sound
-
som a ser enviado, inteiro. Sons possíveis:
0 - nenhum (default) 14 - Ahn??? 15 - Bang! 16 - Banjo 17 - Dinossauro 18 - Fiu-fiu 19 - Ocupado 20 - Oinc 21 - Pigarro 22 - Smack! 23 - Susto 24 - Telefone 25 - Tôlôca 26 - Tosse 07 - Como é? 08 - Não entendi
- Icon
-
ícone a ser enviado, inteiro. Ícones possíveis:
0 - nenhum (default) 38 - Assustado 27 - Bocejo 23 - Careta 30 - Dentuço 18 - Desejo 31 - Eca ! 32 - Gargalhada 33 - Indeciso 34 - Louco 28 - Na praia 35 - Ohhh ! 20 - OK! 36 - Piscada 37 - Raiva 19 - Smack! 21 - Sorriso 26 - Zangado
Retorna 0 se houver falha e 1 se tiver sucesso.
Obs: aparentemente o servidor não aceita mensagens > 200 bytes.
-
scroll (TIMEOUT)
-
Obs: Provavelmente a parte mais chatinha... Mas indispensável se você quer comunicação bidirecional, isto é, o seu bot envia E recebe dados.
O
scroll
visa limpar buffers de entrada e enviar dados para sub-rotina definida emListen_Handler
(leia mais sobre argumentos denew
). Se o listen_handler for omitido então os buffers serão limpos e a rotina retornará sucesso (1). Só retorna 0 se houver quebra inesperada de conexão.O parâmetro
TIMEOUT
é o tempo que oscroll
deva esperar até retornar caso o buffer esteja vazio, em segundos. Resumindo,scroll()
ouscroll(0)
retorna imediatamente (timeout 0).scroll(10)
aguarda 10 segundos pelo dado.scroll(-1)
pausa o programa até que um dado apareça no buffer.O
scroll
é chamado automaticamente pelos métodoslogin
,logout
esend
, portando, não há como o seuListen_Handler
perder algum dado. Porém, se você quiser mais controle, rode umscroll
com timeout razoável sempre que estiver esperando alguma resposta do servidor.Obs: Alguém aí pensou fork? Acredite em mim, não vale a pena! Eu comecei a desenvolver bot bifurcado, com um child para entrada (rodando só
while ($bot->scroll(-1)) { ... }
) e outro para saída (rodando$bot->send(...)
). A sincronização dos dois virou um inferno e o ActivePerl, meu plataforma principal, não era muito amigo do fork. Se você pensar um pouco, verá que o problema em questão é totalmente linear, nunca duas ações são feitas em paralelo. Agora, se você estiver usando plataforma UNIX e não quiser se preocupar onde pôr oscroll
, coloque antes dologin
:$SIG{ALRM} = sub { $bot->scroll; alarm 1 }; alarm 1;
Se você está vendo essa técnica pela 1-a vez, conforme-se com o que já tem.
logout
-
Efetua logout da sala de bate-papo. Retorna 0 se houver falha e 1 se tiver sucesso.
Testei rigorosamente esse módulo, afinal por que a idéia é que um bot rode 24 horas por dia 7 dias por semana sem manutenção.
Porém sempre há coisas que não planejamos afinal, tais como:
organização estranha de módulos/métodos
É resultado dificilmente evitável do progresso do
UOLbot
. Começa-se de um jeito, aí muda-se de idéia e termina de um jeito totalmente diferente. Com certeza você deve estar se perguntando algo do tipo: "mas para quê dar um nick à instância que vai apenas checkar a sala?" ou então: "não seria mais fácil encapsular o endereço da sala emHTTP::Request
por exemplo, afinal vira e mexe aparece URL de um jeito ou de outro!". A pergunta é: a funcionalidade é prejudicada? Caso contrário, para que perder tempo arrumando coisa insignificante, afinal, não é um código para massas ;)incompatibilidade com
Win32
Calma, calma, você pode executar o
UOLbot
num plataformaWin32
. O grande inconveniente é eu não ter o port dojocr
necessário e bibliotecaImage::Magick
para testar funções OCR... Aliás, vi que as vezes há falhas muito estranhas noLWP
. Uma hora tá tudo OK, outra hora não funciona. Eu fiz testes comActivePerl 5.6.1 Build 632
, utilizandoWindows 98
,Windows 98 SE
eWindows XP Professional
. O primeiro e o terceiro não apresentaram falhas, o segundo apresentou raramente. Mas na minha opinião pessoal, eu não confiaria em nada feito pela Micro$oft. Não confiaria nem nos softwares livres rodando em cima de produtos da Micro$oft. Portando, aqui vai uma dica que vai te livrar de muitos problemas: use Linux.tolerância à falhas humanas
O mínimo esperado do usuário é que passe parâmetros corretos; não passe string onde um número é esperado e nem passe expressão regular onde era para pôr referência ao código...
Ainda assim, fiz o necessário para proteger o usuário contra dar um
logout
antes que seja feito umlogin
, portanto não se desanime.utilizar um proxy HTTP
Grande maioria dos proxies públicos (os normalmente utilizados para anonimizar acessos) não deixa conectar nas portas não-HTTP. Nenhuma das salas de bate-papo reside na porta HTTP (80). E então?
Outra coisa... Olha a data desse arquivo. Nessa data UOLbot
estava funcionando, pode ter certeza. Se não está agora, é porque pessoal do UOL alterou o sistema de webchat. Sinto muitíssimo... O que você tem a fazer é ou procurar versão mais atual de UOLbot
ou adaptar o código desse aqui. Não deve ser difícil, fiz código o mais claro e limpo que pude, até comentei tudo (ôôô)!
O mesmo se aplica a qualquer valor ou tabela citados aqui. O UOL muda constantemente o seu sistema de webchat, fazer o quê...
LWP - Library for WWW access in Perl
Vários exemplos distribuídos junto com o módulo:
- simples.pl
-
a aplicação mais simples; listar um sub-grupo, entrar na sala #15, repetir mensagem 5 vezes, sair.
- crawler.pl
-
bot de propaganda; entra em todas as salas nos sub-grupos especificados e deixa uma mensagem.
- list.pl
-
busca em sub-grupos especificados e retorna lista de URLs de salas de bate-papo e seus respectivos títulos.
2.02
1.0 (25/Jan/2002) - primeira versão funcional.
1.1 (09/Fev/2002) - utilizado o
Carp::croak
para erros de usuário e adicionado o métodobrief
. Correções menores na documentação.1.2 (03/Mar/2002) - adicionados métodos
auth
eavatar
(para tirar proveito de ser usuário registrado do UOL ;).1.2a (04/Mar/2002) - atualizações na documentação.
1.3 (27/Mar/2002) - reestruturado o processo de login devido às alterações feitas nos servidores do UOL. Agora você deve dar um
join
na sala escolhida, obter o código de verificação e completar operação comlogin
. Maldição!1.4 (22/Jul/2002) - Código levemente reestruturado para compatibilidade com módulo OCR (para reconhecimento do código de verificação) que estou fazendo. Algumas correções menores também.
2.0 (04/Ago/2002) - Código fortemente reestruturado. Muitas mudanças. Módulo
UOL::OCR
incluído.2.01 (06/Dez/2002) - Correção menor devido à atualização de protocolo nos servidores do UOL.
2.02 (25/Mai/2003) - Arrumado o repentinamente surgido problema com "trailers" de linha. Agora está 100% IE :).
Copyright (C) por Stanislaw Y. Pusep, Janeiro de 2002
A utilização desse módulo, assim como distribuição do módulo e/ou suas versões (alterações feitas no módulo por terceiros) somente deve ser feita com autorização explicita proveniente do autor.
Aqueles que tem cópia autorizada do módulo tem o direito de gerar versões (alterar o módulo conforme for conveniente a eles).
(*)
Qualquer programa feito com utilização desse módulo pode ser usado para quaisquer fins (inclusive lucrativos).
(*)
(*)
-
Desde que não haja infração do
item 1
.
Nome: Stanislaw Y. Pusep
E-Mail: stanis AT linuxmail DOT org
Homepage: http://sysdlabs.hypermart.net/
Hey! The above document had some coding errors, which are explained below:
- Around line 39:
-
Non-ASCII character seen before =encoding in 'DESCRIÇÃO'. Assuming UTF-8