\# CLAUDE.md - Project Pravda \## Overview \*\*Pravda\*\* is a Python-based Dockerized service that monitors Donald Trump's Truth Social feed using the `truthbrush` library. It relays posts to Discord via Webhooks with intelligent media handling (transcoding/splitting) and supports interactive message components. \## Tech Stack \* \*\*Language:\*\* Python 3.12+ \* \*\*Core Libs:\*\* `truthbrush`, `requests`, `fastapi`, `uvicorn`, `ffmpeg-python` \* \*\*System Tools:\*\* `ffmpeg` (installed in container) \* \*\*Deployment:\*\* Docker, Gitea Actions \## Architecture The application runs two concurrent processes: 1\. \*\*The Poller:\*\* Loops infinitely, checking `truthbrush` for new posts. Processed posts are cached (SQLite/File) to prevent duplicates. 2\. \*\*The Server:\*\* A FastAPI instance listening on port \*\*8080\*\* to handle Discord Interaction Webhooks (button clicks). \## Commands \### Local Development ```bash \# Install dependencies pip install -r requirements.txt \# Run locally (requires ENV vars set) python main.py \# Run unit tests pytest ``` \### Docker Operations ```bash \# Build image docker build -t pravda . \# Run in background (Poller + Server) docker run -d \\   -e DISCORD\_WEBHOOK="your\_webhook\_url" \\   -e DISCORD\_PUBLIC\_KEY="your\_app\_public\_key" \\   -v $(pwd)/data:/data \\   -p 8080:8080 \\   pravda \# Manual Invocation (One-off relay of specific post) \# Overrides normal execution loop docker run --rm \\   -e DISCORD\_WEBHOOK="your\_webhook\_url" \\   pravda https://truthsocial.com/@realDonaldTrump/posts/123456789 ``` \## Environment Variables | Variable | Description | Required | | --- | --- | --- | | `DISCORD\_WEBHOOK` | The Discord Webhook URL for posting messages. | Yes | | `DISCORD\_APPLICATION\_ID` | App ID (for component construction). | Yes | | `DISCORD\_PUBLIC\_KEY` | Public Key for verifying interaction signatures. | Yes (if Server enabled) | | `POLL\_INTERVAL` | Seconds between checks (default: `300`). | No | | `TRUTH\_USER` | Target username (default: `realDonaldTrump`). | No | | `DB\_PATH` | Path to SQLite DB for tracking seen IDs (default: `/data/seen.db`). | No | \## Application Logic Requirements \### 1. Media Handling (The "Smart" Relay) \* \*\*Images:\*\* Download and attach directly. \* \*\*Videos:\*\* \* \*\*Must\*\* use `ffmpeg` to re-encode to `H.264/AAC` (MP4 container) for maximum Discord compatibility. \* \*\*Constraint:\*\* Output file must be `< 50MB` (Discord Nitro limit safeguard). \* \*\*Logic:\*\* If > 50MB, attempt to downscale resolution or lower bitrate. \* \*\*Limits:\*\* \* Discord allows max 10 attachments per message. \* Discord allows max 2000 chars per message. \* \*\*Splitting:\*\* If a post exceeds these limits, split the content into a thread or sequential messages. "Part 1/X" style. \### 2. Interaction Handler (FastAPI) \* Expose `POST /interactions`. \* Verify Ed25519 signature using `DISCORD\_PUBLIC\_KEY`. \* \*\*Component 1 (Delete):\*\* Check if user has `MANAGE\_MESSAGES` permission (or allow-list). Delete the webhook message. \* \*\*Component 2 (Raw):\*\* Reply with `flags: 64` (Ephemeral) containing the raw JSON snippet of the post. \### 3. Gitea Action Workflow Create `.gitea/workflows/build-push.yaml`: \* \*\*Trigger:\*\* On `push` to any branch. \* \*\*Steps:\*\* 1\. Checkout code. 2\. Login to Gitea Registry using `${{ secrets.REGISTRY\_USERNAME }}` and `${{ secrets.REGISTRY\_PASSWORD }}`. 3\. Build Docker image. 4\. Tag: `gitea.stevedudenhoeffer.com/steve/pravda:${{ gitea.ref\_name }}`. 5\. If branch is `main`, also tag `:latest`. 6\. Push all tags. \## Dockerfile Specification \* \*\*Base:\*\* `python:3.12-slim` \* \*\*System Deps:\*\* `ffmpeg`, `git` (needed for truthbrush?) \* \*\*Entrypoint:\*\* A script `entrypoint.sh` that detects arguments. \* If args provided (URL), run "One-off Mode". \* If no args, run "Daemon Mode" (Poller + Uvicorn). \## Code Style \* \*\*Formatter:\*\* `black` \* \*\*Linter:\*\* `ruff` \* \*\*Typing:\*\* Strong typing enforced (`mypy`). \* \*\*Error Handling:\*\* Never crash the poller loop on a network error. Log to `stderr` and retry. \## Example Interaction Payload (JSON) When sending the webhook, include components: ```json {   "content": "Post text here...",   "components": \[   {   "type": 1,   "components": \[   {   "type": 2,   "style": 4,   "label": "Delete",   "custom\_id": "delete\_msg"   },   {   "type": 2,   "style": 2,   "label": "View Raw",   "custom\_id": "view\_raw"   },   {   "type": 2,   "style": 5,   "label": "Original Post",   "url": "https://truthsocial.com/..."   }   ]   }   ] } ```