- 🤖 What Is Alisa?
- 🦊 Who Is Alisa Mikhailovna Kujou?
- ✨ Features
- 🎮 Commands
- 📊 How Stats Work
- 📡 How Broadcast Works
- 🚀 Quick Deploy
- 🔐 Configuration
- 🛡️ Security
- 🏗️ Project Structure
- 🧠 Architecture
- 🛠️ Development
- 🤝 Contributing
- 📈 Performance
- 🏆 Credits
- 📝 Changelog
- 📄 License
Alisa is a Telegram bot that automatically reacts to messages with curated emojis — making your chats more lively and fun.
How it works:
- Private chats → Reacts to every message you send
- Groups → Reacts randomly based on your configured level
- Channels → Reacts to every post
Add Alisa to any chat, and she quietly drops fitting reactions when the mood feels right. No spam, no commands needed — just vibes.
Хмпф… Not that you need my permission to add me.
Alisa Mikhailovna Kujou (アリサ・ミハイロヴナ・九条) is the female lead of "Tokidoki Bosotto Russia-go de Dereru Tonari no Alya-san" (Alya Sometimes Hides Her Feelings in Russian), a romantic comedy light novel and anime series.
| Full Name | Alisa Mikhailovna Kujou (Алиса Михайловна Кудзё) |
| Aliases | Alya, The Ice Queen |
| Heritage | Half-Russian, Half-Japanese |
| Family | Maria Kujou (Older Sister) |
| Role | Student Council Treasurer |
| Personality | Tsundere — proud, elegant, and sharp-tongued on the surface, but secretly caring and easily flustered |
| Signature Trait | Speaks her true feelings in Russian, believing no one around her can understand |
| Common Phrases | Хмпф (hmph), Хорошо (okay), Дурак (idiot), Спасибо (thank you), До свидания (goodbye) |
The character's defining trait — hiding emotions behind a language barrier — perfectly mirrors this bot's behavior: silently reacting to messages with the right emoji at the right time. Just like Alisa watches from a distance and slips in her true feelings in Russian, this bot observes your chats and drops reactions that say more than words.
Her tsundere personality — cold on the outside, warm on the inside — gives the bot its voice. Every message carries her pride, her wit, and those rare moments of genuine warmth.
"N-Not that I care about your chats or anything… Хмпф."
|
|
|
|
|
|
|
|
| Command | Description |
|---|---|
/start |
Welcome menu with quick links |
/help |
Full command reference with access levels |
/about |
Bot features, tech stack, and links |
/ping |
Check bot latency and response time |
/stats |
Live statistics — messages, reactions, uptime, top chats |
/reactions |
List currently enabled reaction emojis |
/donate |
Support the project |
| Command | Description |
|---|---|
/setreactions 👍 ❤ 🔥 |
Set custom reaction emojis for this chat |
/setreactions |
Reset to default global emoji set |
/pause |
Pause auto-reactions in this chat |
/resume |
Resume auto-reactions in this chat |
/randomlevel <0-10> |
Set reaction randomness for this chat |
/randomlevel |
View current random level |
/welcome |
Toggle welcome messages for new members |
/goodbye |
Toggle farewell messages when members leave |
| Command | Description |
|---|---|
/broadcast <message> |
Send a message to every chat (60s cooldown) |
/leave <chat_id> |
Remove the bot from any chat |
/remove <chat_id> |
Alias for /leave |
/chats |
List all active chats with status indicators |
/restrict <chat_id> |
Restrict a chat — bot stops reacting |
/unrestrict <chat_id> |
Remove restriction from a chat |
/setwebhook <url> |
Set webhook URL via Telegram |
/setwebhook |
View current webhook status and errors |
/log |
View the last 10 reactions sent |
The /stats command shows:
📊 Alisa Bot Stats
📨 Messages Processed: 1,247
💫 Reactions Sent: 983
💬 Unique Chats: 42
⏸️ Paused Chats: 2
🚫 Restricted Chats: 1
⏱️ Uptime: 3ʜ 24ᴍ 17s
🕐 Started: Mon, 12 May 2026 04:12:00 GMT
📋 Command Usage:
/start — 15
/help — 8
/ping — 23
/stats — 12
🏆 Top Chats (last 50 reactions):
1. Anime Lovers Group — 18
2. Dev Chat — 12
3. My Channel — 8
How it works:
- Every message the bot sees increments
messagesProcessed - Every successful reaction increments
reactionsSent - Every unique chat ID is stored in a
Set - Command usage is tracked per command name
- The last 50 reactions are stored in a rolling buffer
- Top chats counts reactions (not messages) from that buffer
- Chat names are cached from the last message in each chat
- Stats persist across restarts on Docker/Local (file) and Vercel (KV). On Cloudflare Workers, stats reset per invocation.
The /broadcast <message> command lets the bot owner send a message to every chat:
- You send
/broadcast Hey everyone! New update! 🎉 - Bot checks — are you the
OWNER_ID?- ❌ No → "This command is only available to the bot owner."
- ⏳ Cooldown active → "Wait Xs before next broadcast."
- ✅ Yes → Starts broadcasting
- Bot loops through every unique chat ID it has seen
- Sends your message to each one (Markdown supported)
- Reports back:
✅ Broadcast Complete!
📨 Sent: 47
❌ Failed: 3
Notes:
- 60-second cooldown between broadcasts to prevent spam
- Failed sends (bot kicked, chat deleted) are counted but don't stop the broadcast
- Reaches every chat since last restart
Or manually:
git clone https://github.com/Shineii86/AlisaReactionBot.git
cd AlisaReactionBot
npm install
npx wrangler deployNote: The
wrangler.tomlincludescompatibility_flags = ["nodejs_compat"]for Node.js API compatibility. Storage is in-memory only on Workers (no filesystem).
vercel --prodgit clone https://github.com/Shineii86/AlisaReactionBot.git
cd AlisaReactionBot
cp .env.example .env # Edit with your config
docker-compose up -dData persists across restarts via
./data:/app/datavolume mount. State stored indata/state.json.
Option A — Via Telegram (recommended):
/setwebhook https://your-worker.your-subdomain.workers.dev
Option B — Via curl:
curl -X POST "https://api.telegram.org/bot<BOT_TOKEN>/setWebhook" \
-H "Content-Type: application/json" \
-d '{"url": "https://your-worker.your-subdomain.workers.dev", "secret_token": "your_secret"}'Verify:
curl "https://api.telegram.org/bot<BOT_TOKEN>/getWebhookInfo"| Variable | Description | Example | Required |
|---|---|---|---|
BOT_TOKEN |
Telegram Bot API token from @BotFather | 123456:ABC-DEF... |
✅ |
BOT_USERNAME |
Bot username (without @) | AlisaReactionBot |
✅ |
EMOJI_LIST |
Reaction emojis (space or comma separated) | 👍 ❤ 🔥 🎉 👏 |
✅ |
RANDOM_LEVEL |
Reaction randomness for groups (0-10) | 5 |
❌ |
RESTRICTED_CHATS |
Chat IDs to exclude (comma separated) | -100123,456789 |
❌ |
OWNER_ID |
Telegram user ID for owner-only commands | 123456789 |
❌ |
WEBHOOK_SECRET |
Secret token for webhook validation | a1b2c3d4... |
❌ |
BOT_PHOTO |
Photo URL or Telegram file_id for bot messages | https://example.com/photo.jpg |
❌ |
PORT |
Server port for Docker/VPS | 3000 |
❌ |
Note: If
WEBHOOK_SECRETis not set, a random secret is auto-generated at startup. IfOWNER_IDis not set, owner-only commands are disabled. IfEMOJI_LISTis not set, the bot will not react to any messages.
Option 1: Upstash Redis (Free — 10,000 req/day, 256MB)
| Variable | Description | Required |
|---|---|---|
UPSTASH_REDIS_REST_URL |
Upstash Redis REST URL | ❌ |
UPSTASH_REDIS_REST_TOKEN |
Upstash Redis REST token | ❌ |
Sign up free at console.upstash.com, create a Redis database, copy the REST URL and token.
Option 2: Vercel KV (Paid — starts at $8/month)
| Variable | Description | Required |
|---|---|---|
KV_REST_API_URL |
Vercel KV Redis connection URL | ❌ (auto-set) |
KV_REST_API_TOKEN |
Vercel KV authentication token | ❌ (auto-set) |
Without any Redis vars, Docker/Local uses file storage (
data/state.json). Vercel and Cloudflare Workers fall back to in-memory (resets on cold starts).
| Level | Behavior | Group Reaction Chance |
|---|---|---|
0 |
React to every message | 100% |
1 |
Almost always | 90% |
3 |
Mostly | 70% |
5 |
Balanced | 50% |
7 |
Occasional | 30% |
10 |
Very rare | 0% (effectively off) |
Note: In private chats and channels, the bot always reacts regardless of this setting.
When WEBHOOK_SECRET is set (or auto-generated), the bot validates every incoming request against the x-telegram-bot-api-secret-token header. Requests with an invalid or missing secret are rejected with 403 Forbidden.
Set the secret via /setwebhook or BotFather:
{
"url": "https://your-worker.url",
"secret_token": "your_webhook_secret"
}Set OWNER_ID to your Telegram user ID (get it from @userinfobot). Only that user can use:
/broadcast— Send messages to all chats/leave//remove— Remove bot from any chat/chats— List all active chats/restrict//unrestrict— Runtime chat restrictions/setwebhook— Set or view webhook configuration/log— View reaction history
The bot enforces a 30 reactions per minute per chat limit. This prevents:
- Telegram API rate limit errors
- Spam in active groups
- Abuse in high-traffic channels
The /broadcast command has a 60-second cooldown between uses to prevent accidental spam.
Incoming webhook payloads larger than 1MB are rejected with 413 Payload Too Large.
The owner can restrict chats at runtime using /restrict <chat_id>. These restrictions:
- Work alongside env-based
RESTRICTED_CHATS - Persist across restarts (file/KV storage)
- Are shown in
/chatsand/stats - Can be removed with
/unrestrict <chat_id> - Are cleaned up automatically when using
/leave
AlisaReactionBot/
├── api/
│ ├── index.js # Express server (Docker/Vercel/Local)
│ ├── worker.js # Cloudflare Worker entry point
│ ├── bot-handler.js # Core logic — commands, reactions, stats
│ ├── store.js # Persistent state storage (file/KV/memory)
│ ├── TelegramBotAPI.js # Telegram API wrapper (all methods)
│ ├── constants.js # Message templates and keyboard layouts
│ ├── landing.js # Landing page HTML (separated for clarity)
│ ├── helper.js # Emoji parsing, chat ID parsing, logger
│ ├── ads.js # AdLab — centralized ad management library
├── assets/ # Logo and banner images
├── data/ # Runtime state (auto-created, gitignored)
├── .env.example # Environment variable template
├── .gitignore
├── package.json # Dependencies (express, dotenv)
├── wrangler.toml # Cloudflare Workers config
├── vercel.json # Vercel config
├── render.yaml # Render config
├── Dockerfile # Docker build
├── docker-compose.yml # Docker Compose
├── Procfile # Heroku config
├── app.json # Heroku app manifest
├── CHANGELOG.md # Version history
├── GUIDE.md # Complete setup & usage guide
├── LICENSE # MIT License
└── README.md # This file
Request Flow:
- User sends a message in Telegram
- Telegram forwards it to your webhook (POST
/) - Bot validates the webhook secret
bot-handler.jsprocesses the update:- Command? → Execute command, send response
- Regular message? → Check restrictions, rate limit, pick emoji, react
- Stats are updated in-memory
200 OKreturned to Telegram
Memory Model:
| State | Type | Persistent | Purpose |
|---|---|---|---|
stats.messagesProcessed |
Counter | ✅ | Total messages seen |
stats.reactionsSent |
Counter | ✅ | Total reactions placed |
chats |
Object | ✅ | Chat registry (ID, name, type, count) |
reactions |
Object | ✅ | Custom emoji per chat |
paused |
Array | ✅ | Paused chat IDs |
restricted |
Array | ✅ | Runtime-restricted chat IDs |
welcome / goodbye |
Array | ✅ | Toggle states per chat |
stats.commandUsage |
Object | ✅ | Command name → count |
reactionLog[] |
Array (last 50) | ❌ | Recent reactions |
rateLimitMap |
Object | ❌ | Per-chat rate limit windows |
chatNames |
Object | ❌ | Chat ID → display name |
perChatRandomLevel |
Object | ❌ | Per-chat random overrides |
lastBotMessage |
Object | ❌ | Per-chat last bot message ID (cleanup) |
Persistence: State marked ✅ persists to file (Docker/Local) or Upstash Redis (Vercel, free). On Cloudflare Workers, all state is in-memory. No message content is ever stored — only metadata.
# Clone
git clone https://github.com/Shineii86/AlisaReactionBot.git
cd AlisaReactionBot
# Install
npm install
# Configure
cp .env.example .env
# Edit .env with your BOT_TOKEN, BOT_USERNAME, EMOJI_LIST
# Run
npm start # Express server (port 3000)
npm run vercel # Vercel dev server
npm run cloudflare # Wrangler dev server- Fork the repository
- Create your branch —
git checkout -b feature/amazing-feature - Commit —
git commit -m 'Add amazing feature' - Push —
git push origin feature/amazing-feature - Open a Pull Request
- Language/locale support (
/language) - Inline mode for searching reactions
- Reaction charts (visual stats images)
- Per-group random level override
- Scheduled quiet hours (no reactions at night)
- Reaction streak tracking
- Welcome message customization
- PWA offline support for landing page
| Metric | Value |
|---|---|
| Reaction Latency | < 100ms (edge-deployed) |
| Uptime | 99.9% (Cloudflare SLA) |
| Scalability | Automatic — handles any traffic |
| Cold Starts | Zero (Cloudflare Workers) |
| Cost | $0/month on free tier |
| Rate Limit | 30 reactions/min/chat (built-in) |
Developer: Shinei Nouzen
Inspired by: Auto-Reaction-Bot by Malith Rukshan
Built with:
- Telegram Bot API — Official API
- Cloudflare Workers — Edge computing
- Node.js — Runtime
- Express — Server framework
- Wrangler — CLI tool
See CHANGELOG.md for the full version history.
Latest: v2.15.3 — Dynamic island navigation, glassmorphism blur, icon.png logo, auto-reactions, per-chat customization.
This project is licensed under the *MIT License*.
Feel free to use, remix, and share it with proper credits.MIT License — see LICENSE for details.

