A Telegram bot — like Stickers, but for audio and video messages.
A single admin (ADMIN_ID) manages memes via direct messages to the bot:
/add— add an audio or video to the database:- first forward/upload the media, then give it a name (any text) and an optional emoji;
- the bot stores the Telegram
file_idfor later reuse; - send
/cancel(or tap ❌ Отмена) at any step to abort, and/skipto leave the emoji empty.
/list— the management hub: tap a meme to rename it, change its emoji, or delete it (with an inline confirmation and a media preview). Each meme shows its all-time send count. (/deleteopens the same hub.)/users— list users with their usage count and approve/revoke them via inline buttons (relevant whenREQUIRE_APPROVALis on).
- Inline mode — type
@botnamein any chat, pick a meme, and the bot sends the saved audio or video. Type text after the mention to search by name or emoji; with no text, results are ordered by all-time popularity (most-sent first). @botname stats— show the Top-3 most-sent memes of all time.@botname userstats— show the Top-3 most active users of all time.
Set REQUIRE_APPROVAL=true to gate inline usage behind admin approval. Unapproved
users see "Ожидайте разрешение администратором" instead of memes, and the admin
approves them with /users. When the flag is off (default), anyone may use the bot.
Per-user and per-meme send counts are tracked whenever a meme is sent (powering the
stats/userstats leaderboards). This relies on Telegram delivering
chosen_inline_result updates, so enable inline feedback for the bot in
@BotFather (/setinlinefeedback).
By default, docker-compose.yml pulls the prebuilt image from
ghcr.io/leitosama/tg-audiomeme:latest.
cp .env.example .env
# fill in BOT_TOKEN and ADMIN_ID in .env
docker compose up -dTo build the image locally instead of pulling it from the registry:
docker compose up -d --buildThe database is stored in the ./db volume on the host.
| Variable | Required | Default | Description |
|---|---|---|---|
BOT_TOKEN |
yes | — | Bot token from @BotFather. |
ADMIN_ID |
yes | — | Telegram ID of the single admin. |
DB_PATH |
no | ./db/audio_meme.db |
Path to the SQLite file. |
TG_API_URL |
no | — | Custom Bot API endpoint (e.g. a self-hosted Bot API server). |
REQUIRE_APPROVAL |
no | false |
Gate inline usage behind admin approval (see above). |
See .env.example for a template.
Requires Python 3.12+.
python -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txtRun the bot (variables can be passed inline):
BOT_TOKEN=... ADMIN_ID=... python main.pyQuality checks (the same ones CI runs):
ruff check . # linter
ruff format --check . # formatting
mypy main.py # types (strict, configured in pyproject.toml)
pytest # tests + coverageGitHub Actions (.github/workflows/ci.yml):
- On every push and pull request, a single
checkjob runsruff(lint + format),mypy(strict), andpytest(with coverage). - On push to
main, after all checks pass, a multi-platform Docker image (linux/amd64,linux/arm64) is built and published toghcr.io/leitosama/tg-audiomemewith the tagslatestandsha-<commit>.
main is production: there is no separate staging environment and no release
versioning — working code ships straight to main.
All memes are stored in SQLite (./db/audio_meme.db by default).
The memes table:
id— unique identifier;name— meme name (any text, unique);file_id— Telegramfile_idused for caching;media_type— type:audioorvideo;emoji— optional emoji shown in the inline results and the admin list;count— all-time number of times the meme has been sent;created_at— date added.
The users table:
userid— Telegram user id (primary key);displayname— the user's first name, refreshed on each use;approved— whether the user may send memes (only enforced whenREQUIRE_APPROVALis on);count— number of memes the user has sent.
See LICENSE.