# icherniukh/mr-prompter-bot architecture

> Architecture diagram of the GitHub repository icherniukh/mr-prompter-bot, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-17). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/icherniukh/mr-prompter-bot
- Repository: https://github.com/icherniukh/mr-prompter-bot

## Overview

1. This repository actually contains two related execution paths:
   - a legacy Telegram bot for batch watermark/overlay removal, implemented under `src/`
   - a newer standalone Gemini 2.5 Flash Image tool under `scripts/`, which the README says is the current recommended path

2. The legacy bot is the main system architecture to diagram if you want the deployed service. Its entrypoint is `src/main.py`, which wires together configuration, persistence, Telegram handlers, and the image-editing engine.

3. The request flow in the legacy bot is:
   user sends one or more images to Telegram → `handlers.py` groups and routes the batch → `engine.py` sends each image independently to an image-output model → cleaned images are returned to Telegram one-for-one.
   Captions are ignored, and the instruction is fixed in code rather than user-provided.

4. The bot has a hard split between free-tier processing and user-owned processing:
   - a host-provided OpenRouter key can be used for the first 25 images per user
   - after that, the user must add their own OpenRouter key via `/setup`
   - `/model`, `/forget`, `/status`, and `/cancel` manage that state
   This free-tier limit is enforced atomically in the database so concurrent batches cannot over-grant slots.

5. Persistence is centered on SQLite via `aiosqlite` in `src/database.py`. The database stores per-user state such as:
   - encrypted API key
   - selected model
   - cumulative free-image usage
   - reservation/refund state for the free tier
   The README indicates the encryption key is stored separately in `data/secret.key`, and the database file is locked down on disk.

6. The engine boundary is the external image-edit provider. In the legacy bot, `src/engine.py` uses `httpx` to call OpenRouter image-editing models, not a text-only LLM. The repo emphasizes that the task is image transformation, so the model must return edited images rather than textual descriptions.

7. Configuration is handled in `src/config.py` and `.env`. It controls:
   - Telegram/OpenRouter credentials
   - default model selection and model shortlist
   - host free-tier availability
   - runtime paths such as `data/`
   The architecture depends on environment-driven deployment, especially for keys and model selection.

8. The standalone Gemini tool in `scripts/gemini_25_free_watermark_remover.py` is a separate local pipeline. It processes files/folders directly instead of going through Telegram, and uses prompt files from `prompts/` such as `conservative-watermark-removal.txt`. That path is simpler: local inputs → Gemini API → cleaned images on disk.

9. The `scripts/evaluate_image_models.py` utility suggests an evaluation loop around model choice. Combined with the `prompts/` directory, this repo is set up not just as a bot, but as a model-comparison workspace for testing watermark-removal quality and tradeoffs.

10. Deployment is handled by `run_bot.sh` and `deploy/mr-prompter-bot.service`. The run script bootstraps a virtualenv and loads `.env`; the systemd unit is the server-side wrapper for the legacy Telegram bot. Operational logs are written under `data/logs/` with rotation for postmortem analysis.

11. The test suite is architecture-relevant because it validates the key boundaries:
   - configuration parsing
   - database behavior, including the free-tier concurrency regression
   - engine behavior for success and failure cases
   - handler routing for free-tier exhaustion, unlimited own-key usage, and refund-on-failure
   This indicates the system’s most important invariants are around state management and external API error handling.

12. In diagram terms, the main components are: Telegram client/UI, handler layer, SQLite-backed user state store with encrypted secrets, OpenRouter image-edit API, and the standalone Gemini local tool as an alternate execution path. The key data flow is “batch image upload → per-image edit call → per-image response,” with quota and key-management checks happening before and after each edit.

Main entry points: [`src/main.py`](https://github.com/icherniukh/mr-prompter-bot/blob/main/src/main.py) (Main), [`src/handlers.py`](https://github.com/icherniukh/mr-prompter-bot/blob/main/src/handlers.py) (Handlers), [`src/engine.py`](https://github.com/icherniukh/mr-prompter-bot/blob/main/src/engine.py) (Engine), [`src/database.py`](https://github.com/icherniukh/mr-prompter-bot/blob/main/src/database.py) (Database)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_legacy_bot["Legacy Telegram Bot"]
  node_src_main["Main<br/>entrypoint<br/>[main.py]"]
  node_src_handlers["Handlers<br/>telegram routing<br/>[handlers.py]"]
  node_src_engine["Engine<br/>image edit client<br/>[engine.py]"]
  node_src_database[("Database<br/>sqlite state store<br/>[database.py]")]
  node_src_config["Config<br/>[config.py]"]
  node_telegram(("Telegram<br/>chat client"))
  node_openrouter{{"OpenRouter<br/>image-edit api"}}
  node_data_dir[("Data Files<br/>runtime storage")]
end

subgraph group_local_tools["Standalone Tools"]
  node_gemini_tool["Gemini Tool<br/>local pipeline"]
  node_eval_tool["Model Eval<br/>comparison utility"]
  node_prompts["Prompts<br/>prompt corpus"]
  node_gemini_api{{"Gemini API<br/>image model api"}}
  node_filesystem_inputs[("Local Files<br/>inputs/outputs")]
end

subgraph group_ops["Deployment"]
  node_run_bot["Run Script<br/>bootstrap<br/>[run_bot.sh]"]
  node_systemd_service["Systemd Unit<br/>service wrapper"]
end

node_telegram -->|"messages"| node_src_main
node_src_main -->|"load settings"| node_src_config
node_src_main -->|"register"| node_src_handlers
node_src_main -->|"open store"| node_src_database
node_src_main -->|"wire client"| node_src_engine
node_src_handlers -->|"check quota"| node_src_database
node_src_handlers -->|"edit batch"| node_src_engine
node_src_handlers -->|"reply images"| node_telegram
node_src_engine -->|"image edit"| node_openrouter
node_src_database -->|"persist"| node_data_dir
node_src_config -->|"paths"| node_data_dir
node_run_bot -->|"launch"| node_src_main
node_systemd_service -->|"service start"| node_run_bot
node_gemini_tool -->|"read/write"| node_filesystem_inputs
node_gemini_tool -->|"load prompt"| node_prompts
node_gemini_tool -->|"generate"| node_gemini_api
node_eval_tool -.->|"compare prompts"| node_prompts
node_eval_tool -.->|"benchmark"| node_gemini_api
node_src_database -.->|"state result"| node_src_handlers
node_src_engine -.->|"success/fail"| node_src_handlers

click node_src_main "https://github.com/icherniukh/mr-prompter-bot/blob/main/src/main.py"
click node_src_handlers "https://github.com/icherniukh/mr-prompter-bot/blob/main/src/handlers.py"
click node_src_engine "https://github.com/icherniukh/mr-prompter-bot/blob/main/src/engine.py"
click node_src_database "https://github.com/icherniukh/mr-prompter-bot/blob/main/src/database.py"
click node_src_config "https://github.com/icherniukh/mr-prompter-bot/blob/main/src/config.py"
click node_data_dir "https://github.com/icherniukh/mr-prompter-bot/tree/main/data"
click node_run_bot "https://github.com/icherniukh/mr-prompter-bot/blob/main/run_bot.sh"
click node_systemd_service "https://github.com/icherniukh/mr-prompter-bot/blob/main/deploy/mr-prompter-bot.service"
click node_gemini_tool "https://github.com/icherniukh/mr-prompter-bot/blob/main/scripts/gemini_25_free_watermark_remover.py"
click node_eval_tool "https://github.com/icherniukh/mr-prompter-bot/blob/main/scripts/evaluate_image_models.py"
click node_prompts "https://github.com/icherniukh/mr-prompter-bot/tree/main/prompts"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_src_main,node_src_handlers,node_src_engine,node_src_database,node_src_config,node_telegram,node_openrouter,node_data_dir toneBlue
class node_gemini_tool,node_eval_tool,node_prompts,node_gemini_api,node_filesystem_inputs toneAmber
class node_run_bot,node_systemd_service toneMint
```

## Components

### Legacy Telegram Bot

Deployed batch image-removal service under src/

- [Main](https://github.com/icherniukh/mr-prompter-bot/blob/main/src/main.py): entrypoint · Wires configuration, handlers, database, and engine for the Telegram bot · `src/main.py`
- [Handlers](https://github.com/icherniukh/mr-prompter-bot/blob/main/src/handlers.py): telegram routing · Groups batch uploads, routes commands, and manages quota/key state transitions · `src/handlers.py`
- [Engine](https://github.com/icherniukh/mr-prompter-bot/blob/main/src/engine.py): image edit client · Calls external image-edit models and returns edited images one-for-one · `src/engine.py`
- [Database](https://github.com/icherniukh/mr-prompter-bot/blob/main/src/database.py): sqlite state store · Async SQLite persistence for user state, free-tier accounting, and encrypted secrets · `src/database.py`
- [Config](https://github.com/icherniukh/mr-prompter-bot/blob/main/src/config.py): env config · Loads environment-driven settings, model shortlist, paths, and credentials · `src/config.py`
- **Telegram**: chat client · User-facing messaging and image upload interface
- **OpenRouter**: image-edit api · External provider used for the legacy bot's per-image transformations
- [Data Files](https://github.com/icherniukh/mr-prompter-bot/tree/main/data): runtime storage · Persistent on-disk data such as logs, database, and secret key material · `data`

### Standalone Tools

Local Gemini workflow and model evaluation utilities under scripts/ and prompts/

- [Gemini Tool](https://github.com/icherniukh/mr-prompter-bot/blob/main/scripts/gemini_25_free_watermark_remover.py): local pipeline · Standalone file/folder workflow using Gemini 2.5 Flash Image · `scripts/gemini_25_free_watermark_remover.py`
- [Model Eval](https://github.com/icherniukh/mr-prompter-bot/blob/main/scripts/evaluate_image_models.py): comparison utility · Utility for comparing model quality and tradeoffs · `scripts/evaluate_image_models.py`
- [Prompts](https://github.com/icherniukh/mr-prompter-bot/tree/main/prompts): prompt corpus · Instruction files used by the standalone tool and evaluation workflows · `prompts`
- **Gemini API**: image model api · External model endpoint used by the standalone local pipeline
- **Local Files**: inputs/outputs · Direct file and folder inputs and on-disk cleaned outputs

### Deployment

Runtime bootstrap and systemd service wrapper

- [Run Script](https://github.com/icherniukh/mr-prompter-bot/blob/main/run_bot.sh): bootstrap · Bootstraps the virtualenv and loads .env for local/server execution · `run_bot.sh`
- [Systemd Unit](https://github.com/icherniukh/mr-prompter-bot/blob/main/deploy/mr-prompter-bot.service): service wrapper · Server-side service definition for the legacy Telegram bot · `deploy/mr-prompter-bot.service`

## Connections

- Telegram → Main: messages · Users send batches and commands into the bot entrypoint
- Main → Config: load settings · Initializes runtime from environment and path configuration
- Main → Handlers: register · Wires Telegram update handling and command routes
- Main → Database: open store · Creates the persistence layer used by handlers and quota logic
- Main → Engine: wire client · Connects the editing engine into the request flow
- Handlers → Database: check quota · Reads and updates user state, key ownership, and reservations
- Handlers → Engine: edit batch · Sends each image independently for transformation
- Handlers → Telegram: reply images · Returns cleaned images one-for-one to the user
- Engine → OpenRouter: image edit · Calls the external provider for edited image outputs
- Database → Data Files: persist · Stores SQLite data, encrypted secrets, and logs on disk
- Config → Data Files: paths · Defines runtime directories such as data/ and logs
- Run Script → Main: launch · Bootstraps and starts the legacy bot process
- Systemd Unit → Run Script: service start · Server wrapper that invokes the bootstrap script
- Gemini Tool → Local Files: read/write · Processes local files and writes cleaned images back to disk
- Gemini Tool → Prompts: load prompt · Uses prompt files to steer image-removal behavior
- Gemini Tool → Gemini API: generate · Calls Gemini 2.5 Flash Image for local image editing
- Model Eval → Prompts: compare prompts · Supports model and prompt comparison workflows
- Model Eval → Gemini API: benchmark · Runs evaluation against image model endpoints
- Database → Handlers: state result · Returns quota and ownership state for routing decisions
- Engine → Handlers: success/fail · Propagates image-edit outcomes for refund and retry handling
