Creación de un bot simple para Mastodon

por: @ElPamplina@masto.es

API de Mastodon para Python:

GitHub - halcy/Mastodon.py: Python wrapper for the Mastodon ( https://github.com/mastodon/mastodon/ ) API.

Objeto del bot: Poesías completas de Antonio Machado

Poesías completas | Biblioteca Virtual Miguel de Cervantes

Preparar entorno

virtualenv env-machadobot
. ./env-machadobot/bin/activate
pip install Mastodon.py

Pasar a JSON el texto original

Instalar librería de ayuda.

pip install html2text

Bajar el texto HTML y convertirlo

curl -o "poesias.html" https://www.cervantesvirtual.com/obra-visor/poesias-completas-1158024/html/613eab1d-2c06-4d6f-bb4f-453605cb6d5c_2.html
html2text --ignore-links --ignore-images --ignore-emphasis --ignore-tables --unicode-snob poesias.html utf-8 >poesias.v1.txt

(Ojo, cuidadín, si no pones la opción --unicode-snob, el conversor te elimina todas las tildes).

Eliminar líneas en blanco, cabeceras (líneas con todo mayúsculas) y líneas de marcadores (las que empiezan por asteriscos, barras y paréntesis).

grep -v '^\s*


 poesias.v1.txt |grep -v '^\s*[\*\\(]' |grep -v '^[ A-Z]*


 >poesias.v2.txt

Termino el trabajo editando manualmente. Quito la cabecera y pie de página para que solo haya texto de poemas. Dejo los signos # que me servirán para separar cada poema. Elimino los pasajes largos de prosa. Añado el comienzo y final para formar el array JSON:

[
......TEXTO.....
]

Ahora sustituyo cada línea que empiece por # con unas comillas de cierre y apertura. Luego uso el venerable AWK para convertir los saltos de línea a "\n":

sed 's/^#.*$/","/' poesias.v2.txt >poesias.v3.txt
awk '{printf "%s\\n", $0}' poesias.v3.txt >poesias.json

Voy a comprobar que el formato JSON ha quedado bien, cargándolo directamente en Python, por si salta algún error.

$ python
Python 3.9.5 (default, May 11 2021, 08:20:37)
[GCC 10.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import json
>>> with open("poesias.json") as f:
...   res=json.load(f)
...
>>> len(res)
514

Ya podemos empezar nuestro bot.

Registrar bot

Necesitamos una cuenta de bot en algún servidor de Mastodon. Yo voy a usar masto.es porque es mi casa.

En masto.es, las normas son las siguientes (en otros servidores podrían diferir):

Si queréis alojar una cuenta bot en masto.es, podéis esperar las siguientes condiciones:
* Que publiquen con visibilidad "no listada" para no saturar nuestra línea pública.
* Que activen la eliminación automática entre 1 y 3 meses para hacer un uso responsable de los recursos del servidor.
* (En caso de interactuar con el usuario) Que respeten la etiqueta #nobot en el perfil.
* Y por supuesto, que respeten las otras reglas.

La cuenta bot se registra como cualquier otra, solo que en el perfil hay que marcar que se trata de un bot:

img/tutorial-bot-mastodon/img1.png

Ahora vamos a "Desarrollo" y creamos una nueva aplicación. Eso nos proporcionará unos tokens que nuestra API usará para comunicarse con el servidor. Con usar las opciones por defecto nos vale para lo que vamos a hacer.

Iniciar la API

Para acceder a la API de Mastodon vamos a usar la librería

Mastondon.py

para Python. Esta librería utiliza unos archivos con extensión .secret para guardar información de conexión con el servidor y de las credenciales de usuario. Solo tenemos que crearlos una vez.

Iniciamos los secrets y hacemos una prueba simple de envío de un post:

from mastodon import Mastodon
Mastodon.create_app('MachadoBot', api_base_url='https://masto.es', to_file='machadobot-app.secret')
mastodon = Mastodon(client_id='machadobot-app.secret')
mastodon.log_in('xxxxxxxUSUARIOxxxxxxx', 'xxxxxxPASSWORDxxxxxxx', to_file='machadobot-user.secret')
status = mastodon.status_post("""   Desdeño las romanzas de los tenores huecos
y el coro de los grillos que cantan a la luna.
A distinguir me paro las voces de los ecos,
y escucho solamente, entre las voces, una.""", visibility="unlisted")

Con esto ya deberíamos ver nuestro post en el timeline del bot:

img/tutorial-bot-mastodon/img2.png

A partir de aquí usaremos los archivos machadobot-app.secret y machadobot-user.secret para que nuestro programa no tenga que autenticarse cada vez. Por supuesto, esos archivos hay que guardarlos bien protegidos:

chmod 600 machadobot-app.secret machadobot-user.secret

Script del bot

Preparo el script Python que hará el trabajo de hacer un post de nuestro bot. Debe:

Leer lista de poesías

with open(POESIAS, encoding='utf-8') as f:
    poesias = json.load(f)
elegida = None
cuenta = len(poesias)
print(f"Cargado {POESIAS} con {cuenta} elementos.")
while elegida is None and cuenta > 0:
    candidata = random.choice(poesias)
    if candidata.strip() != '' and len(candidata) < LIMITE:
        elegida = candidata
    cuenta -= 1
print(f"Poesía elegida: {elegida}")

He usado unas constantes para los elementos configurables, como la ruta del archivo de poesías y el límite de caracteres del servidor. También he puesto la salvaguarda por si se hubiera colado en el JSON alguna comilla vacía o un texto demasiado largo.

Hacer post

Utilizamos unas variables predefinidas para la ruta de los archivos secret que ya tenemos preparados. Utiizo la opción no listada para cumplir con la norma del servidor.

if elegida is not None:
    mastodon = Mastodon(client_secret=APP_SECRET, access_token=USER_SECRET)
    post = mastodon.status_post(elegida, visibility='unlisted')
    print(f"Posteado: {post.uri}")
else:
    print("ERROR: NO ENCONTRADA.")

Con esto ya tenemos nuestro script completo.

Registrar cron

Usaremos la utilidad

cron

del sistema para hacer un post automáticamente cada hora, concretamente en el minuto 26:

26 * * * * /home/ubuntu/env-machadobot/bin/python /home/ubuntu/machadobot/machadobot.py

Con esto termina este tutorial. El resultado lo puedes ver en vivo en:

https://masto.es/@machadobot

@ElPamplina@masto.es

elpamplinadecai@gmail.com

Volver al índice