feat: add telegram notifier
This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
# Notify Telegram (Codex)
|
||||||
|
|
||||||
|
Send Codex completion summaries to Telegram with safe Markdown rendering and stable list bullets.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
1. Ensure `uv` is installed.
|
||||||
|
2. Copy the script into your repo (already in this folder).
|
||||||
|
3. Create your Telegram creds file at `~/.codex/telegram.json`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"bot_token": "123456:ABCDEF...",
|
||||||
|
"chat_id": "462722"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configure
|
||||||
|
|
||||||
|
Add a `notify` entry to `~/.codex/config.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
notify = ["uv", "run", "/absolute/path/to/agents/codex/notify_telegram/notify_telegram.py"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- The script reads `last-assistant-message` and treats it as Markdown.
|
||||||
|
- Markdown is rendered to HTML, converted to Telegram text/entities via `sulguk`, then posted with `requests`.
|
||||||
|
- List bullets are normalized from `•` to `-` to keep Telegram output consistent.
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
- `notify_telegram.py`: the notifier script
|
||||||
|
- `telegram.json.example`: sample credentials file
|
||||||
|
- `config.toml.example`: sample Codex `notify` config line
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
notify = ["uv", "run", "/Users/YOU/path/to/agents/codex/notify_telegram/notify_telegram.py"]
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# /// script
|
||||||
|
# requires-python = ">=3.10"
|
||||||
|
# dependencies = ["requests", "markdown-it-py", "sulguk"]
|
||||||
|
# ///
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from markdown_it import MarkdownIt
|
||||||
|
from sulguk import transform_html
|
||||||
|
|
||||||
|
CREDS_PATH = Path.home() / ".codex" / "telegram.json"
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
creds = json.loads(CREDS_PATH.read_text(encoding="utf-8"))
|
||||||
|
bot_token = creds["bot_token"]
|
||||||
|
chat_id = str(creds["chat_id"])
|
||||||
|
|
||||||
|
payload = json.loads(sys.argv[1])
|
||||||
|
|
||||||
|
md = payload["last-assistant-message"].rstrip()
|
||||||
|
thread_id = payload.get("thread-id")
|
||||||
|
cwd = payload.get("cwd")
|
||||||
|
prompt = (payload.get("input-messages") or [""])[-1].rstrip()
|
||||||
|
|
||||||
|
footer = "\n".join(
|
||||||
|
line
|
||||||
|
for line in [
|
||||||
|
"---",
|
||||||
|
f"- cwd: `{cwd}`" if cwd else "",
|
||||||
|
f"- thread: `{thread_id}`" if thread_id else "",
|
||||||
|
f"- prompt: `{prompt}`" if prompt else "",
|
||||||
|
]
|
||||||
|
if line
|
||||||
|
)
|
||||||
|
|
||||||
|
md_full = md if not footer else f"{md}\n\n{footer}"
|
||||||
|
|
||||||
|
html = MarkdownIt("commonmark", {"html": False}).render(md_full)
|
||||||
|
result = transform_html(html)
|
||||||
|
|
||||||
|
# Use "-" instead of "•" for list markers (keep offsets stable: 1 char -> 1 char)
|
||||||
|
text = re.sub(r"(?m)^(\s*)• ", r"\1- ", result.text)
|
||||||
|
|
||||||
|
requests.post(
|
||||||
|
f"https://api.telegram.org/bot{bot_token}/sendMessage",
|
||||||
|
json={
|
||||||
|
"chat_id": chat_id,
|
||||||
|
"text": text,
|
||||||
|
"entities": result.entities,
|
||||||
|
"disable_web_page_preview": True,
|
||||||
|
},
|
||||||
|
timeout=15,
|
||||||
|
).raise_for_status()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"bot_token": "123456:ABCDEF...",
|
||||||
|
"chat_id": "462722"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user