Depois de um grande tempo em standby, eu retomei a minha busca pelo bot concurseiro. Resolvi tentar criar um bot bem simples (@RodrigoLiraBot no Telegram) só para testar a API do telegram.

bot

Para isso eu dei uma olhada no site do próprio Telegram . Nele eu encontrei um módulo para  Python chamada twx.botapi . Sua utilização é bem simples e por isso resolvi usá-la.

A instalação é usando o pip

$ sudo pip install twx.botapi

No próprio do github tem um exemplo que guiou o meu desenvolvimento.

from twx.botapi import TelegramBot, ReplyKeyboardMarkup

"""
Setup the bot
"""

bot = TelegramBot('')
bot.update_bot_info().wait()
print(bot.username)

"""
Send a message to a user
"""
user_id = int()

result = bot.send_message(user_id, 'test message body').wait()
print(result)

"""
Get updates sent to the bot
"""
updates = bot.get_updates().wait()
for update in updates:
    print(update)

"""
Use a custom keyboard
"""
keyboard = [
    ['7', '8', '9'],
    ['4', '5', '6'],
    ['1', '2', '3'],
         ['0']
]
reply_markup = ReplyKeyboardMarkup.create(keyboard)

bot.send_message(user_id, 'please enter a number', reply_markup=reply_markup).wait()

O API TOKEN é um token que é gerado polo BotFather na criação do Bot. Lembrando que isso é uma informação secreta do seu bot. O legal desse exemplo é que ele também mostra como o teclado do bot pode ser customizado para atender a um determinado bot.

Abaixo segue um exemplo de update que é retornado pela função get_updates(). Um update é uma interação com o bot. Ele contém a mensagem e o usuário que realizou a interação.

Update(update_id=194163476, message=Message(message_id=288, sender=User(id=31616677, first_name=u'Rodrigo Lira', last_name=None, username=u'rodrigoclira'), date=1458837621, chat=Chat(id=31616677, type=u'private', title=None, username=u'rodrigoclira', first_name=u'Rodrigo Lira', last_name=None), forward_from=None, forward_date=None, reply_to_message=None, text=u'teste', audio=None, document=None, photo=None, sticker=None, video=None, voice=None, caption=None, contact=None, location=None, new_chat_participant=None, left_chat_participant=None, new_chat_title=None, new_chat_photo=None, delete_chat_photo=None, group_chat_created=None, supergroup_chat_created=None, channel_chat_created=None, migrate_to_chat_id=None, migrate_from_chat_id=None), inline_query=None, chosen_inline_result=None)

No meu caso, eu modifiquei um pouco esse código para criar um bot que fica respondendo sempre a mesma mensagem independente do que foi escrito para ele. A cada 30 segundos, ele responde a quem falou com ele com uma mensagem determinada por mim.

Para evitar mensagens repetidas, eu coloquei uma funcionalidade que evita o envio de mensagem para o mesmo update. A cada resposta do bot é guardada os identificadores das mensagem que foram respondidas usando a biblioteca pickle de Python. Se por acaso o programa for encerrado, o arquivo será lido na sua inicialização. Essa foi a alternativa mais rápida que encontrei mas creio que haja formas melhores de contornar isso.

No momento esse script está sendo executando num servidor que tenho na Dreamhost, mas é possível executar ele em qualquer máquina que tenha acesso a internet. O código do final do @RodrigoLiraBot é o seguinte:


from twx.botapi import TelegramBot, ReplyKeyboardMarkup
from time import sleep
import pickle
from os import path

CURR_PATH = path.dirname(path.realpath(__file__))
DUMP_FILE = path.join(CURR_PATH, "data.pkl")


"""
Configurando o bot
"""

BOTAPI='API_AQUI'
bot = TelegramBot(BOTAPI)
bot.update_bot_info().wait()

print(bot.username)

if path.exists(DUMP_FILE): # Se existe, carregar a lista de mensagens respondidas
    pkl_file = open(DUMP_FILE)
    answered_messages = pickle.load(pkl_file)
else:
    answered_messages = []

bot_message = "Oi, eu sou um bot do http://blog.rodrigolira.net/. Em breve terei mais funcionalidades!"

while (True):
    print ("Getting updates".center(50, '-'))
    
    updates = bot.get_updates().wait()
    for pos, update in enumerate(updates):

        print(str(pos) +" "+  str(update) + "n")

        update_id = update.update_id
        if (update_id not in answered_messages): # Se a mensagem não foi respondida, responda o usuário
            sender_id = update.message.sender.id
            result = bot.send_message(sender_id, bot_message).wait()

            print(result)

            if (result):
                answered_messages.append(update_id)

    output = open(DUMP_FILE, 'wb') 
    pickle.dump(answered_messages, output) # persiste a lista de mensagens respondidas
    sleep(30)

Se você quiser usar com o seu bot simplesmente coloque o APITOKEN recebido na criação dele.
O resultado é algo assim:

bottelegram

| Criando um bot do Telegram (parte 1)
| Criando um bot do Telegram (parte 2)

Resolvi colocar um exemplo para demonstrar o funcionamento
do decorador @classmethod. Como se pode ver na execução,
nesse código, após chamar o método unpack, é criado um novo
objeto do tipo MinhaClasse.


#!/usr/bin/python
# -*- coding: utf-8 -*-

class MinhaClasse:
    def __init__(self, raw, prev):
        print ("Criando a classe MinhaClasse")
        self.raw = raw
        self.prev = prev

    #Método estático unpack
    @classmethod
    def unpack(cls, raw, prev=None):
        print ("Tipo='%s' com o raw='%s' e prev='%s'" % (cls.__name__, raw, prev))
        return cls(raw=raw, prev=prev)

if __name__ == '__main__':
    MinhaClasse.unpack("raw content", "prev content") #Não precisa de instância, o método é chamado como o nome da classe
    #Não precisa informar o valor de cls porque implicitamente ele sabe que deve ser passado o tipo da classe, ou seja "MinhaClasse"

Rodrigo Lira,

Um amigo me mandou um email perguntando uma dúvida sobre um decorator de Python…

@classmethod
def unpack (cls, raw, prev=None):
  return cls(raw=raw, prev=prev)

Pode destrinchar isto para mim? classmethod é uma função built-in do Python. Significa que dentro do método eu substituo cls por classmetho?

Oi,

Segundo o que vi em algumas referências, o @classmethod
é igual ao @staticmethod, ambos são para definir um método estático dentro de uma classe[1][2]. Um método estático não é nada mais que uma função definida dentro de uma classe. Não precisa criar uma instância de uma classe para chamar ele.

Por exemplo, supondo essa classe:

class A:
    def __init__(self):
        pass

    def foo(self):
        pass

    @staticmethod
    def boo():
        pass

O método foo não é estático então deveria ser chamado a partir de uma instância:

obj = A()
# Chamando um método não estático a partir de uma instância
obj.foo()

#Chamando um método estático a partir de uma instância
obj.boo()

Já o método boo é estático então não precisa ser chamado de uma instância, mas pode ser, apesar que não seja uma boa prática.

obj = A()
# Chamando um método estático a partir de uma classe
A.boo()

# Chamando um método não estático a partir de uma classe
A.foo()
Traceback (most recent call last):
File "input", line 1, in
TypeError: unbound method foo() must be called with A instance as first argument
(got nothing instead)

Como pode ver, conseguimos chamar um método estático a partir da classe, mas não um não estático.

Voltando a @classmethod e @staticmethod… O decorador @staticmethod permite criar métodos estáticos e esses métodos não podem ser sobrescritos pelas subclasses. Ele é imutável.

Já os métodos com o decorador @classmethod permite criar métodos estáticos que podem ser sobrescritos pelas subclasses. Isto é porque o primeiro parâmetro das funções que tem o @classmethod tem que ser sempre cls (classe)[3].

Aparentemente esse método que você enviou é uma factory[4]. Métodos que são usados para criar instância de outras classes.

O exemplo que você me enviou:

   @classmethod
   def unpack (cls, raw, prev=None):
       return cls(raw=raw, prev=prev)

Segundo o que eu disse, cls é um tipo de classe e o método retorna uma instância dessa classe no qual é passado os outros dois parâmetros para o construtor dela.

Abraço.

[1] http://jfine-python-classes.readthedocs.org/en/latest/decorators.html
[2] http://stackoverflow.com/questions/12179271/python-classmethod-and-staticmethod-for-beginner
[3] http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python
[4] https://pt.wikipedia.org/wiki/Factory_Method

O meu último post sobre o Bot do Telegram mostrou minha ideia de criar um bot para ser utilizado como coletor de informações de concurso do site PCIConcursos. Desde daquele post não tive tempo livre para finalizar esse meu projeto particular. Contudo, eu consegui encontrar uma ferramenta que me ajudará na implementação desse projeto.

O objetivo desse post é apresentar o “import.io“, um site que  permite transformar uma web page em um repositório de dados. Acabei descobrindo-o visualizando uns slides sobre uma palestra de acesso a dados públicos, eu encontrei esse site.  A palestra a qual me refiro está aqui embaixo:

Bem, a mágica do import.io é transformar uma webpage com um certo padrão de visualização em uma fonte de dados. Então imagine criar uma api para acessar os posts do meu blog. Bem, só imagine porque com o import.io é bem simples. Inclusive, segue o link

https://magic.import.io/?site=http:%2F%2Fblog.rodrigolira.net%2F

Simples, não? Imagine a infinidade de sites que existem que podem ser facilmente exportados para uma API.

https://magic.import.io/?site=http:%2F%2Fwww.hardmob.com.br%2Fpromocoes%2Findex1.html

Você pode editar cada uma das colunas preestabelecidas pelo site. Abaixo segue uma imagem da interface de administração do site. Nesse caso, eu estou usando a url http://www.pciconcursos.com.br/ultimas

importio

Ainda no painel de administração, é possível escolher formas de acesso a base de dados criada.

importio2

No meu caso, eu pretendo que o bot utilize uma API. Por isso eu escolhi mostrar o “Simple API Integration”.  Utilizando o import.io, eu consegui gerar a seguinte fonte de dados para ser consumida (URL encurtada): https://goo.gl/lSgWIq . Através dela, o bot saberá me informar quais são os editais de concursos mais recentes.

Por enquanto, isso é tudo!

| Criando um bot do Telegram parte 3

 

Apresentação criada para o curso de Android do Porto Digital.

Um amigo me perguntou se eu sabia fazer a conversão de docs para PDF de forma automatizada no Linux. Eu disse que não mas que podia dar uma pesquisada rapidamente e fazer algo com shell script. Depois de ler algumas páginas do stack overflow e testar diversas formas de fazer a exportação para PDF, eu encontrei o que me pareceu mais legal. A utilização do libreoffice através da linha de comando.

O resultado foi o seguinte:

doc2PDF.sh


#!/bin/bash
#Author: Rodrigo Lira  

EXCLUDE=".pdf|.sh"

TODAY=`date +'%Y%m%d'`
files=`find . | egrep -v "$EXCLUDE"`

echo $files

if [ ! -z "$files" ] 

then	
	for file in $files
	do
#		name=`echo "$file" | awk -F "." '{ print $2 }'`
		echo "Converting $file"
        soffice --headless --convert-to pdf $file
	done

fi

Para minha surpresa, ele disse que na verdade o problema era transformar código fonte, ou seja arquivos de texto para PDF.
Refiz rapidamente o código para utilizar duas outras ferramentas: o enscript e o ps2pdf. O resultado foi o seguinte:

txt2PDF.sh


#!/bin/bash
#Author: Rodrigo Lira  

INCLUDE=".c$|.sh$|.java"

TODAY=`date +'%Y%m%d'`
files=`find . | egrep "$INCLUDE"`

echo $files

if [ ! -z "$files" ] 

then	
	for file in $files
	do
		name=`echo "$file" | awk -F "." '{ print $2 }'`
		echo "Converting $file"
        #soffice --headless --convert-to pdf $file
        enscript -p .${name}.ps ${file}
        ps2pdf .${name}.ps .${name}.pdf
        rm .${name}.ps
	done

fi

Em ambos, o script apenas convertem os arquivos que estão na mesma pasta dele, mas isso pode ser facilmente modificado.

Rodrigo Lira,


Recentemente,  o Telegram liberou para os desenvolvedores criarem Bots para usar no mensageiro. Bot é um negócio que acho bem legal, inclusive, eu já tinha feito um bot para o tweet em que usei o Google AppEngine. Ele era bem simples, basicamente um script python que usavam o cron e a biblioteca BeutifulSoup, ele postava as notícias do site do Ecomp – curso de Engenharia da Computação da UPE – no Tweet.  Enfim, resolvi me aventurar no desenvolvimento de um bot utilizando a API do Telegram. Vou usar o blog para contar minha saga na criação do meu primeiro bot nesse mensageiro. Isso pode demorar um tempo, talvez nunca ser finalizado, mas vou deixar tudo registrado!

O problema

Desde que acabei o mestrado eu venho olhando quase que diariamente os sites de concurso, na verdade eu só olho o pciconcursos. Minha procura sempre é a mesma, concursos recentes para professor universitário aqui na redondeza de Pernambuco. Meu acesso é bem simples, toda noite eu visualizo a página “Últimas” do site e procuro por concursos para PE, PB ou AL. É simples e mecânico.

A solução

Vendo a possibilidade de criar algo legal com essa API do Telegram, eu corri logo pro BotFather e criei alguns bots. Por enquanto já sou dono do @RodrigoLiraBot, @ConcursoBot, @ConcurseiroBot. Resolvi usar essa minha necessidade de visualizar novos concursos para aprender como manusear com bots do mensageiro.

Bem, já tenho um problema e uma possível solução. Fazer um bot que me informe os concursos recentes e que possa até me informar de alguma novidade que tenha passado despercebido.

Ahh, a forma de criar bots no telegram é bem simples:

  1. Adicione o @BotFather
  2. Escreva: /newbot
  3. Ele pedirá um nome para o seu bot. Escreva o nome.
  4. Se o nome estiver disponível, você terá que adicionar um username. Digite o username.
  5. Você receberá um token de acesso. Agora é só fazer a lógica de comunicação do bot!

Mais informações: https://core.telegram.org/bots/

Quer ver com o um bot funciona? Adiciona o @ImageBot e digita “/get rodrigoclira“.  Voilá. It is me!  😀

Let the game begin!

| Criando um Bot do Telegram (Part 2)

RL,

Java, Como programar

O livro é quase uma lenda para quem aprendeu Java na graduação.
Eu recomendo a compra para aqueles que desejam aprender a programar em Java.

LINK ATUALIZADO:

https://thepiratebay.se/torrent/7481378/Java_Como_Programar_Deitel_8_edicao

Outros livros:
ITBOOKS JAVA

It is really simple debug a shell script.  For instance, if you need to trace all the code, you just need insert the code “set -x” into the code.
Let me show you an example:

#!/bin/bash
set -x

num=3

if [ $num -le 1 ]
then
   echo "if"
else
   echo "else"
fi

OUTPUT
rcls@rcls-notebook:~$ ./test.sh
+ num=3
+ ‘[‘ 3 -le 1 ‘]’
+ echo else
else