Hacer un bot de telegram sin usar ninguna librería de telegram

Entiendo que conoces la aplicación telegram, lleva con nosotros mucho tiempo y, aunque en nuestro país es mucho más usada whatsapp, telegram tiene también sus adeptos, sobre todo para canales de distribución o para uso secundario con aquellos que ya usan esta herramienta.

Una de las características más importantes de esta plataforma es la separación entre usuarios y bots, los usuarios tienen que tener un número de teléfono registrado y no es tan sencillo hacerse con una cuenta adicional si no tienes otro teléfono, la plataforma distingue perfectamente entre personas y bots, que serían los programas a los que solo se permite interacturar con personas que hayan hablado con ellos antes o con canales de distribución a los que se hayan añadido como administradores (antes podían añadirse como miembros, pero esa posibilidad ya no existe). El caso es que llevo un tiempo desarrollando bots para esta plataforma, usando diversas librerías y después de tantear todos los límites de telegram y de las librerías me he visto obligado a ir directo al api de telegram para bots… Y resulta que no solo es sencillo, sino muy sencillo iniciarse en la creación de bots sin ninguna librería adicional… En este caso vamos a crear un bot de cero y sin librerías de por medio.

Pero, como decía Jack el destripador: vayamos por partes…

Lo primero es crear un bot, telegram pone a nuestra disposición el bot llamado botfather que nos permite crear bots asociados a nuestra cuenta (un máximo de 20 por si os sentís tentados de crear armadas de bots) y se crean simplemente con el comando /newbot y responder unas pocas preguntas… Como podemos ver en la imagen:

Lo importante, y fundamental, es el token que nos genera botfather, esto será todo lo que necesitamos para acceder al api, que como bien nos indican está en https://core.telegram.org/bots/api

Lo segundo será decidir en qué lenguaje y para qué plataforma vamos a crear nuestro bot, en nuestro caso y para simplificar las cosas vamos a hacerlo en python que puede correr en cualquier sitio (linux, mac, windows o incluso serverless), en mi caso vamos a crear un bot que, cuando se lo pedimos, nos genere una nueva contraseña (luego ya veremos si queremos mejorarlo). Por cierto, todo el código que generemos aquí estará en el repositorio https://github.com/yoprogramo/nomorepassbot para que podáis usarlo y modificarlo a voluntad.

Hemos dicho que no tendría dependencias de ninguna librería telegram, pero no hemos dicho que no la tuviese de alguna otra, así que es momento de decidir si queremos usar alguna librería http, en mi caso, por simplicidad he elegido la librería httpx, como tampoco quiero ir instalando cosas de más voy a utilizar pipenv para crear mi entorno de trabajo (vosotros podéis hacerlo como queráis)

La lógica del programa será sencilla, simplemente preguntaremos periódicamente a telegram si tenemos updates, y si los tenemos, miraremos a ver si alguna petición contiene la cadena «password» y si la contiene devolveremos una nueva contraseña generada por nosotros en ese momento. Para recuperar los updates haremos un bucle infinito en donde llamaremos a la función getUpdates y si recibimos elementos los recorreremos uno a uno para tratarlos.

La función para generar una contraseña aleatoria será esta:

def generatePassword(num=10):
    # Generamos una contraseña aleatoria de num caracteres
    letras = string.ascii_letters + string.digits
    password = ''.join(random.choice(letras) for i in range(num))
    return password

Lo primero que tenemos que hacer es dar un valor a nuestro token y establecer la url del api de telegram:

token = 'TOKEN'
url_base = f'https://api.telegram.org/bot{token}/'

Y la función que recupera las actualizaciones será, por tanto esta:

r = httpx.get(url_base + 'getUpdates')
    updates = r.json()['result']

La función para enviar un mensaje a un usuario (o a un chat) se llama sendMessage y recibe como parámetros (entre otros) chat_id y text, así que poniendo todo junto nos quedaría esta función:

while True:
    r = httpx.get(url_base + 'getUpdates')
    updates = r.json()['result']
    for update in updates:
        if 'message' in update:
            message = update['message']
            if 'text' in message:
                text = message['text']
                if 'from' in update['message']:
                    user = update['message']['from']
                    if 'password' in text:
                        respuesta = 'La contraseña es ' + generatePassword(10)
                        r = httpx.post(url_base + 'sendMessage', data={'chat_id': user['id'], 'text': respuesta})
                else:
                    continue 
    time.sleep(1) 

Si ejecutamos esto (y tenemos el token que nos ha dado godfather) ya podremos pedir la contraseña y recibiremos respuesta (al hablar con nuestro bot, claro):

Claro que si dejamos el código así el bot se empeñará en darnos contraseñas una detrás de otra sin parar, y es que telegram no sabe si hemos tratado o no el update que nos ha enviado, para ello hay que usar el parámetro offset para indicar cual será la siguiente actualización a tratar y cambiando el código un poco nos quedaría:

offset = 0
while True:
    r = httpx.get(url_base + 'getUpdates', params={'offset': offset+1})
    updates = r.json()['result']
    for update in updates:
        offset = update['update_id']
        if 'message' in update:
            message = update['message']
            if 'text' in message:
                text = message['text']
                if 'from' in update['message']:
                    user = update['message']['from']
                    if 'password' in text:
                        respuesta = 'La contraseña es ' + generatePassword(10)
                        r = httpx.post(url_base + 'sendMessage', data={'chat_id': user['id'], 'text': respuesta})
                else:
                    continue
    time.sleep(1)

Obviamente nos falta tratar las respuestas incorrectas y los timeouts y demás (y alguna respuesta adicional que nos puede dar telegram si hacemos demasiadas peticiones), pero eso lo dejo para que lo mejoréis en el repositorio https://github.com/yoprogramo/nomorepassbot