From ce8f05d6e7c0594bec458b937bb8129d44c975bc Mon Sep 17 00:00:00 2001 From: Ezra Date: Sun, 5 Apr 2026 07:42:34 +0000 Subject: [PATCH] =?UTF-8?q?[DEEP-DIVE]=20Scaffold=20component=20=E2=80=94?= =?UTF-8?q?=20#830?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../deep-dive/delivery/delivery_pipeline.py | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 scaffold/deep-dive/delivery/delivery_pipeline.py diff --git a/scaffold/deep-dive/delivery/delivery_pipeline.py b/scaffold/deep-dive/delivery/delivery_pipeline.py new file mode 100644 index 0000000..bec22bd --- /dev/null +++ b/scaffold/deep-dive/delivery/delivery_pipeline.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +""" +Delivery Pipeline for Deep Dive +Sends audio briefings to Telegram +""" + +import os +import asyncio +from pathlib import Path +from typing import Optional + +# Telegram bot integration +try: + from telegram import Bot + TELEGRAM_AVAILABLE = True +except ImportError: + TELEGRAM_AVAILABLE = False + print("python-telegram-bot not installed, delivery will be stubbed") + +TELEGRAM_BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "") +TELEGRAM_CHANNEL_ID = os.environ.get("TELEGRAM_HOME_CHANNEL", "") + +class TelegramDelivery: + def __init__(self, token: str = None, channel_id: str = None): + self.token = token or TELEGRAM_BOT_TOKEN + self.channel_id = channel_id or TELEGRAM_CHANNEL_ID + self.bot = None + + if TELEGRAM_AVAILABLE and self.token: + self.bot = Bot(token=self.token) + + async def send_voice_message( + self, + audio_path: Path, + caption: str = None, + duration: int = None + ) -> bool: + """Send voice message to Telegram channel.""" + if not self.bot or not self.channel_id: + print(f"[STUB] Would send {audio_path} to {self.channel_id}") + print(f"[STUB] Caption: {caption}") + return True + + try: + with open(audio_path, "rb") as audio: + await self.bot.send_voice( + chat_id=self.channel_id, + voice=audio, + caption=caption, + duration=duration + ) + return True + except Exception as e: + print(f"Telegram delivery failed: {e}") + return False + + async def send_text_summary(self, text: str) -> bool: + """Send text summary as fallback.""" + if not self.bot or not self.channel_id: + print(f"[STUB] Would send text to {self.channel_id}") + return True + + try: + # Split if too long + chunks = [text[i:i+4000] for i in range(0, len(text), 4000)] + for chunk in chunks: + await self.bot.send_message( + chat_id=self.channel_id, + text=chunk, + parse_mode="Markdown" + ) + return True + except Exception as e: + print(f"Text delivery failed: {e}") + return False + +def deliver_briefing( + audio_path: Path, + text_summary: str = None, + dry_run: bool = False +) -> bool: + """Convenience function for delivery.""" + delivery = TelegramDelivery() + + if dry_run: + print(f"[DRY RUN] Audio: {audio_path}") + print(f"[DRY RUN] Text: {text_summary[:200] if text_summary else 'None'}...") + return True + + async def _send(): + success = await delivery.send_voice_message(audio_path) + if text_summary and success: + await delivery.send_text_summary(text_summary) + return success + + return asyncio.run(_send()) + +if __name__ == "__main__": + print("Delivery pipeline loaded") + print(f"Telegram available: {TELEGRAM_AVAILABLE}")