feat: init AI email summarization bot
- Multi-account IMAP email polling with UID tracking - DeepSeek API integration with JSON Mode structured output - Telegram notification with formatted MarkdownV2 message - YAML config with dataclass-based type validation - Graceful shutdown on SIGINT/SIGTERM - 60s default polling interval
This commit is contained in:
11 files changed
+364
No files matched your search
@@ -0,0 +1,54 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List
|
||||
import yaml
|
||||
|
||||
|
||||
@dataclass
|
||||
class EmailAccount:
|
||||
imap_server: str
|
||||
imap_port: int
|
||||
username: str
|
||||
password: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class AIConfig:
|
||||
api_key: str
|
||||
model: str
|
||||
base_url: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class TelegramConfig:
|
||||
bot_token: str
|
||||
chat_id: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class PollingConfig:
|
||||
interval_seconds: int
|
||||
|
||||
|
||||
@dataclass
|
||||
class Config:
|
||||
email_accounts: List[EmailAccount]
|
||||
ai: AIConfig
|
||||
telegram: TelegramConfig
|
||||
polling: PollingConfig
|
||||
|
||||
|
||||
def load_config(path: str) -> Config:
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
raw = yaml.safe_load(f)
|
||||
|
||||
accounts = [EmailAccount(**a) for a in raw["email_accounts"]]
|
||||
ai = AIConfig(**raw["ai"])
|
||||
tg = TelegramConfig(**raw["telegram"])
|
||||
polling = PollingConfig(**raw["polling"])
|
||||
|
||||
return Config(
|
||||
email_accounts=accounts,
|
||||
ai=ai,
|
||||
telegram=tg,
|
||||
polling=polling,
|
||||
)
|
||||