Skip to content

astrovm/respondedorbot

Repository files navigation

respondedorbot

An AI-powered Telegram bot playing "el gordo" — a blunt, politically incorrect Argentine character who answers everything in a single lowercase phrase using Argentine slang.

t.me/respondedorbot

Features

  • AI chat: configurable personality with web search, powered by Qwen via OpenRouter
  • Streaming responses: AI replies stream token-by-token to Telegram (when no tools are active)
  • Chat memory with RediSearch: persistent conversation history, full-text search, automatic compaction
  • Incremental summaries: /resumen streams conversation summaries using Minimax, with automatic context compaction
  • Agentic tools: AI can call tools (price lookup, calculator, web fetch, task scheduling) via function calling
  • Market data: /prices, /usd, /petroleo, /devo, /powerlaw, /rainbow, /rulo, /eleccion
  • BCRA economic data: /bcra, /variables
  • Media: audio transcription (Whisper via Groq, with OpenRouter fallback) and image description (OpenRouter)
  • Scheduled tasks: /tareas, /tasks — create, list, and delete one-shot or recurring reminders via AI or inline buttons
  • AI credits billing: Telegram Stars (/topup, /balance, /transfer)
  • Link enrichment: URLs get metadata injected into AI context; social links auto-replaced (fxTwitter, fixupx, etc.)
  • Context injection: market data, weather, Hacker News top stories, and Buenos Aires time in every system prompt
  • Response cleanup: deduplication, prefix stripping, identity leak prevention

Quick Start

uv sync --locked
cp .env.example .env
# Edit .env with your keys
uv run --locked python run_polling.py

Configuration

Variable Description
BOT_SYSTEM_PROMPT Complete AI personality prompt
BOT_TRIGGER_WORDS Comma-separated keywords that trigger responses in groups
TELEGRAM_TOKEN Bot token from @BotFather
TELEGRAM_USERNAME Bot username
REDIS_HOST / REDIS_PORT / REDIS_PASSWORD Redis cache (requires RediSearch)
SUPABASE_POSTGRES_URL Pooled Supabase Postgres URL (for AI credits)
COINMARKETCAP_KEY CoinMarketCap API key
GROQ_API_KEY Paid Groq API key for transcription
GROQ_FREE_API_KEY Optional free-tier Groq key for transcription
OPENROUTER_API_KEY OpenRouter API key for chat/vision
CF_AIG_TOKEN Cloudflare AI Gateway token forwarded to OpenRouter requests
GIPHY_API_KEY Giphy API key for /gm and /gn
ADMIN_CHAT_ID Telegram chat ID for error reports
FRIENDLY_INSTANCE_NAME Instance name for admin reports

Provider contract

Use Provider Model
Chat OpenRouter qwen/qwen3.6-plus
Vision OpenRouter google/gemini-3.1-flash-lite-preview
Transcription Groq → OpenRouter fallback whisper-large-v3google/gemini-3.1-flash-lite-preview
Summary OpenRouter minimax/minimax-m2.7

Streaming: token streaming only when no tools/web-search are active. Tool-enabled requests return complete responses.

Commands

Command Aliases Description
/ask /pregunta, /che, /gordo AI chat (streaming)
/resumen /summary Stream conversation summary
/transcribe /describe Transcribe audio / describe image
/prices /price, /precios, /precio, /presio(s), /bresio(s), /brecio(s), /crypto, /criptos Crypto prices
/dolar /dollar, /usd Dollar rates (CriptoYa)
/petroleo /oil Oil prices
/acciones /stocks Stock prices
/eleccion /elecciones, /election, /elections Global Polymarket elections by liquidity
/mundial /worldcup Next 10 World Cup games on Polymarket
/devo - Arbitrage calculator (tarjeta vs crypto)
/rulo - Dollar arbitrage chains
/powerlaw - Bitcoin power law
/rainbow - Bitcoin rainbow chart
/satoshi /sat, /sats Satoshi value
/bcra /variables BCRA economic variables
/random - Random choice or number
/convertbase - Number base conversion
/comando /command Text → Telegram command
/time - Unix timestamp
/config - Chat settings (admin only in groups)
/topup - Buy AI credits with Telegram Stars
/balance - Show credit balance
/transfer - Transfer credits to group
/tareas /tasks Manage scheduled reminders
/gm - Good morning GIF
/gn - Good night GIF
/help - Command reference
/instance - Instance name

Architecture

Provider abstraction (api/providers/)

  • ProviderChain — tries providers in order until one succeeds
  • OpenRouterProvider — streaming + completion, primary chat model

Streaming (api/bot/streaming.py)

TelegramMessageStreamer edits Telegram messages every 400ms or 15+ new chars. Token streaming from OpenRouterProvider.stream() when no tools active. Falls back to complete response for tool-enabled requests.

AI service (api/ai/service.py)

AIService orchestrates credit reservation → model call → billing settlement:

  • Reserve: holds worst-case credits before AI call
  • Settle: calculates actual cost, charges/refunds difference
  • Refund: full return on failure, fallback, or empty response

Chat memory compaction

  • COMPACTION_THRESHOLD = 20 — compact when delta > 20 messages
  • COMPACTION_KEEP = 25 — retain last 25 messages
  • COMPACTION_THRESHOLD = 40 — compact when 40+ new messages
  • Incremental summaries from delta messages + prior summary
  • RediSearch index (idx:chat_messages) for full-text search and RAG retrieval

Billing & credits

  • User credits — personal balance
  • Group credits — shared pool subsidizing creditless users
  • Onboarding — 3 free credits for new users
  • Hourly limitcreditless_user_hourly_limit caps free messages per user per hour
  • Credit packs (Telegram Stars): 50→2500 credits with 50% bonus tiers

Response pipeline (api/ai/pipeline.py)

Sequential cleanup:

  1. Remove "gordo:" prefix
  2. Strip echoed context strings
  3. Remove identity leak prefixes (@user:)
  4. Deduplicate consecutive lines/sentences

Context injection

Every system prompt includes:

  • Market: top 3 cryptos + dollar rates (oficial, blue, mep, tarjeta, usdt)
  • Weather: Buenos Aires temp, rain probability, cloud cover
  • Hacker News: top 5 stories (title, points, comments)
  • Time: current Buenos Aires datetime

Project layout

  • api/ - application code
    • api/admin/ - admin commands, reporting, authorization
    • api/ai/ - AI orchestration, prompting, pricing, response cleanup
    • api/billing/ - credits, settlement, billing commands, Stars callbacks
    • api/bot/ - Telegram adapter, handlers, routing, streaming, chat config
    • api/cache/ - HTTP and Redis caching
    • api/core/ - configuration, constants, logging
    • api/links/ - URL metadata, replacement, and enrichment
    • api/markets/ - crypto, dollar, stocks, Polymarket, weather
    • api/media/ - image, audio, video, transcription, media cache
    • api/memory/ - chat history, retrieval, compaction, summaries
    • api/providers/ - AI provider abstraction (OpenRouter, ProviderChain)
    • api/tasks/ - task execution and scheduling
    • api/tools/ - agentic tool registry (crypto, calculator, web fetch, tasks)
    • api/services/ - persistence and low-level external adapters
    • api/utils/ - reusable helpers
    • api/index.py - application composition root and compatibility exports
  • quadlets/ - Podman Quadlet container definitions
  • systemd/ - systemd service and timer units
  • run_polling.py - bot entrypoint
  • run_maintenance.py - maintenance entrypoint
  • tests/ - test suite
  • Containerfile - container image definition

Deployment (Podman + systemd)

Prerequisites (Debian/Ubuntu)

sudo apt install -y podman uidmap dbus-user-session slirp4netns fuse-overlayfs
sudo useradd -m -s /bin/bash respondedorbot
sudo loginctl enable-linger respondedorbot

Setup (as respondedorbot user)

git clone https://github.com/astrovm/respondedorbot
cd respondedorbot

mkdir -p ~/.config/containers/systemd
cp quadlets/* ~/.config/containers/systemd/

mkdir -p ~/respondedorbot/workspace
cp .env.example ~/respondedorbot/.env
# Create ~/respondedorbot/workspace/SOUL.md and RULES.md manually.
# Edit ~/respondedorbot/.env - set REDIS_HOST=respondedorbot-redis
# Quadlet Redis uses redis-stack-server because the bot needs RediSearch (FT.CREATE / FT.SEARCH)

export XDG_RUNTIME_DIR=/run/user/$(id -u)
export DBUS_SESSION_BUS_ADDRESS=unix:path=${XDG_RUNTIME_DIR}/bus

systemctl --user daemon-reload
systemctl --user start respondedorbot-redis.service
systemctl --user start respondedorbot.service

The bot container mounts ~/respondedorbot/workspace read-only at /app/workspace. Both SOUL.md and RULES.md live outside Git and must be created on the VPS before starting the service. Alternatively, BOT_SYSTEM_PROMPT can provide the complete prompt through the environment.

The bundled Redis Quadlet uses the pinned redis/redis-stack-server:7.4.0-v8 image, not plain Redis, because chat memory search and compaction require RediSearch commands. Redis does not auto-update; upgrade the pinned version only after testing FT.CREATE and FT.SEARCH. The unit intentionally does not override the container command; it passes Redis tuning through REDIS_ARGS so the image can boot Redis Stack with its modules enabled.

Image publishing and rollback

The CI workflow runs Ruff, mypy, and the complete test suite before building the bot image. A successful push to main publishes both:

  • ghcr.io/astrovm/respondedorbot:latest for normal Podman auto-updates.
  • ghcr.io/astrovm/respondedorbot:sha-<full-commit-sha> for rollback.

To temporarily roll back the VPS to a known-good commit:

ROLLBACK_SHA=<full-commit-sha>
podman pull "ghcr.io/astrovm/respondedorbot:sha-${ROLLBACK_SHA}"
sed -i \
  "s|^Image=.*|Image=ghcr.io/astrovm/respondedorbot:sha-${ROLLBACK_SHA}|" \
  ~/.config/containers/systemd/respondedorbot.container
systemctl --user daemon-reload
systemctl --user restart respondedorbot.service
systemctl --user status respondedorbot.service --no-pager

The SHA tag prevents Podman auto-update from moving the bot forward. After the problem is fixed, return to automatic releases:

sed -i \
  "s|^Image=.*|Image=ghcr.io/astrovm/respondedorbot:latest|" \
  ~/.config/containers/systemd/respondedorbot.container
systemctl --user daemon-reload
systemctl --user restart respondedorbot.service

Persist across reboots

systemctl --user enable fails on Quadlet-generated units on some distros — use symlinks instead:

mkdir -p ~/.config/systemd/user/default.target.wants
ln -sf ~/.config/containers/systemd/respondedorbot.container \
  ~/.config/systemd/user/default.target.wants/respondedorbot.container
ln -sf ~/.config/containers/systemd/respondedorbot-redis.container \
  ~/.config/systemd/user/default.target.wants/respondedorbot-redis.container
systemctl --user daemon-reload

Maintenance timers

cp systemd/respondedorbot-maintenance.* ~/.config/systemd/user/
cp systemd/respondedorbot-podman-prune.* ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now respondedorbot-maintenance.timer
systemctl --user enable --now respondedorbot-podman-prune.timer

Useful commands

journalctl --user -fu respondedorbot.service
systemctl --user status respondedorbot.service --no-pager
systemctl --user stop respondedorbot.service respondedorbot-redis.service
systemctl --user enable --now podman-auto-update.timer
podman exec systemd-respondedorbot python /app/run_maintenance.py

Tests

uv run --locked pytest -q

About

Telegram bot AI based on Argentina internet culture

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages