domingo, 3 de maio de 2009

Bot do MSN em Python

Existem muitos serviços de DNS dinâmico, mas eles são atualizados de "tempos em tempos". O ideal seria ter alguém do outro lado pra nos dizer qual é o IP atual. Então, vamos criar um BOT para isso. Já que quase todo mundo usa MSN, vamos usar ele! :D

Primeiro, vamos usar o site http://www.cmyip.com/. Ele foi escolhido porque é o que tem menos "firulas" ao mostrar o IP. O código (arquivo commandos.py):

import httplib
import re

def getIP(msg):
h = httplib.HTTP('www.cmyip.com')
h.putrequest('GET', '/')
h.endheaders()
returncode, returnmsg, headers = h.getreply()
if returncode == 200:
f = h.getfile().readlines()[27].strip()
ip = re.compile('\d+\.\d+\.\d+\.\d+').match(f).group()
return ip
else:
return 'ops! erro interno (%s)! =/' % (returncode)

COMMAND = {
'IP': getIP,
}


Pode testar. É feio pegar a resposta na linha 27, mas funciona! :D

Agora criamos o cliente para o MSN. Usando o pymsn.

O código:

# -*- coding: utf-8 -*-

import pymsn
import pymsn.event

import gobject

import logging
#logging.basicConfig(level=logging.DEBUG) #para DEBUG =]

logging.basicConfig(level=logging.CRITICAL)

ALLOWED_CONTACTS = ('*****@hotmail.com',)

from comandos import COMMAND

# respostas a mudanças de status (do BOT)
class ClientEvents(pymsn.event.ClientEventInterface):
def on_client_state_changed(self, state):
if state == pymsn.event.ClientState.OPEN:
# mudar status para online

self._client.profile.presence_msn_object = pymsn.Presence.ONLINE, None
# definir subnick
self._client.profile.personal_message_current_media = "BOT!!", None

def on_client_error(self, error_type, error):
print "ERROR :", error_type, " ->", error

# respostas a eventos de conversação

class ClientConversation(pymsn.event.ConversationEventInterface):

# ao receber uma mensagem
def on_conversation_message_received(self, sender, message):
self._do(sender.account, message.content)

def _do(self, contact, cmd):
if contact not in ALLOWED_CONTACTS:
msg = "Hello %s! I'm a bot! :D" % contact
fmt = pymsn.TextFormat("Comic Sans MS",
pymsn.TextFormat.UNDERLINE | pymsn.TextFormat.BOLD,
'FF0000')
else:
c = cmd.split(' ')[0]
fmt = pymsn.TextFormat("Comic Sans MS",
pymsn.TextFormat.NO_EFFECT,
'000000')
try:
msg = COMMAND[c](cmd)
except KeyError:
msg = 'Bad command or filename... ;)'

fmt = pymsn.TextFormat("Comic Sans MS",
pymsn.TextFormat.BOLD,
'FF0000')
except:
msg = 'Erro interno... alguma coisa na função'
fmt = pymsn.TextFormat("Comic Sans MS",
pymsn.TextFormat.UNDERLINE | pymsn.TextFormat.BOLD,
'FF0000')

self._client.send_text_message(pymsn.ConversationMessage(msg, fmt))
return True

def on_conversation_error(self, error_type, error):
print "ERROR :", error_type, " ->", error


# "convite" para iniciar uma conversa
class Invite(pymsn.event.InviteEventInterface):
def on_invite_conversation(self, conversation):
self._conversation = ClientConversation(conversation)


class Client(pymsn.Client):
def __init__(self, account):
server = ('messenger.hotmail.com', 1863)
self.account = account

pymsn.Client.__init__(self, server)
self._event_handler = ClientEvents(self)
self._invite_handler = Invite(self)
gobject.idle_add(self._connect)

def _connect(self):
print 'connecting...'

self.login(*self.account)

def main():
import gobject
mainloop = gobject.MainLoop(is_running=True)

# aqui vão os dados da conexão: melhorar!
cl = Client(('bill@hotmail.com', 'Linux@PC'))
cl._connect()
while mainloop.is_running():
mainloop.run()

if __name__ == '__main__':
main()



Pode-se ver algumas validações. No exemplo, só vai responder para a minha conta no MSN. Para os outros, nada. E ainda é possível expandir através do arquivo commandos.py.

Acho que ficou bom. Alguém tem sujestões de aplicações? Lembrem-se que é um protocolo em texto plano, sem nenhum tipo de segurança das informações transmitidas...


Fontes:
http://ubuntuforums.org/showthread.php?t=1052281
arquivo test.py do pacote python-msn :)
http://madpython.com/pymsn/module-tree.html
Minha cabeça e ociosidade

Para deixar o código python legível no blog:
http://aima.cs.berkeley.edu/python/py2html.html (ainda tem que melhorar, precisei alterar o HTML pra poder colocar aqui... mas ajuda)

quarta-feira, 22 de abril de 2009

Oracle, order by e acentos

Problemas acentuação na ordenação oracle?!?

O oracle, por default, ordena primeiros os caracteres sem acentuação, depois os caracteres com acentos. Isso, na maioria das vezes, não é o que a gente precisa.

A solução é uma variável de ambiente, que faz o oracle ignorar os acentos:

NLS_SORT=generic_m_ai

Ou, no conf do Apache:

SetEnv NLS_SORT generic_m_ai

Lembrando que isso faz a ordenação ser também "case insensitive"

Fonte: http://glufke.net/2009/01/08/ignorando-acentos-e-maiusculasminusculas-no-10g/

terça-feira, 14 de abril de 2009

IA: robô com sentimento?!

A Inteligência Artificial evoluiu muito, mas ainda é um mistério a forma como funcionam os sentimentos humanos. Nada impedem pesquisas nesse sentido, claro.

Pesquisadores japoneses - sempre eles - criaram um robô que tinha sentimentos. Só não sei dizer quem confundiu o quê. Apesar disso, garanto que programadores também tem sentimentos...

Só que, num belo dia, o robo tornou-se obsessivo! Não deixou mais a pesquisadora sair da "casa" onde estavam juntos (era um estudo, nada de sacanagem). Bloqueou a porta e a agarrava com abraços e fazia sons animalescos. Só acabou quando ela pediu ajuda para outros pesquisadores, que desligaram o robô através de um botão em suas costas...

Eu fiquei aqui pensando... tem comportamento mais humano do que isso? =P



E se você já assistiu o final, tenha certeza: all this happened before... and it will be happen again!


Fonte: http://www.geek.com.br/blogs/832697632/posts/9488-robo-programado-para-amar-tem-ataque-obsessivo
http://www.muckflash.com/?p=200

segunda-feira, 13 de abril de 2009

Youtube também é educação

Eu achava que o youtube era só perda de tempo/porcarias. Estava errado... Patrocinado por algumas grandes universidades, temos aulas disponíveis online.

Tem uma de física quântica! =D

Agora sim vou me dedicar um pouco a aprender inglês...


Os links para os vídeos estão aqui: http://www.youtube.com/edu

domingo, 12 de abril de 2009

Assembly - goto x,y

No pascal (onde aprendi a programar), existia uma biblioteca que eu não lembro o nome que dava um comando que colocava o cursor em um ponto da tela. Depois, era só escrever que ele colocava o texto ali.

Pois bem, vamos fazer isso em assembly! É um longo código:

.MODEL SMALL
.STACK 200h
.386

.DATA
Message db "Hello World$"

.CODE

;
;Posiciona o cursor em posicao dh (linha) e dl (coluna)
;
posic:
push bx
push ax
mov bh, 0 ;pagina
mov ah, 2 ;numero do servico de BIOS
int 10h ;chama a interrupcao
pop ax
pop bx
ret

escreve:
push ax ;empilhar tudo o que usamos (para nao corromper outro codigo)
push dx
push ds

mov ax, seg Message ;faz a escrita
mov dx, offset Message
mov ds, ax
mov ah, 09h
int 21h

pop ds ;volta tudo o que empilhamos
pop dx
pop ax
ret

Start:
xor dh, dh ;escrever na coordenada 0,0
xor dl, dl
call posic
call escreve

mov dh, 1 ;escreve na coordenada 1,1
mov dl, 1
call posic
call escreve

mov dh, 1 ;escreve a mensagem no fim da primeira linha, em 1,79
mov dl, 79
call posic
call escreve

mov ax, 4c00h ;retorna para o SO (DOS)
int 21h
End Start


Aqui já temos várias coisas novas. O programa é dividido em partes (como funções), que são executadas através de "call".

O que temos de novo aqui é o uso da pilha, identificada através da diretiva:
.STACK 200h

Ela é usada através do push e do pop. Como todas as operações são feitas com os registradores e só temos 4, então precisamos de espaço para guardar os valores. "push" coloca na pilha, "pop" retira dela, sempre usando o registrador passado por parâmetro. Nenhuma validação é feita, então dá pra empilhar ax e ler bx...

Em "posic", você pode ver que a idéia das interrupções é sempre a mesma: empilhar os registradores, setar os que a interrupção vai usar, chamar a interrupção e desempilhar tudo. No fim, o "ret" manda o fluxo de execução (ou seja, o IP - Instruction Pointer) de volta para quem o chamou...

Uma lista de interrupções pode ser encontrada em http://www.emu8086.com/assembly_language_tutorial_assembler_reference/8086_bios_and_dos_interrupts.html
A lista de comandos assembly para os processadores da Intel estão em http://www.intel.com/software/products/compilers/embedded/toolsuite/docs/compiler/assembler/asxscale_p.htm

HP, Microsoft e o notebook - HD Sata, Windows XP e a solução

Encontrei uma solução para o problema que reportei aqui, com o HD Sata e sem drive de disquete.

Usar o NLite (http://www.nliteos.com/) para recriar o CD de instalação do Windows XP. Baixar o driver da controladora SATA do site da HP e usar o programa.

A única coisa que alterei foi adicionar o driver, criar a ISO e gravar o CD (de tão simples o processo, fiz numa máquina virtual com o KVM... hehe).

É simples, permite adicionar atualizações do XP e até o SP3. Realmente interessante, mas não testei nem mesmo 1% da ferramenta.

Fica a ajuda se precisar de novo da solução...

sábado, 11 de abril de 2009

Assembly - hello world

Iniciando uma nova série sobre... assembly! =D

Aos navegantes: um programa simples em assembly para plataforma Intel, que só roda em Windows (o Linux usa arquitetura AT&T).

.MODEL SMALL ;avisamos o montador que não vamos precisar de muita memória (por hora, fica nisso)
.386 ;indica que vamos brincar de ser um 386

.DATA ;indica o segmento de dados
Msg db "Hello World", "$" ;"cria" uma string de bytes (db) chamada Message

.CODE ;indica o segmento de codigo
Start: ;indica o comeco do programa (vc escolhe o nome que quiser)
mov ax, seg Msg ;move o numero do segmento "Msg" para o registrador AX
mov dx, offset Msg ;move o endereço de Msg para o registrador DX
mov ds, ax ;move ax para ds, carregando o segmento de dados
mov ah, 09h ;coloca o nro da interrupcao "DOS" de escrever na tela em AH
int 21h ;chama a interrupcao com o codigo AH

mov ax, 4c00h ;coloca o nro da interrupcao de retorno para o DOS
int 21h ;chama a interrupcao
End Start ;indica o fim do programa


Estamos usando 2 segmentos aqui: DS (ou DATA SEGMENT) e CS (ou CODE SEGMENT). No DS estão os dados (!) e no CS está o código do programa (!!). Temos outros, mas só usamos esses.
As linhas que começam com pontos são diretivas para o montador (assembly não se compila, se monta).

AX é um registrador de uso geral, assim como DX. AX tem 16 bits, que são divididos em 2: AH (8 bits mais significativos) e AL (8 bits menos significativos - à direita). O mesmo vale para DX, que possui DH e DL. Temos outros, mas só usamos esses (no novo).

mov faz uma atribuição. Então, mov ah, 09h significa:
av <- 9h
O "h" depois do número indica que ele é hexadecimal.

int chama uma interrupção de BIOS (Basic Input/Output System) ou de DOS (Disk Operating System). o número depois dela é o código da interrupção.

Por hora é isso... :P