WordSeek is a Telegram word game bot inspired by Wordle. It supports private games, group multiplayer rounds, daily global challenges, Telegram Forum topic controls, leaderboards, moderation tools, and production deployment on Bun, PostgreSQL, and a Redis-protocol cache such as Valkey or Redis.
This repository is a maintained fork of binamralamsal/WordSeek.
- Features
- Gameplay
- Commands
- Administration
- Deployment
- Configuration
- Development
- Troubleshooting
- Credits
- WordSeek I - Main instance
- WordSeek II - Backup instance
- Multiplayer word rounds in Telegram groups.
- Private chat daily challenge with one shared puzzle per day.
- 4-letter, 5-letter, and 6-letter game modes.
- Telegram Forum topic support, including topic-specific game settings.
- Global, group, and time-period leaderboards.
- PostgreSQL-backed durable state with Valkey/Redis-backed cache and queues.
- Local dictionary data for daily word meanings, pronunciations, and examples when available.
- Admin authorization, global bans, captcha checks, broadcasts, and tracking.
- Docker, Heroku, Render, Railway, and direct VPS deployment support.
- Runtime: Bun
- Language: TypeScript
- Bot framework: grammY
- Database: PostgreSQL with Kysely
- Cache and queues: Valkey or Redis with BullMQ
- Validation: Zod
- Start a game with
/new,/new4,/new5, or/new6. - Send a word guess directly in the chat.
- Use the colored feedback to narrow down the answer:
- Green means the letter is correct and in the correct position.
- Yellow means the letter is present but in the wrong position.
- Red or gray means the letter is not in the answer.
- A normal game ends when someone solves the word or the attempt limit is reached.
- Daily WordSeek has a 6-attempt limit and is available in private chat only.
| Mode | Command examples | Description |
|---|---|---|
| Normal 5-letter | /new, /new5 |
Default WordSeek mode for private chats and groups. |
| Short 4-letter | /new4, /new 4 |
Faster rounds with shorter words. |
| Long 6-letter | /new6, /new 6 |
Harder rounds with longer words. |
| Daily WordSeek | /daily, /pausedaily |
One globally shared private-chat puzzle per day. |
| Group multiplayer | /new in a group |
First correct guess wins; everyone can participate. |
| Forum topic rounds | /setgametopic |
Restrict games to a selected Telegram Forum topic if needed. |
/scoreshows personal statistics and supports lookup arguments./leaderboardshows rankings by scope and period.- Supported leaderboard scopes include group and global views.
- Supported periods include today, week, month, year, and all time.
- Daily mode tracks streaks independently from regular group rounds.
- Daily word details are loaded from the bundled local dictionary. No AI or external dictionary API is required at runtime.
- Start with words that cover common vowels and consonants.
- Avoid repeating letters already marked absent.
- In groups, review previous guesses before submitting your own.
- Use topic restrictions in busy Forum groups to keep game traffic organized.
| Command | Description | Notes |
|---|---|---|
/start |
Initialize the bot. | Opens the main bot menu. |
/help |
Show the interactive help menu. | Includes player and admin guidance. |
/id |
Show chat, user, and message identifiers. | Useful for admin setup and debugging. |
/new |
Start a default 5-letter game. | Also accepts /new 4, /new 5, etc. |
/new4 |
Start a 4-letter game. | Available in private and group chats. |
/new5 |
Start a 5-letter game. | Available in private and group chats. |
/new6 |
Start a 6-letter game. | Available in private and group chats. |
/daily |
Start Daily WordSeek. | Private chat only. |
/pausedaily |
Pause Daily WordSeek and return to normal. | Previous daily attempts still count. |
/end |
End the current game. | Admins can end directly; others vote. |
/score |
Show user statistics. | Supports optional user lookup. |
/myscore |
Legacy score command. | Redirects users to /score. |
/leaderboard |
Show rankings. | Supports scope and period filters. |
/startmatch |
Reserved command hook for match workflows. | Currently no-op in the command module. |
These commands require Telegram group admin rights or authorization through the bot.
| Command | Description | Example |
|---|---|---|
/seekauth |
Authorize trusted users for game admin. | /seekauth @username |
/seekauth list |
List authorized users in the group. | /seekauth list |
/seekauth remove |
Remove an authorized user. | /seekauth remove @username |
/setgametopic |
Restrict games to the current topic. | Run inside the target topic. |
/unsetgametopic |
Remove the topic restriction. | Run in the group or topic. |
/allowonlylen |
Restrict allowed word lengths by topic. | /allowonlylen 4 5 |
/recreatetopic |
Recreate expired or deleted game topics. | /recreatetopic on or off |
These commands are restricted to Telegram user IDs listed in ADMIN_USERS.
| Command | Description | Example |
|---|---|---|
/stats |
Show bot and system statistics. | /stats |
/ban |
Globally ban a user. | /ban 123456789 |
/unban |
Remove a global ban. | /unban 123456789 |
/broadcast |
Broadcast a replied message to known chats. | Reply to a message. |
/broadcast_status |
Show current broadcast progress. | /broadcast_status |
/broadcast_cancel |
Cancel an active broadcast. | /broadcast_cancel |
/captcha |
Force a captcha challenge for a user. | /captcha <chat_id> <user_id> |
/transfer |
Transfer stats between Telegram user IDs. | /transfer <old_id> <new_id> |
/track |
Track messages in a chat for diagnostics. | /track <chat_id> |
/untrack |
Stop tracking a chat. | /untrack <chat_id> |
/tracklist |
List tracked chats. | /tracklist |
- Create a bot through @BotFather.
- Add the bot to your group.
- Promote it to administrator if you need message management, forum topic management, captcha, or moderation features.
- In Forum groups, run
/setgametopicinside the topic where games should be allowed. - Use
/allowonlylento tune the available word lengths per topic.
- Group admins can manage games in their own groups.
- Users authorized with
/seekauthcan perform selected game-management actions. - Bot owners are configured through
ADMIN_USERSand can use global commands such as bans, broadcasts, captcha, tracking, and transfers.
- Keep
BOT_TOKEN, database URLs, Valkey/Redis credentials, and API keys out of Git. - Keep
ADMIN_USERSlimited to trusted Telegram user IDs. - Use a private Valkey/Redis instance; do not expose it directly to the public internet.
- Use
DATABASE_SSL=truefor managed databases that require TLS. - Keep
DATABASE_SSL_REJECT_UNAUTHORIZED=falseonly when your provider does not support trusted CA verification. - Configure
LOGS_CHANNELif you want operational alerts from tracking and moderation flows.
- Bun 1.3.x
- PostgreSQL
- Valkey or Redis
- A Telegram bot token
- A configured
.envfile
git clone https://github.com/bisug/TG-WordGame
cd TG-WordGame
bun install
cp .env.example .env
bun run db:migrate
bun run devUse bun run start instead of bun run dev when you do not need hot reload.
The Compose setup is intended for self-hosted VPS deployments. It includes the bot, PostgreSQL, a Valkey/Redis-compatible cache, persistent volumes, health checks, and a one-shot migration service.
Default Docker images are pinned to stable releases available in May 2026:
- PostgreSQL
18.4viapostgres:18.4-alpine3.23. - Valkey
9.1.0viavalkey/valkey:9.1.0-alpine3.23. - Redis Open Source
8.8.0is also supported by settingCACHE_IMAGE=redis:8.8.0-alpine3.23.
cp .env.docker.example .env
# Edit BOT_TOKEN, DAILY_WORDLE_SECRET, ADMIN_USERS, and POSTGRES_PASSWORD.
docker compose up -d --build
docker compose logs -f wordseek-botFor Docker deployments using managed PostgreSQL or Redis, set
WORDSEEK_DATABASE_URL or WORDSEEK_REDIS_URI in .env. Keep
DATABASE_SSL=false for the bundled Compose PostgreSQL service. Set
DATABASE_SSL=true for managed databases that require TLS.
PostgreSQL 18 uses the official image's versioned data directory
/var/lib/postgresql/18/docker and mounts the parent directory
/var/lib/postgresql. If you already have a Compose volume from PostgreSQL 16
or 17, do not switch the image directly on production data. Take a pg_dump
backup, start a fresh PostgreSQL 18 volume, run migrations, and restore the
backup.
Railway uses railway.toml and Nixpacks.
- Create a Railway project from the repository.
- Add PostgreSQL and Redis services.
- Set the required environment variables.
- Deploy. Railway runs
bun run db:migratebefore the start command.
Render uses render.yaml for a web service and render-worker.yaml for a worker
deployment.
- Connect the repository to Render.
- Create PostgreSQL and Redis instances.
- Set
WEB_SERVICE=trueonly for web-service deployments that need a health endpoint. - Set the required environment variables.
- Deploy. Render runs
bun run db:migrateas the pre-deploy command.
Heroku uses heroku.yml for Docker-based deployment.
- Create the Heroku app.
- Add Heroku Postgres and Heroku Data for Redis or set external service URLs.
- Set the required environment variables.
- Deploy. Heroku runs
bun run db:migrateas the release command.
bun install --frozen-lockfile
bun run db:migrate
bun run startFor process supervision, run the bot under systemd, Supervisor, PM2, or your preferred service manager. If using PM2:
pm2 start src/index.ts --interpreter bun --name wordseekFor South Asia users, keep the bot, PostgreSQL, and Valkey/Redis in the same region whenever possible. Code-level caching helps, but it cannot remove network round-trip latency between India, Europe, and the United States. The lowest latency setup is usually:
- App server in India, Singapore, or another nearby South Asia/Southeast Asia region.
- PostgreSQL in the same region as the app.
- Valkey/Redis in the same region as the app.
- Telegram Bot API root left as
https://api.telegram.orgunless you operate a local Bot API server close to the app.
| Variable | Required | Default | Description |
|---|---|---|---|
BOT_TOKEN |
Yes | None | Telegram bot token from BotFather. |
DAILY_WORDLE_SECRET |
Yes | None | Secret used for daily challenge verification. |
DATABASE_URL |
Yes | None | PostgreSQL connection string. |
REDIS_URI |
Yes | redis://127.0.0.1:6379 |
Valkey/Redis URI. Falls back to REDIS_URL. |
ADMIN_USERS |
Yes | Empty | Comma-separated Telegram user IDs with owner access. |
NODE_ENV |
No | development |
Use production in hosted environments. |
WEB_SERVICE |
No | false |
Starts a small health-check HTTP server when true. |
TIME_ZONE |
No | UTC |
Timezone for daily reset logic and scheduled jobs. |
DAILY_WORDLE_START_DATE |
No | 2025-01-01 |
Start date for the daily word rotation. |
DATABASE_SSL |
No | Auto | Overrides PostgreSQL SSL usage. |
DATABASE_SSL_REJECT_UNAUTHORIZED |
No | false |
Enables strict PostgreSQL TLS certificate verification. |
CUSTOM_API_ROOT |
No | https://api.telegram.org |
Telegram Bot API endpoint. |
LOGS_CHANNEL |
No | None | Telegram channel ID for selected operational logs. |
UPDATES_CHANNEL |
No | https://t.me/WordSeek |
Link shown in bot keyboards. |
DISCUSSION_GROUP |
No | https://t.me/WordGuesser |
Link shown in bot keyboards. |
POSTGRES_IMAGE |
Docker | postgres:18.4-alpine3.23 |
Compose PostgreSQL image. |
POSTGRES_PGDATA |
Docker | /var/lib/postgresql/18/docker |
Compose PostgreSQL data directory. |
CACHE_IMAGE |
Docker | valkey/valkey:9.1.0-alpine3.23 |
Compose cache image; Redis 8.8.0 is supported. |
WORDSEEK_DATABASE_URL |
Docker | Internal Compose PostgreSQL | Compose-only override mapped to DATABASE_URL. |
WORDSEEK_REDIS_URI |
Docker | Internal Compose Valkey | Compose-only override mapped to REDIS_URI. |
src/
commands/ Telegram command handlers
config/ Environment, bot, database, and logger configuration
handlers/ Message, callback query, sync, tracking, and moderation handlers
queues/ BullMQ-backed background work
services/ Daily WordSeek and domain services
util/ Shared helpers, caches, keyboards, and formatters
migrations/ Kysely database migrations
.github/ CI workflows
| Command | Purpose |
|---|---|
bun run dev |
Start the bot with Bun watch mode. |
bun run start |
Start the bot normally. |
bun run lint |
Check formatting with Prettier. |
bun run test |
Run Bun tests. |
bun run typecheck |
Run TypeScript type checking. |
bun run build |
Bundle the app to dist/. |
bun run db:migrate |
Apply Kysely migrations. |
bun run db:seed |
Run configured Kysely seeds. |
bun run db:codegen |
Regenerate Kysely database types. |
Migrations live in migrations/ and are executed with:
bun run db:migrateWhen adding schema changes, add a new migration and update generated database types with:
bun run db:codegen- Create a new command module in
src/commands/. - Implement the handler with
Composer. - Register it in
src/commands/index.ts. - Add or update tests for shared logic.
- Run
bun run lint,bun run test,bun run typecheck, andbun run build.
- Confirm
BOT_TOKENis valid. - Make sure the bot is not blocked by privacy mode for the group behavior you expect.
- Promote the bot to group admin if it needs moderation or Forum topic permissions.
- Check application logs for Telegram API errors.
- Confirm PostgreSQL is running and reachable from the app.
- Check
DATABASE_URL. - For Docker Compose, keep
DATABASE_SSL=falsewith the bundled Postgres service. - For managed Postgres, set
DATABASE_SSL=trueif the provider requires TLS.
- Confirm Valkey or Redis is running and reachable from the app.
- Check
REDIS_URI. - Do not expose Valkey or Redis publicly on a VPS; keep it on a private network.
- Confirm the database exists.
- Confirm the configured database user can create and alter tables.
- Run migrations before starting the worker if you deploy without the provided cloud or Compose migration hooks.
- Keep the app, Valkey/Redis, and PostgreSQL in the same region.
- Avoid running the app in Europe or the United States while Valkey/Redis, PostgreSQL, or users are in South Asia.
- Use the Docker/VPS path in a nearby region if your platform does not offer South Asia infrastructure.
- Updates: WordSeek
- Discussion: WordGuesser
- Issues: GitHub Issues
- Maintained fork: bisug/TG-WordGame
- Original project: binamralamsal/WordSeek
- Creator support: buymemomo.com/binamra
This project is licensed under the MIT License. See LICENSE for details.