Add Translator Bot for Telegram
This commit is contained in:
parent
5821636a01
commit
fbecbbf0a1
10
catch-all/06_bots_telegram/03_translator_bot/Dockerfile
Normal file
10
catch-all/06_bots_telegram/03_translator_bot/Dockerfile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
FROM python:3.10-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY . /app/
|
||||||
|
|
||||||
|
RUN pip install -r requirements.txt
|
||||||
|
|
||||||
|
CMD ["python", "translator.py"]
|
||||||
|
|
19
catch-all/06_bots_telegram/03_translator_bot/config.py
Normal file
19
catch-all/06_bots_telegram/03_translator_bot/config.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# config.py
|
||||||
|
# Este módulo gestiona la configuración y la carga de variables de entorno.
|
||||||
|
|
||||||
|
import os
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# Cargar las variables de entorno desde el archivo .env
|
||||||
|
load_dotenv('.env')
|
||||||
|
|
||||||
|
# Obtener el token del bot y el ID del chat de grupo desde las variables de entorno
|
||||||
|
BOT_TOKEN = os.getenv('BOT_TOKEN')
|
||||||
|
GROUP_CHAT_ID = os.getenv('GROUP_CHAT_ID')
|
||||||
|
|
||||||
|
# Validar que las variables de entorno estén configuradas
|
||||||
|
if not BOT_TOKEN or not GROUP_CHAT_ID:
|
||||||
|
raise AssertionError("Por favor, configura las variables de entorno BOT_TOKEN y GROUP_CHAT_ID")
|
||||||
|
|
||||||
|
# Convertir GROUP_CHAT_ID a entero
|
||||||
|
GROUP_CHAT_ID = int(GROUP_CHAT_ID)
|
63
catch-all/06_bots_telegram/03_translator_bot/logger.py
Normal file
63
catch-all/06_bots_telegram/03_translator_bot/logger.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
"""
|
||||||
|
# Ejemplo de uso del logger
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
logger.info('Logger configurado correctamente.')
|
||||||
|
logger.debug('Este es un mensaje de depuración.')
|
||||||
|
logger.warning('Este es un mensaje de advertencia.')
|
||||||
|
logger.error('Este es un mensaje de error.')
|
||||||
|
logger.critical('Este es un mensaje crítico.')
|
||||||
|
"""
|
||||||
|
|
||||||
|
# logger.py
|
||||||
|
# Este módulo configura el logging con rotación de archivos.
|
||||||
|
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
from logging.handlers import RotatingFileHandler
|
||||||
|
|
||||||
|
|
||||||
|
def setup_logger():
|
||||||
|
# Crear el directorio de logs si no existe
|
||||||
|
log_directory = 'logs'
|
||||||
|
if not os.path.exists(log_directory):
|
||||||
|
os.makedirs(log_directory)
|
||||||
|
|
||||||
|
# Ruta del archivo de log
|
||||||
|
log_file = os.path.join(log_directory, 'bot.log')
|
||||||
|
|
||||||
|
# Formato de los mensajes de log
|
||||||
|
log_formatter = logging.Formatter(
|
||||||
|
'%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||||
|
|
||||||
|
# Configurar RotatingFileHandler
|
||||||
|
# maxBytes: tamaño máximo del archivo de log en bytes (5MB en este caso)
|
||||||
|
# backupCount: número máximo de archivos de respaldo
|
||||||
|
file_handler = RotatingFileHandler(
|
||||||
|
log_file, maxBytes=5*1024*1024, backupCount=5)
|
||||||
|
file_handler.setFormatter(log_formatter)
|
||||||
|
file_handler.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
# Configurar StreamHandler para la consola
|
||||||
|
console_handler = logging.StreamHandler()
|
||||||
|
console_handler.setFormatter(log_formatter)
|
||||||
|
|
||||||
|
# Puedes cambiar este nivel según tus necesidades
|
||||||
|
console_handler.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
# Configurar el logger
|
||||||
|
logger = logging.getLogger('telegram_bot')
|
||||||
|
# Configurar el nivel del logger a DEBUG para capturar todos los mensajes
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
logger.addHandler(file_handler)
|
||||||
|
logger.addHandler(console_handler)
|
||||||
|
|
||||||
|
# Evitar que los mensajes se dupliquen en el log
|
||||||
|
logger.propagate = False
|
||||||
|
|
||||||
|
return logger
|
||||||
|
|
||||||
|
|
||||||
|
# Inicializar el logger
|
||||||
|
logger = setup_logger()
|
@ -0,0 +1,3 @@
|
|||||||
|
python-telegram-bot==21.3
|
||||||
|
translate==3.6.1
|
||||||
|
python-dotenv==1.0.1
|
211
catch-all/06_bots_telegram/03_translator_bot/translator.py
Normal file
211
catch-all/06_bots_telegram/03_translator_bot/translator.py
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
"""
|
||||||
|
Este módulo contiene el código para un bot de Telegram que realiza tareas de traducción.
|
||||||
|
|
||||||
|
El bot utiliza la API de Telegram Bot para interactuar con los usuarios y la API de Google Translate para la traducción.
|
||||||
|
|
||||||
|
La función principal inicializa el bot y comienza a escuchar los mensajes entrantes.
|
||||||
|
|
||||||
|
Para ejecutar el bot, asegúrese de tener las credenciales y la configuración de la API necesarias configuradas en el módulo `config`.
|
||||||
|
|
||||||
|
Extraido del tutorial de youtube y luego actualizado: https://www.youtube.com/watch?v=8buZAq148gk&ab_channel=SBDeveloper
|
||||||
|
|
||||||
|
Autor: manuelver
|
||||||
|
"""
|
||||||
|
|
||||||
|
import signal
|
||||||
|
|
||||||
|
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
|
||||||
|
from telegram.ext import ApplicationBuilder, MessageHandler, CommandHandler, CallbackContext, filters, CallbackQueryHandler
|
||||||
|
|
||||||
|
from translate import Translator
|
||||||
|
|
||||||
|
import config
|
||||||
|
from logger import logger
|
||||||
|
|
||||||
|
|
||||||
|
def def_handler(sig, frame):
|
||||||
|
"""
|
||||||
|
Función manejadora de señales para salir del programa de manera elegante.
|
||||||
|
"""
|
||||||
|
logger.info("Saliendo del programa...")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
# Configurar el manejador de señal para SIGINT (Ctrl+C)
|
||||||
|
signal.signal(signal.SIGINT, def_handler)
|
||||||
|
|
||||||
|
|
||||||
|
async def select_origin_lang(update: Update, context: CallbackContext) -> None:
|
||||||
|
"""
|
||||||
|
Función para seleccionar el idioma de origen para la traducción.
|
||||||
|
"""
|
||||||
|
keyboard = [
|
||||||
|
[
|
||||||
|
InlineKeyboardButton("Español", callback_data='es'),
|
||||||
|
InlineKeyboardButton("Catalán", callback_data='ca'),
|
||||||
|
InlineKeyboardButton("English", callback_data='en'),
|
||||||
|
InlineKeyboardButton("Français", callback_data='fr')
|
||||||
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton("Deutsch", callback_data='de'),
|
||||||
|
InlineKeyboardButton("Italiano", callback_data='it'),
|
||||||
|
InlineKeyboardButton("Português", callback_data='pt')
|
||||||
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton("Русский (Ruso)", callback_data='ru'),
|
||||||
|
InlineKeyboardButton("日本語 (Japonés)", callback_data='ja'),
|
||||||
|
InlineKeyboardButton("中文 (Chino)", callback_data='zh')
|
||||||
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton("(Árabe) العربية", callback_data='ar'),
|
||||||
|
InlineKeyboardButton("हिन्दी (Hindi)", callback_data='hi'),
|
||||||
|
InlineKeyboardButton("עברית (Hebreo)", callback_data='he')
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
||||||
|
|
||||||
|
await update.message.reply_text(
|
||||||
|
'Por favor, selecciona el idioma de origen:', reply_markup=reply_markup)
|
||||||
|
|
||||||
|
|
||||||
|
async def select_dest_lang(update: Update, context: CallbackContext) -> None:
|
||||||
|
"""
|
||||||
|
Función para seleccionar el idioma de destino para la traducción.
|
||||||
|
"""
|
||||||
|
keyboard = [
|
||||||
|
[
|
||||||
|
InlineKeyboardButton("Español", callback_data='es'),
|
||||||
|
InlineKeyboardButton("Catalán", callback_data='ca'),
|
||||||
|
InlineKeyboardButton("English", callback_data='en'),
|
||||||
|
InlineKeyboardButton("Français", callback_data='fr')
|
||||||
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton("Deutsch", callback_data='de'),
|
||||||
|
InlineKeyboardButton("Italiano", callback_data='it'),
|
||||||
|
InlineKeyboardButton("Português", callback_data='pt')
|
||||||
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton("Русский (Ruso)", callback_data='ru'),
|
||||||
|
InlineKeyboardButton("日本語 (Japonés)", callback_data='ja'),
|
||||||
|
InlineKeyboardButton("中文 (Chino)", callback_data='zh')
|
||||||
|
],
|
||||||
|
[
|
||||||
|
InlineKeyboardButton("(Árabe) العربية", callback_data='ar'),
|
||||||
|
InlineKeyboardButton("हिन्दी (Hindi)", callback_data='hi'),
|
||||||
|
InlineKeyboardButton("עברית (Hebreo)", callback_data='he')
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
||||||
|
|
||||||
|
await update.message.reply_text(
|
||||||
|
f'Por favor, selecciona el idioma de destino:', reply_markup=reply_markup)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async def button(update: Update, context: CallbackContext) -> None:
|
||||||
|
"""
|
||||||
|
Función para manejar los botones de idioma seleccionados.
|
||||||
|
"""
|
||||||
|
query = update.callback_query
|
||||||
|
await query.answer()
|
||||||
|
|
||||||
|
if 'origin_lang' not in context.user_data:
|
||||||
|
context.user_data['origin_lang'] = query.data
|
||||||
|
await query.edit_message_text(text=f"Idioma de origen seleccionado.\n\nAhora selecciona el idioma de destino con el comando /langTo")
|
||||||
|
await select_dest_lang(update, context)
|
||||||
|
else:
|
||||||
|
context.user_data['dest_lang'] = query.data
|
||||||
|
await query.edit_message_text(text=f"Idioma de destino seleccionado.\n\nEnvía tu texto para traducir.")
|
||||||
|
|
||||||
|
logger.info(f"Idioma seleccionado: {query.data}")
|
||||||
|
|
||||||
|
|
||||||
|
async def lang_translator(user_input, from_lang, to_lang):
|
||||||
|
|
||||||
|
try:
|
||||||
|
translator = Translator(from_lang=from_lang, to_lang=to_lang)
|
||||||
|
translation = translator.translate(user_input)
|
||||||
|
|
||||||
|
return translation
|
||||||
|
|
||||||
|
except TranslationError as e:
|
||||||
|
logger.error(f"Error en la traducción: {str(e)}")
|
||||||
|
return "Error en la traducción. Por favor, intenta de nuevo más tarde."
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error inesperado al traducir el texto: {str(e)}")
|
||||||
|
return "Error inesperado al traducir el texto."
|
||||||
|
|
||||||
|
|
||||||
|
async def reply(update: Update, context: CallbackContext):
|
||||||
|
|
||||||
|
user_input = update.message.text
|
||||||
|
from_lang = context.user_data.get(
|
||||||
|
'origin_lang', 'es') # Español por defecto
|
||||||
|
to_lang = context.user_data.get('dest_lang', 'en') # Inglés por defecto
|
||||||
|
|
||||||
|
translation = await lang_translator(user_input, from_lang, to_lang)
|
||||||
|
await update.message.reply_text(translation)
|
||||||
|
|
||||||
|
logger.info(f"Mensaje recibido: {user_input}")
|
||||||
|
logger.info(f"Texto traducido: {translation}")
|
||||||
|
|
||||||
|
|
||||||
|
async def start(update: Update, context: CallbackContext):
|
||||||
|
|
||||||
|
await update.message.reply_text("¡Hola! Soy un bot de traducción.\n\nSi necesitas ayuda: /help.")
|
||||||
|
|
||||||
|
logger.info("Comando /start recibido.")
|
||||||
|
|
||||||
|
|
||||||
|
async def help_command(update: Update, context: CallbackContext):
|
||||||
|
"""
|
||||||
|
Función para mostrar los comandos disponibles.
|
||||||
|
"""
|
||||||
|
commands = [
|
||||||
|
"/start - Iniciar el bot",
|
||||||
|
"/langFrom - Seleccionar idioma de origen",
|
||||||
|
"/langTo - Seleccionar idioma de destino",
|
||||||
|
"/help - Mostrar este mensaje de ayuda"
|
||||||
|
]
|
||||||
|
help_text = "\n".join(commands)
|
||||||
|
|
||||||
|
await update.message.reply_text(f"El idioma por defecto origen es español y el de destino el Inglés.\nPuedes configurar otras opciones.\nUna vez lo tengas listo tan solo tienes que enviar el texto con el idioma origen.\n\nOpciones:\n{help_text}")
|
||||||
|
|
||||||
|
logger.info("Comando /help recibido.")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""
|
||||||
|
Función principal para inicializar el bot y comenzar a escuchar los mensajes.
|
||||||
|
"""
|
||||||
|
api = config.BOT_TOKEN
|
||||||
|
|
||||||
|
application = ApplicationBuilder().token(api).build()
|
||||||
|
|
||||||
|
# Manejadores de comandos y mensajes
|
||||||
|
application.add_handler(CommandHandler('start', start))
|
||||||
|
application.add_handler(CommandHandler('langFrom', select_origin_lang))
|
||||||
|
application.add_handler(CommandHandler('langTo', select_dest_lang))
|
||||||
|
application.add_handler(CommandHandler('help', help_command))
|
||||||
|
application.add_handler(CommandHandler('command', help_command))
|
||||||
|
application.add_handler(MessageHandler(
|
||||||
|
filters.TEXT & ~filters.COMMAND, reply))
|
||||||
|
application.add_handler(CallbackQueryHandler(button))
|
||||||
|
|
||||||
|
# Iniciar el bot
|
||||||
|
logger.info("Bot iniciado.")
|
||||||
|
|
||||||
|
# Iniciar el bucle de eventos
|
||||||
|
application.run_polling()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
main()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f'Error en la ejecución del bot: {str(e)}')
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
def_handler(None, None)
|
@ -1,10 +1,10 @@
|
|||||||
# Bots de Telegram
|
# Bots de Telegram
|
||||||
|
|
||||||
| Nombre | Descripción | Nivel |
|
| Nombre | Descripción | Nivel |
|
||||||
| ---------------------------------------------------- | ----------------------------------------- | ---------- |
|
| ----------------------------------------- | ----------------------------------------- | ---------- |
|
||||||
| [Bot que devuelve id del bot](./01_id_bot/id_bot.py) | Bot que devuelve el id del bot | básico |
|
| [Bot id del chat](./01_id_bot/) | Bot que devuelve el id del bot | básico |
|
||||||
| [Bot pruebas](./02_pruebas_bot/bot.py) | Bot que devuelve mensajes básicos | básico |
|
| [Bot mensajes](./02_pruebas_bot/) | Bot que devuelve mensajes básicos. Loggin | intermedio |
|
||||||
| **Bot de traducción** (próximamente) | Bot que traduce mensajes a varios idiomas | intermedio |
|
| [Bot de traducción](./03_translator_bot/) | Bot que traduce mensajes a varios idiomas | avanzado |
|
||||||
| **Bot de clima** (próximamente) | Bot que devuelve el clima de una ciudad | intermedio |
|
| **Bot de clima** (próximamente) | Bot que devuelve el clima de una ciudad | intermedio |
|
||||||
| **Bot de noticias** (próximamente) | Bot que devuelve noticias de última hora | intermedio |
|
| **Bot de noticias** (próximamente) | Bot que devuelve noticias de última hora | intermedio |
|
||||||
| **Bot de mareas** (próximamente) | Bot que devuelve información de mareas | avanzado |
|
| **Bot de mareas** (próximamente) | Bot que devuelve información de mareas | avanzado |
|
||||||
|
Loading…
Reference in New Issue
Block a user