init
This commit is contained in:
109
delivery.py
Normal file
109
delivery.py
Normal file
@@ -0,0 +1,109 @@
|
||||
"""
|
||||
Доставка дайджеста: Telegram (Избранное / бот) или файл.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import httpx
|
||||
from telethon import TelegramClient
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
SESSION_DIR = Path("/data")
|
||||
|
||||
|
||||
def _split_message(text: str, max_length: int = 4000) -> list[str]:
|
||||
if len(text) <= max_length:
|
||||
return [text]
|
||||
|
||||
parts = []
|
||||
current = ""
|
||||
for line in text.split("\n"):
|
||||
if len(current) + len(line) + 1 > max_length:
|
||||
if current:
|
||||
parts.append(current.strip())
|
||||
current = line + "\n"
|
||||
else:
|
||||
current += line + "\n"
|
||||
if current.strip():
|
||||
parts.append(current.strip())
|
||||
return parts
|
||||
|
||||
|
||||
class DeliveryManager:
|
||||
def __init__(self, config: dict):
|
||||
self.cfg = config["delivery"]
|
||||
self.tg_cfg = config["telegram"]
|
||||
self.method = self.cfg["method"]
|
||||
self.max_length = self.cfg.get("max_message_length", 4000)
|
||||
|
||||
async def deliver(self, digest: str) -> None:
|
||||
now = datetime.now().strftime("%d.%m.%Y %H:%M")
|
||||
header = f"📰 **Новостной дайджест** — {now}\n\n"
|
||||
full_text = header + digest
|
||||
|
||||
if self.method == "saved_messages":
|
||||
await self._send_saved_messages(full_text)
|
||||
elif self.method == "bot":
|
||||
await self._send_via_bot(full_text)
|
||||
elif self.method == "file":
|
||||
self._save_to_file(full_text)
|
||||
else:
|
||||
raise ValueError(f"Неизвестный метод доставки: {self.method}")
|
||||
|
||||
async def _send_saved_messages(self, text: str):
|
||||
session_path = SESSION_DIR / self.tg_cfg["session_name"]
|
||||
client = TelegramClient(
|
||||
str(session_path),
|
||||
self.tg_cfg["api_id"],
|
||||
self.tg_cfg["api_hash"],
|
||||
)
|
||||
await client.connect()
|
||||
|
||||
if not await client.is_user_authorized():
|
||||
raise RuntimeError("Сессия не авторизована")
|
||||
|
||||
parts = _split_message(text, self.max_length)
|
||||
me = await client.get_me()
|
||||
for i, part in enumerate(parts, 1):
|
||||
await client.send_message(me, part, parse_mode="md")
|
||||
logger.info(f"Отправлена часть {i}/{len(parts)} в Избранное")
|
||||
|
||||
await client.disconnect()
|
||||
logger.info("✓ Дайджест отправлен в Избранное")
|
||||
|
||||
async def _send_via_bot(self, text: str):
|
||||
token = self.cfg["bot_token"]
|
||||
chat_id = self.cfg["chat_id"]
|
||||
url = f"https://api.telegram.org/bot{token}/sendMessage"
|
||||
|
||||
parts = _split_message(text, self.max_length)
|
||||
|
||||
async with httpx.AsyncClient(timeout=30) as client:
|
||||
for i, part in enumerate(parts, 1):
|
||||
resp = await client.post(
|
||||
url,
|
||||
json={
|
||||
"chat_id": chat_id,
|
||||
"text": part,
|
||||
"parse_mode": "Markdown",
|
||||
"disable_web_page_preview": True,
|
||||
},
|
||||
)
|
||||
if resp.status_code != 200:
|
||||
logger.error(f"Bot API: {resp.status_code} {resp.text}")
|
||||
else:
|
||||
logger.info(f"Часть {i}/{len(parts)} через бота")
|
||||
|
||||
logger.info("✓ Дайджест отправлен через бота")
|
||||
|
||||
def _save_to_file(self, text: str):
|
||||
output_dir = Path("/data/digests")
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
filename = datetime.now().strftime("digest_%Y%m%d_%H%M.md")
|
||||
filepath = output_dir / filename
|
||||
filepath.write_text(text, encoding="utf-8")
|
||||
logger.info(f"✓ Дайджест сохранён: {filepath}")
|
||||
Reference in New Issue
Block a user