Skip to content

Instantly share code, notes, and snippets.

@erseco
Last active June 11, 2024 10:31
Show Gist options
  • Save erseco/9ea3052e3b2e441606a13de093eabe22 to your computer and use it in GitHub Desktop.
Save erseco/9ea3052e3b2e441606a13de093eabe22 to your computer and use it in GitHub Desktop.
"""
Telegram Channel Media Downloader
Este script descarga archivos multimedia de un canal de Telegram especificado y evita descargar archivos ya existentes.
Las variables de configuración se leen desde un archivo `.env`.
### Instrucciones:
1. Instala las dependencias necesarias:
pip install telethon python-dotenv
2. Crea un archivo `.env` en el mismo directorio que este script con el siguiente contenido:
API_ID=your_api_id
API_HASH=your_api_hash
PHONE_NUMBER=your_phone_number
CHANNEL_ID=your_channel_id
SAVE_DIR=downloads
LOG_FILE=log.txt
3. Ejecuta el script:
python tg_downloader.py
Este script utiliza el modo sincrónico de Telethon y verifica si los archivos ya existen antes de descargarlos.
También registra todas las descargas y errores en un archivo log.
"""
import os
from telethon.sync import TelegramClient
from telethon.errors import ChannelPrivateError, ChannelInvalidError, ChatAdminRequiredError
from datetime import datetime
import sys
import time
# Function to read configuration from a file
def read_config(filename):
config = {}
with open(filename, 'r') as file:
for line in file:
name, value = line.strip().split('=')
config[name] = value
return config
# Read configuration
config = read_config('config.txt')
# Extract variables from config
api_id = int(config['API_ID'])
api_hash = config['API_HASH']
phone = config['PHONE_NUMBER']
channel_id = int(config['CHANNEL_ID'])
save_dir = config['SAVE_DIR']
log_file = config['LOG_FILE']
# Ensure the save directory exists
if not os.path.exists(save_dir):
os.makedirs(save_dir)
# Initialize the Telegram client
client = TelegramClient('session_name', api_id, api_hash)
# Function to log messages
def log_message(message):
with open(log_file, 'a') as log:
log.write(f"{datetime.now()}: {message}\n")
# Function to download media from a message and check if the file size is correct
def download_media(message):
if message.media:
filename = message.file.name or f"{message.id}_{message.date.strftime('%Y-%m-%d_%H-%M-%S')}.unknown"
file_path = os.path.join(save_dir, filename)
if os.path.exists(file_path) and os.path.getsize(file_path) == message.file.size:
print(f"Skipped (already exists and is complete): {file_path}")
log_message(f"Skipped (already exists and is complete): {file_path}")
return
download_successful = False
retry_count = 0
while not download_successful and retry_count < 5:
try:
client.download_media(message.media, file_path)
# Check if the file size matches the expected size
if os.path.exists(file_path) and os.path.getsize(file_path) == message.file.size:
download_successful = True
print(f"\nDownloaded: {file_path}")
log_message(f"Downloaded: {file_path}")
else:
raise Exception("File size does not match, retrying download.")
except Exception as e:
retry_count += 1
error_message = f"Failed to download message ID {message.id} ({file_path}): {e}"
print(f"\n{error_message}")
log_message(error_message)
if os.path.exists(file_path):
os.remove(file_path) # Remove incomplete file
# Progress bar with dots
print(f"Retry {retry_count}/5. Retrying in 3 seconds...", end='', flush=True)
time.sleep(3)
for _ in range(3):
print('.', end='', flush=True)
time.sleep(1)
print('')
# Main function to download all media from the channel
def main():
client.start()
try:
entity = client.get_entity(channel_id)
for message in client.iter_messages(entity):
filename = message.file.name if message.file else "No Title"
print(f"\nProcessing message ID {message.id} - {filename}")
download_media(message)
except (ChannelPrivateError, ChannelInvalidError, ChatAdminRequiredError) as e:
error_message = f"An error occurred: {e}"
print(error_message)
log_message(error_message)
except Exception as e:
error_message = f"An unexpected error occurred: {e}"
print(error_message)
log_message(error_message)
finally:
client.disconnect()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment