import requests import time import os from pathlib import Path from audio_splitter import split_audio from requests_toolbelt.multipart.encoder import MultipartEncoder, MultipartEncoderMonitor from requests.exceptions import ConnectionError, ReadTimeout, ChunkedEncodingError BOT_TOKEN = os.environ["TELEGRAM_TOKEN"] CHAT_ID = os.environ["CHAT_ID"] MAX_RETRIES = 5 def progress_callback(monitor): percent = monitor.bytes_read / monitor.len * 100 print(f"\rUploading: {percent:5.1f}%", end="", flush=True) def send_message(text): url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage" r = requests.post(url, data={ "chat_id": CHAT_ID, "text": text }, timeout=30) if not r.ok: print("Telegram message error:", r.text) def upload_file(file_path, caption): url = f"https://api.telegram.org/bot{BOT_TOKEN}/sendAudio" for attempt in range(1, MAX_RETRIES + 1): print(f"Connecting to Telegram (attempt {attempt}/{MAX_RETRIES})") try: with open(file_path, "rb") as f: encoder = MultipartEncoder( fields={ "chat_id": str(CHAT_ID), "title": caption, "audio": (file_path.name, f, "audio/mpeg"), } ) monitor = MultipartEncoderMonitor(encoder, progress_callback) print("Connection established, starting upload...") r = requests.post( url, data=monitor, headers={"Content-Type": monitor.content_type}, timeout=(20, 3600) # (connect_timeout, read_timeout) ) print("\nServer responded:", r.status_code) if r.ok: print("Upload success") return True print("Telegram API error:", r.text) except ConnectionError: print("\nConnection dropped by Telegram") except ReadTimeout: print("\nUpload timed out") except ChunkedEncodingError: print("\nChunked encoding error (connection reset)") except Exception as e: print("\nUnexpected error:", repr(e)) wait = 5 * attempt print(f"Retrying in {wait} sec...\n") time.sleep(wait) return False def send_audio(file_path, title): parts = split_audio(Path(file_path)) for i, part in enumerate(parts, start=1): caption = title if len(parts) > 1: caption = f"{title} (part {i}/{len(parts)})" print("Uploading:", part.name) success = upload_file(part, caption) if not success: return False # upload failed -> KEEP files for retry # if we got here, ALL parts uploaded successfully -> cleanup for part in parts: part.unlink(missing_ok=True) # also delete the original mp3 if we were uploading split parts original = Path(file_path) if len(parts) > 1 and original.exists(): original.unlink(missing_ok=True) return True