Archives
Trending
Support
Login
clear text
XML
Django
JavaScript
MATLAB
C
C++
C#
Python
SQL
Shell
Bash
Markdown
YAML
JSON
HTML
CSS
PHP
Java
Ruby
Go
Rust
Swift
Kotlin
Arduino
TypeScript
Perl
Autohotkey
Lua
SQF
R
Scala
Haskell
Groovy
Dart
Clojure
VB.NET
Objective-C
PowerShell
Bash
CoffeeScript
Verilog
from telethon import TelegramClient, events import asyncio import logging import os from pathlib import Path # Intentar cargar variables de entorno desde .env try: from dotenv import load_dotenv load_dotenv() logger_init = logging.getLogger(__name__) logger_init.info("✅ Variables de entorno cargadas desde .env") except ImportError: pass # python-dotenv no está instalado, usar valores directos # Configuración de logging logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO ) logger = logging.getLogger(__name__) # ===================== CONFIGURACIÓN ===================== # Opción 1: Usar variables de entorno (recomendado para seguridad) API_ID = os.getenv('API_ID') or 'TU_API_ID' API_HASH = os.getenv('API_HASH') or 'TU_API_HASH' BOT_TOKEN = os.getenv('BOT_TOKEN') or 'TU_BOT_TOKEN' SOURCE_CHANNEL = os.getenv('SOURCE_CHANNEL') or '@canal_origen' TARGET_CHANNEL = os.getenv('TARGET_CHANNEL') or '@canal_destino' # Extensiones de archivo a repostear (puedes agregar más) ALLOWED_EXTENSIONS = ('.zip', '.rar', '.7z', '.tar', '.gz', '.3mf', '.stl', '.gcode') # Opciones adicionales FORWARD_AS_COPY = False # Si True, copia el mensaje sin mostrar "Forwarded from" ADD_WATERMARK = False # Si True, agrega un texto al repostear WATERMARK_TEXT = "\n\n📦 Reposteado automáticamente" # ========================================================= # Crear el cliente del bot bot = TelegramClient('bot_session', API_ID, API_HASH) def is_allowed_file(file_name): """ Verifica si el archivo tiene una extensión permitida """ if not file_name: return False return any(file_name.lower().endswith(ext) for ext in ALLOWED_EXTENSIONS) async def get_file_info(message): """ Extrae información del archivo del mensaje """ if not message.document: return None file_name = None file_size = message.document.size mime_type = message.document.mime_type for attribute in message.document.attributes: if hasattr(attribute, 'file_name'): file_name = attribute.file_name break return { 'name': file_name, 'size': file_size, 'mime_type': mime_type } def format_file_size(size_bytes): """ Convierte bytes a formato legible (KB, MB, GB) """ for unit in ['B', 'KB', 'MB', 'GB']: if size_bytes < 1024.0: return f"{size_bytes:.2f} {unit}" size_bytes /= 1024.0 return f"{size_bytes:.2f} TB" @bot.on(events.NewMessage(chats=SOURCE_CHANNEL)) async def repost_handler(event): """ Maneja los nuevos mensajes del canal origen y los repostea al destino """ try: message = event.message # Verificar si el mensaje tiene un archivo if message.media and message.document: file_info = await get_file_info(message) if not file_info or not file_info['name']: logger.debug("⏭️ Mensaje sin nombre de archivo, ignorado") return file_name = file_info['name'] # Verificar si es una extensión permitida if is_allowed_file(file_name): file_size = format_file_size(file_info['size']) logger.info(f"📥 Reposteando archivo: {file_name} ({file_size})") if FORWARD_AS_COPY: # Opción: Enviar como copia (sin "Forwarded from") caption = message.message or "" if ADD_WATERMARK: caption += WATERMARK_TEXT await bot.send_file( TARGET_CHANNEL, file=message.media, caption=caption ) else: # Opción: Forward directo (muestra "Forwarded from") await bot.forward_messages( entity=TARGET_CHANNEL, messages=message.id, from_peer=SOURCE_CHANNEL ) logger.info(f"✅ Archivo reposteado exitosamente: {file_name}") else: logger.debug(f"⏭️ Archivo ignorado (extensión no permitida): {file_name}") else: logger.debug("⏭️ Mensaje sin archivo, ignorado") except Exception as e: logger.error(f"❌ Error al repostear mensaje: {e}", exc_info=True) @bot.on(events.NewMessage(pattern='/start')) async def start_handler(event): """ Comando /start para verificar que el bot funciona """ await event.respond( "🤖 **Bot de Reposteo Activo**\n\n" f"📡 Canal origen: `{SOURCE_CHANNEL}`\n" f"📤 Canal destino: `{TARGET_CHANNEL}`\n" f"📁 Extensiones: {', '.join(ALLOWED_EXTENSIONS)}\n\n" "✅ El bot está funcionando correctamente." ) @bot.on(events.NewMessage(pattern='/status')) async def status_handler(event): """ Comando /status para verificar el estado del bot """ try: # Verificar acceso a los canales source_entity = await bot.get_entity(SOURCE_CHANNEL) target_entity = await bot.get_entity(TARGET_CHANNEL) await event.respond( "📊 **Estado del Bot**\n\n" f"✅ Canal origen: {source_entity.title}\n" f"✅ Canal destino: {target_entity.title}\n" f"✅ Extensiones activas: {len(ALLOWED_EXTENSIONS)}\n" f"✅ Bot funcionando correctamente" ) except Exception as e: await event.respond(f"❌ Error: {e}") async def main(): """ Función principal para iniciar el bot """ logger.info("🤖 Iniciando bot...") # Validar configuración if API_ID == 'TU_API_ID' or API_HASH == 'TU_API_HASH': logger.error("❌ ERROR: Debes configurar API_ID y API_HASH") return if BOT_TOKEN == 'TU_BOT_TOKEN': logger.error("❌ ERROR: Debes configurar BOT_TOKEN") return # Conectar con el token del bot await bot.start(bot_token=BOT_TOKEN) # Obtener información del bot me = await bot.get_me() logger.info(f"✅ Bot conectado: @{me.username}") logger.info(f"📡 Escuchando mensajes en: {SOURCE_CHANNEL}") logger.info(f"📤 Reposteando a: {TARGET_CHANNEL}") logger.info(f"📁 Extensiones permitidas: {', '.join(ALLOWED_EXTENSIONS)}") logger.info(f"🔄 Modo: {'Copia' if FORWARD_AS_COPY else 'Forward'}") logger.info("🟢 Bot funcionando. Presiona Ctrl+C para detener.") logger.info("💡 Tip: Envía /start o /status al bot para verificar su estado") # Mantener el bot corriendo await bot.run_until_disconnected() if __name__ == '__main__': try: asyncio.run(main()) except KeyboardInterrupt: logger.info("\n🛑 Bot detenido por el usuario") except Exception as e: logger.error(f"❌ Error fatal: {e}", exc_info=True)
Mark as private (unlisted)
for 30 minutes
for 6 hours
for 1 day
for 1 week
for 1 month
for 1 year
everlasting (like CCCP)