initial commit
This commit is contained in:
322
CLAUDE.md
Normal file
322
CLAUDE.md
Normal file
@@ -0,0 +1,322 @@
|
||||
\# 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/..."
|
||||
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user