From 2bd851a426ffa7ec0e4fb2c829ae00e2009e645c Mon Sep 17 00:00:00 2001 From: Yanxin Lu Date: Wed, 11 Feb 2026 12:38:36 -0800 Subject: [PATCH] vault backup: 2026-02-11 12:38:36 --- notes/martial_arts/TELEGRAM_BOT_PLAN.md | 141 ++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 notes/martial_arts/TELEGRAM_BOT_PLAN.md diff --git a/notes/martial_arts/TELEGRAM_BOT_PLAN.md b/notes/martial_arts/TELEGRAM_BOT_PLAN.md new file mode 100644 index 0000000..98d3b79 --- /dev/null +++ b/notes/martial_arts/TELEGRAM_BOT_PLAN.md @@ -0,0 +1,141 @@ +# Plan: Telegram Bot for Martial Arts Note Conversion + +## Goal +Build a Telegram bot (`bot.py`, ~100 lines of Python) that receives photos of handwritten martial arts notes, uses Claude API to transcribe them, and commits the resulting markdown files to the Gitea repo on your VPS. + +## How It Works + +``` +Your Phone (Telegram) bot.py (VPS) External +───────────────── ──────────── ──────── +Send photos Bot polls Telegram ─────────→ Telegram API + ←──────────── Download photos + Send to Claude API ───────→ Claude (vision) + ← JSON response ←───────── Returns markdown + + art/instructor/date + Create file via ──────────→ Gitea API (localhost) + Gitea API +Reply "Done!" ←──────────── +``` + +## User Flow + +1. Finish martial arts class, take photos of notebook pages +2. Open Telegram, send photos to your bot +3. Bot replies: "Done! Committed `八极拳/baji-2025.02.12-vincent.md`" +4. Next time you open Obsidian or pull the repo, the note is there + +## Tech Stack + +- **Python 3** (already on VPS) with 3 libraries: + - `python-telegram-bot` — polls Telegram for photos (no port/SSL needed) + - `anthropic` — send photos to Claude for transcription + - `requests` — call Gitea API (localhost) +- **Runs on**: your Vultr VPS, in a tmux/screen session +- **Cost**: only Claude API usage (~$0.01-0.05 per set of photos) + +## Three Tokens (one-time setup) + +1. **Telegram bot token** — message @BotFather on Telegram, free +2. **Claude API key** — from console.anthropic.com +3. **Gitea API token** — from your Gitea instance (Settings > Applications > Generate Token) + +## Code Structure + +Single-file bot (`bot.py`) with clear separation between handlers. To add new features later, add a new handler function and register it — no restructuring needed. + +### Structure of bot.py +```python +# --- Config --- +# Load .env tokens + +# --- Handlers --- +# Each feature is a handler function registered with the bot + +async def handle_photos(update, context): + """Martial arts note conversion: photos → markdown → Gitea""" + ... + +# async def handle_future_feature(update, context): +# """Add new features here""" +# ... + +# --- Main --- +# Register handlers and start polling +app.add_handler(MessageHandler(filters.PHOTO, handle_photos)) +# app.add_handler(...) # register new handlers here +app.run_polling() +``` + +### 1. `handle_photos()` — Telegram handler +- Triggered when user sends photos +- Groups multiple photos sent within 30 seconds as pages of one lesson +- Downloads photos from Telegram +- Calls `transcribe()` then `commit_to_gitea()` +- Replies with confirmation + +### 2. `transcribe(photos)` — Claude API call +- Sends all photos to Claude API in one vision call +- Prompt asks Claude to: + - Transcribe the handwritten notes (English + Chinese) + - Identify: martial art, instructor, date, lesson number + - Return structured JSON with metadata + full markdown +- Uses the same format template and title conventions from `CONVERSION_PLAN.md` + +### 3. `commit_to_gitea(metadata, markdown)` — Gitea API call +- Determines directory from art type: + - FMA/Silat/SEAMA → `notes/martial_arts/FMA/` + - 八极拳 → `notes/martial_arts/八极拳/` + - 劈挂拳 → `notes/martial_arts/八极拳/` + - Other → `notes/martial_arts/` +- Constructs filename: `--.md` +- Calls Gitea API to create the file: + ``` + POST http://localhost:8003/api/v1/repos/{owner}/{repo}/contents/{filepath} + Body: { "content": base64(markdown), "message": "Add note: ..." } + ``` + +## Files to Create + +``` +telegram-bot/ +└── bot.py # Everything in one file (config + logic) +``` + +## Config + +Tokens are defined at the top of `bot.py`: +```python +# --- Config (edit these) --- +TELEGRAM_TOKEN = "your-telegram-token" +ANTHROPIC_API_KEY = "your-claude-key" +GITEA_URL = "http://localhost:8003" +GITEA_TOKEN = "your-gitea-token" +GITEA_REPO = "lyx/obsidian-yanxin" +``` +**Note**: Since tokens are in the source file, don't commit `bot.py` to a public repo. Your Gitea instance is private, so this is fine there. + +## Deployment + +1. Create Telegram bot via @BotFather +2. Get Claude API key from console.anthropic.com +3. Generate Gitea API token from your Gitea instance +4. On the VPS: + ```bash + pip install python-telegram-bot anthropic requests + # Copy bot.py to the VPS and edit the config section at the top with your tokens + python bot.py # run in tmux/screen to keep alive + ``` + +## Resource Usage + +- **Memory**: ~30MB Python process +- **CPU**: Near zero when idle +- **Fine for 1vCPU / 2GB VPS** + +## Verification + +1. Send a test photo of handwritten notes to the bot on Telegram +2. Bot replies with filename and summary +3. Check Gitea web UI — new `.md` file appears in the correct directory +4. Pull in Obsidian on your computer — note shows up with correct frontmatter