Add possibility to translate messages in some bots

This commit is contained in:
Antonio J. Delgado 2023-04-25 11:22:51 +03:00
parent dfed69e958
commit fcf37a9035
4 changed files with 170 additions and 92 deletions

View File

@ -3,67 +3,94 @@ from common import get_api
from common import list_append
from common import list_read
from common import list_write
import json
import os
class load_custom_messages():
def __init__(self, custom_message_file):
if os.path.exists(custom_message_file):
with open(custom_message_file, 'r') as messages_pointer:
custom_messages = json.load(messages_pointer)
return custom_messages
# Messages
mensaje = "Alguien que te aprecia mucho quiere recordarte que eres una persona maravillosa :ablobcatheartsqueeze: ¡Sigue así, "
mensaje_croqueta = "Alguien que te aprecia mucho quiere enviarte croquetas :croqueta: :croqueta: :croqueta:"
mensaje_mismo = "La persona más importante que debes apreciar eres tú. ¡Eres increíble! ❤"
mensaje_nobot = "La cuenta objetivo tiene la etiqueta #nobot en su biografía. ¡No tengo poder aquí!"
mensaje_aviso = "Has intentado apreciar a alguien pero no has usado un mensaje directo/privado. ¡Tienes que mencionarme en un mensaje directo/privado para que funcione!"
mensaje_error = "No pude procesar tu apreciación. ¡Asegúrate de no incluir saltos de línea ni otros caracteres extraños! El mensaje debería ser tal que así: \"@apreciabot@masto.es usuario@servidor\n"
mensaje_no_encontrado = " No se pudo encontrar la cuenta del usuario especificado. \n\nRevisa que has escrito bien la cuenta con el formato \"usuario@servidor\" (por ejemplo, rober@masto.es, excluyendo el primer @ para evitar mencionarlo).\n\nSi lo has mencionado por error, ¡borra el mensaje antes de que se de cuenta!"
class apreciabot():
def __init__(self, **kwargs):
# Initialization
self.kwargs = kwargs
self.custom_messages = load_custom_messages(self.kwargs['custom_message_file'])
bot_name = self.custom_messages['apreciabot']['bot_name']
# Initialization
bot_name = 'apreciabot'
api = get_api('masto.es', bot_name)
last_ids = list_read(bot_name)
max_notifications=10
new_last_ids=[]
notifications = api.notifications(types=["mention"],limit=max_notifications)
for n in notifications:
new_last_ids.append(n['id'])
# Messages
messages = self.custom_messages[self.kwargs['language']]
mensaje = self.custom_messages[bot_name]['mensaje']
mensaje_croqueta = self.custom_messages[bot_name]['mensaje_croqueta']
mensaje_mismo = self.custom_messages[bot_name]['mensaje_mismo']
mensaje_nobot = self.custom_messages[bot_name]['mensaje_nobot']
mensaje_aviso = self.custom_messages[bot_name]['mensaje_aviso']
mensaje_error = self.custom_messages[bot_name]['mensaje_error']
mensaje_no_encontrado = self.custom_messages[bot_name]['mensaje_no_encontrado']
mensaje_muestra_aprecio_enviada = self.custom_messages[bot_name]['mensaje_muestra_aprecio_enviada']
# Some notifications may have been deleted since last fetch
# Therefore, it is better to check less than the maximum number of notifications
for i in range(0, max_notifications - 5):
n = notifications[i]
if str(n['id']) not in last_ids:
# Mentions data are HTML paragraphs so we delete everything between <> to clean it up
content = BeautifulSoup(n['status']['content'], "html.parser").get_text().split(" ")
try:
first_mention = content[0]
target = "@" + content[1]
user = "@" + n['account']['acct']
except:
api.status_reply(n['status'], mensaje_error)
continue
# The bot is meant to be anonymous so only allow directs
if n['status']['visibility'] == "direct":
if user == target:
api.status_reply(n['status'], mensaje_mismo, visibility="unlisted")
else:
# Find account if it is not known by the server
api.search(target, result_type="accounts")
api = get_api(self.kwargs['instance_name'], bot_name)
last_ids = list_read(bot_name)
max_notifications=10
new_last_ids=[]
notifications = api.notifications(types=["mention"],limit=max_notifications)
for n in notifications:
new_last_ids.append(n['id'])
# Some notifications may have been deleted since last fetch
# Therefore, it is better to check less than the maximum number of notifications
for i in range(0, max_notifications - 5):
n = notifications[i]
if str(n['id']) not in last_ids:
# Mentions data are HTML paragraphs so we delete everything between <> to clean it up
content = BeautifulSoup(n['status']['content'], "html.parser").get_text().split(" ")
try:
bio = api.account_lookup(target)
first_mention = content[0]
target = "@" + content[1]
user = "@" + n['account']['acct']
except:
api.status_post(user + mensaje_no_encontrado, in_reply_to_id=n['status']['id'], visibility="direct" )
else:
if "nobot" in bio['note']:
api.status_reply(n['status'], mensaje_nobot)
api.status_reply(n['status'], mensaje_error)
continue
# The bot is meant to be anonymous so only allow directs
if n['status']['visibility'] == "direct":
if user == target:
api.status_reply(n['status'], mensaje_mismo, visibility="unlisted")
else:
#api.status_post(mensaje + target + "!", in_reply_to_id=n['status']['id'], visibility="unlisted")
if ("croqueta" in content
or "croquetas" in content
or '"croqueta"' in content
or '"croquetas"' in content
):
new_status = api.status_post(target + " " + mensaje_croqueta, visibility="unlisted")
else:
new_status = api.status_post(mensaje + target + "!", visibility="unlisted")
api.status_reply(n['status'], 'Tu muestra de aprecio ha sido enviada ❤️ ' + new_status['url'], visibility="direct")
elif first_mention == "@apreciabot" and n['status']['in_reply_to_id'] == None:
api.status_reply(n['status'], mensaje_aviso, visibility='direct')
# Find account if it is not known by the server
api.search(target, result_type="accounts")
try:
bio = api.account_lookup(target)
except:
api.status_post(user + mensaje_no_encontrado, in_reply_to_id=n['status']['id'], visibility="direct" )
else:
if "nobot" in bio['note']:
api.status_reply(n['status'], mensaje_nobot)
else:
#api.status_post(mensaje + target + "!", in_reply_to_id=n['status']['id'], visibility="unlisted")
if ("croqueta" in content
or "croquetas" in content
or '"croqueta"' in content
or '"croquetas"' in content
):
new_status = api.status_post(target + " " + mensaje_croqueta, visibility="unlisted")
else:
new_status = api.status_post(mensaje + target + "!", visibility="unlisted")
api.status_reply(n['status'], mensaje_muestra_aprecio_enviada + new_status['url'], visibility="direct")
elif first_mention == "@" + bot_name and n['status']['in_reply_to_id'] == None:
api.status_reply(n['status'], mensaje_aviso, visibility='direct')
list_write(bot_name, new_last_ids)
@click.command()
@click.option('--language', '-l', default='es', help="Language.")
@click.option('--custom-message-file', '-j', default='custom_messages.json', help='JSON file containing the messages.')
@click.option('--instance-name', '-i', default='masto.es', help='Instance FQDN')
@click_config_file.configuration_option()
def __main__(**kwargs):
return apreciabot(**kwargs)
if __name__ == "__main__":
__main__()
list_write(bot_name, new_last_ids)

22
custom_messages.json Normal file
View File

@ -0,0 +1,22 @@
{
"es": {
"apreciabot": {
"message": "Alguien que te aprecia mucho quiere recordarte que eres una persona maravillosa :ablobcatheartsqueeze: ¡Sigue así, ",
"mensaje_croqueta": "Alguien que te aprecia mucho quiere enviarte croquetas :croqueta: :croqueta: :croqueta:",
"mensaje_mismo": "La persona más importante que debes apreciar eres tú. ¡Eres increíble! ❤",
"mensaje_nobot": "La cuenta objetivo tiene la etiqueta #nobot en su biografía. ¡No tengo poder aquí!",
"mensaje_aviso": "Has intentado apreciar a alguien pero no has usado un mensaje directo/privado. ¡Tienes que mencionarme en un mensaje directo/privado para que funcione!",
"mensaje_error": "No pude procesar tu apreciación. ¡Asegúrate de no incluir saltos de línea ni otros caracteres extraños! El mensaje debería ser tal que así: \"@apreciabot@masto.es usuario@servidor\n",
"mensaje_no_encontrado": " No se pudo encontrar la cuenta del usuario especificado. \n\nRevisa que has escrito bien la cuenta con el formato \"usuario@servidor\" (por ejemplo, rober@masto.es, excluyendo el primer @ para evitar mencionarlo).\n\nSi lo has mencionado por error, ¡borra el mensaje antes de que se de cuenta!",
"bot_name": "apreciabot",
"mensaje_muestra_aprecio_enviada": "Tu muestra de aprecio ha sido enviada ❤️ "
},
"describot": {
"message": "¡Hola! He detectado que has publicado imágenes o vídeo sin texto alternativo. Añadir una descripción de texto alternativa a tus vídeos e imágenes es esencial para que las personas con alguna discapacidad visual puedan disfrutar de nuestras publicaciones. \n\n Por favor, considera añadir texto alternativo a tus publicaciones la próxima vez (o edita esta publicación para añadírselo). Si necesitas ayuda para saber cómo hacerlo, consulta la publicación fijada en mi perfil: https://masto.es/@TeLoDescribot/110249937862873987 \n\n ¡Gracias por hacer de este espacio un lugar más accesible para todos! \n\n Bip bop. Esta es una cuenta automatizada, si no quieres que te mencione más, eres libre de bloquearme.",
"bot_name": "describot"
},
"federabot": {
"message": "¡Hola! Veo que es tu primera vez en Mastodon, ¡te doy la bienvenida si así es!\n\nSoy Roberto, el administrador del servidor de Mastodon en español https://masto.es. Ya ves que aunque estemos en servidores diferentes, somos capaces de comunicarnos gracias al modelo federado de Mastodon :mastodance:\n\nAunque yo no sea tu administrador en {{ user_domain }}, si necesitas ayuda para empezar puedes consultar la guía que he preparado para mis usuarios: https://masto.es/@rober/109412552189056438\n\nY si tienes alguna duda más, estaré encantado de ayudarte, solo responde a este mensaje privado 🙂"
}
}
}

View File

@ -3,45 +3,71 @@ from common import list_append
from common import list_read
from common import list_write
from common import get_new_notifications
import json
import os
message = "¡Hola! He detectado que has publicado imágenes o vídeo sin texto alternativo. Añadir una descripción de texto alternativa a tus vídeos e imágenes es esencial para que las personas con alguna discapacidad visual puedan disfrutar de nuestras publicaciones. \n\n Por favor, considera añadir texto alternativo a tus publicaciones la próxima vez (o edita esta publicación para añadírselo). Si necesitas ayuda para saber cómo hacerlo, consulta la publicación fijada en mi perfil: https://masto.es/@TeLoDescribot/110249937862873987 \n\n ¡Gracias por hacer de este espacio un lugar más accesible para todos! \n\n Bip bop. Esta es una cuenta automatizada, si no quieres que te mencione más, eres libre de bloquearme."
class load_custom_messages():
def __init__(self, custom_message_file):
if os.path.exists(custom_message_file):
with open(custom_message_file, 'r') as messages_pointer:
custom_messages = json.load(messages_pointer)
return custom_messages
class describot():
def __init__(self, **kwargs):
# Initialization
self.kwargs = kwargs
self.custom_messages = load_custom_messages(self.kwargs['custom_message_file'])
bot_name = messages['describot']['bot_name']
messages = self.custom_messages[self.kwargs['language']]
api_internal = get_api(self.kwargs['instance_name'], bot_name)
max_posts=20
warned=[]
following = list_read(bot_name + "_following")
def check_timeline(domain, api_external, timeline_name = 'local'):
last_ids = list_read(bot_name + "_" + domain + "_last_ids")
warned.extend(list_read(bot_name + "_" + domain))
timeline = api_external.timeline(timeline=timeline_name, limit=max_posts)
new_last_ids=[]
for post in timeline:
new_last_ids.append(post['id'])
for i in range(0, len(timeline) - 2):
post = timeline[i]
if str(post['id']) not in last_ids and (str(post['account']['acct']) not in warned or (timeline_name == 'home' and post['account']['acct'] in following)):
for media in post['media_attachments']:
if media['description'] is None:
print('Warning ' + post['account']['acct'])
api_internal.status_reply(post, message, visibility="unlisted")
warned.append(post['account']['acct'])
if domain != 'home':
list_append(bot_name + "_" + domain, post['account']['acct'])
break
list_write(bot_name + "_" + domain + "_last_ids", new_last_ids)
notifications = get_new_notifications(api_internal, bot_name, types=['follow'])
for n in notifications:
if n['account']['acct'] not in following:
print("Following: " + n['account']['acct'])
api_internal.account_follow(n['account']['id'])
following.append(n['account']['acct'])
list_append(bot_name + "_following", n['account']['acct'])
bot_name = 'describot'
api_mastoes = get_api('masto.es', bot_name)
max_posts=20
warned=[]
check_timeline(self.kwargs['instance_name'], api_internal)
check_timeline('home', api_internal, timeline_name='home')
following = list_read(bot_name + "_following")
@click.command()
@click.option('--language', '-l', default='es', help="Language.")
@click.option('--custom-message-file', '-j', default='custom_messages.json', help='JSON file containing the messages.')
@click.option('--instance-name', '-i', default='masto.es', help='Instance FQDN')
@click_config_file.configuration_option()
def __main__(**kwargs):
return describot(**kwargs)
def check_timeline(domain, api_external, timeline_name = 'local'):
last_ids = list_read(bot_name + "_" + domain + "_last_ids")
warned.extend(list_read(bot_name + "_" + domain))
timeline = api_external.timeline(timeline=timeline_name, limit=max_posts)
new_last_ids=[]
for post in timeline:
new_last_ids.append(post['id'])
for i in range(0, len(timeline) - 2):
post = timeline[i]
if str(post['id']) not in last_ids and (str(post['account']['acct']) not in warned or (timeline_name == 'home' and post['account']['acct'] in following)):
for media in post['media_attachments']:
if media['description'] is None:
print('Warning ' + post['account']['acct'])
api_mastoes.status_reply(post, message, visibility="unlisted")
warned.append(post['account']['acct'])
if domain != 'home':
list_append(bot_name + "_" + domain, post['account']['acct'])
break
list_write(bot_name + "_" + domain + "_last_ids", new_last_ids)
if __name__ == "__main__":
__main__()
notifications = get_new_notifications(api_mastoes, bot_name, types=['follow'])
for n in notifications:
if n['account']['acct'] not in following:
print("Following: " + n['account']['acct'])
api_mastoes.account_follow(n['account']['id'])
following.append(n['account']['acct'])
list_append(bot_name + "_following", n['account']['acct'])
check_timeline('masto.es', api_mastoes)
check_timeline('home', api_mastoes, timeline_name='home')

3
requirements.txt Normal file
View File

@ -0,0 +1,3 @@
click
click_config_file
Jinja2