Files
pravda/CLAUDE.md
2026-01-23 00:53:46 -05:00

323 lines
5.0 KiB
Markdown

\# 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
{
&nbsp; "content": "Post text here...",
&nbsp; "components": \[
&nbsp; {
&nbsp; "type": 1,
&nbsp; "components": \[
&nbsp; {
&nbsp; "type": 2,
&nbsp; "style": 4,
&nbsp; "label": "Delete",
&nbsp; "custom\_id": "delete\_msg"
&nbsp; },
&nbsp; {
&nbsp; "type": 2,
&nbsp; "style": 2,
&nbsp; "label": "View Raw",
&nbsp; "custom\_id": "view\_raw"
&nbsp; },
&nbsp; {
&nbsp; "type": 2,
&nbsp; "style": 5,
&nbsp; "label": "Original Post",
&nbsp; "url": "https://truthsocial.com/..."
&nbsp; }
&nbsp; ]
&nbsp; }
&nbsp; ]
}
```