39
Universal AI Telegram Bot
I wrote in my Telegram channel that I had long ago created a GPT in ChatGPT — 'Russian > English Corrector and Translator' — to help with learning English. It’s simple yet useful:
- Send an English word — you get a vocabulary card with a definition, part of speech, examples, etc.
- Send a Russian text — you get a direct translation with explanations of why it was translated that way.
- Send an English text — it’s checked for mistakes and style, and you get a corrected version with explanations.
But opening ChatGPT every time is inconvenient — it would be much more comfortable to receive the same functionality via Telegram.
I’ve also built a local Telegram emulator to test bots locally with webhooks.
Implementation
There’s not much point in describing the development process — as usual, everything was written with Cursor. I’ll better explain the internal design.
The program is written in Go and essentially acts as a proxy between Telegram and the AI. To connect to Telegram, you need a bot API token from @BotFather. To connect to the AI, you need an OpenAI‑compatible API. I use OpenRouter with a free model.
The bot has two simple commands, /start and /help, which it answers with messages defined in the config.
All other user messages are sent to the LLM, preceded by the prompt specified in the config.
No conversation context is stored or used, so you can’t chat with this bot in a multi-turn dialog — only single messages. Media and files aren’t supported yet either, so interaction is text‑only.
Installation and running
Since the program is in Go, GitHub builds binaries for all major systems right in the releases, and they require no additional dependencies. See the releases page for the current list: https://github.com/positron48/universal-ai-bot/releases.
You also need to place a .env configuration file next to the binary. An example with the full list of variables is available in the repository: https://github.com/positron48/universal-ai-bot/blob/master/env.example
Minimum required values:
TELEGRAM_TOKEN— the bot token obtained from @BotFather;AI_API_KEY— the API key to access the model API;AI_URL— the OpenAI‑compatible API URL of the model you’ll call (by default it points to OpenRouter, but you can even run lmstudio locally and try that);AI_MODEL— by defaultqwen/qwen3-coder:freefrom OpenRouter. Keep in mind that to use free models via API you usually need to enable training on your prompts and prompt logging, so this is the least confidential mode.
You’ll find even more parameters in my GitHub repo. You can configure it to work via webhook (long polling is used by default).
Message templates and the model’s system prompt are configured separately. For example, my settings look like this:
AI_PROMPT_FILE=prompts/english-teacher.txt
# Bot Messages Configuration (optional — uses defaults if not set)
BOT_START_MESSAGE='🇬🇧 Hi! I am your personal English teacher!\n\n📝 What I can do:\n• Correct mistakes in English text\n• Translate from Russian to English\n• Create word cards with explanations\n\n💡 Just send me a word or text to get started.'
BOT_HELP_MESSAGE='📚 Help for the English-teacher bot:\n\n🔤 One word → A word card with:\n• Part of speech\n• IPA transcription\n• Definition in Russian\n• Usage examples\n• Irregular forms (if applicable)\n\n📝 Russian text → Direct English translation with brief reasoning\n\n✍️ English text → Corrections with explanations and a suggested improved version'
BOT_UNKNOWN_COMMAND_MESSAGE='❓ Unknown command. Use /help to see what I can do.'
BOT_ERROR_MESSAGE='Sorry, an error occurred while processing your message. Please try again later.'
BOT_EMPTY_MESSAGE='Please send a non-empty message.'
The system prompt is also public and lives in the repository: https://github.com/positron48/universal-ai-bot/blob/master/prompts/english-teacher.txt
After all settings are in place, just run the binary — if everything is configured correctly, the bot will start working.
Deployment
I went a bit further: manually ensuring the binary is running and restarting it on crashes is not the way.
The repository also includes a detailed guide on setting up auto‑deployment to a server from GitHub (useful if you clone the repo and modify the code): https://github.com/positron48/universal-ai-bot/blob/master/DEPLOYMENT.md
In short, it seems to follow best practices for deployment from GitHub.
On the server (I use an Ubuntu VPS) you need to create a service user to run the bot. Grant it the necessary permissions and revoke unnecessary ones.
Then generate SSH keys for this user and store the private key in the repository’s Actions secrets along with the server connection details (where GitHub should connect).
An interesting thing I learned: via ~/.ssh/authorized_keys you can restrict which commands a user connecting over SSH may run. For deployment, for example:
# Add this line to ~/.ssh/authorized_keys
command="cd /path/to/your/bot && make update",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... deploy@your-domain.com
This allows only a single command during auto‑deploy: enter the bot directory and run make update (which downloads the latest release binary and restarts the systemd service on the server).
Finally, the bot itself is public — you can find it as @positroid_english_bot.
In addition to the AI bot repository I also prepared a barebones Telegram bot skeleton in Go — this is mainly useful for developers, as it implies modifying the code. It also works out of the box with simple commands — the AI bot is built on top of it.
No comments yet
-
YouTube Watch History Analysis
Ever wondered how much time you spend watching videos? Let's count it. -
Image2model with Tripo3D and Blender
Sometimes you want a drawn or AI-generated character to become real. -
Local Telegram Emulator
Have you ever written Telegram bots? -
Reviving Coat Hanger Bases
We have a couple of coat hangers with hangers at home, where clothes are conven… -
Cutlery Organizer
Organization is one of the areas where I periodically try to apply my skills.… -
Cross-posting Engineering DIY Content
I started going beyond my personal blog, it seems like some content deserves wi…