# Telegram Channel Monitor

Async channel monitor that polls Telegram channels, analyzes messages via LLM (DeepSeek structured output), and sends alerts.

## Architecture

```
monitor/
├── __init__.py      # AsyncMonitorMixin + exports
├── _config.py       # MonitorConfig (Pydantic)
├── _types.py        # MonitorAlert, MessageAnalysis, BatchAnalysis
├── _analyzer.py     # Default LLM analyzer factory (sdk.parse)
├── _notifier.py     # Notifier — sends alerts via MTProto or bot
├── _poller.py       # Parallel channel polling (asyncio.gather)
├── _monitor.py      # ChannelMonitor — async iterator + run()
└── _formatter.py    # HTML formatting for bot messages
```

## How It Works

1. **Polling** (`_poller.py`): All channels polled in parallel via `asyncio.gather`. Each channel tracks its `min_id` offset.
2. **Analysis** (`_analyzer.py`): Messages batched per channel, sent to LLM with structured output (`BatchAnalysis` Pydantic model). Semaphore limits concurrent LLM calls.
3. **Alerts** (`_monitor.py`): Matching messages converted to `MonitorAlert` and pushed to `asyncio.Queue`.
4. **Notification** (`_notifier.py`): Alerts sent to `chat_ids` via MTProto (`account_send_message`) or bot.

## Usage

```python
from sdkrouter import AsyncSDKRouter

sdk = AsyncSDKRouter(api_key="sk_live_...")

# Bot mode — auto-notify
monitor = sdk.telegram.monitor(
    channels=["@forklogAI"],
    topics=["new token listing"],
    chat_ids=["me"],
)
await monitor.run()

# Iterator mode — custom handling
async for alert in sdk.telegram.monitor(
    channels=["@forklogAI"],
    topics=["crypto regulation"],
):
    print(alert.summary)
```

## Custom Analyzer

Replace LLM with any `async (channel, messages, topics) -> list[MonitorAlert]`:

```python
async def my_filter(channel, messages, topics):
    return [MonitorAlert(...) for m in messages if matches(m)]

monitor = sdk.telegram.monitor(..., analyzer=my_filter)
```
