No description
Find a file
2026-03-10 06:56:47 +00:00
config Update telegram-approval-join submodule and apply branding patches 2026-03-09 20:53:04 +00:00
handlers Update telegram-join-approval-bot submodule and apply patches 2026-03-10 06:44:52 +00:00
patches Update telegram-approval-join submodule and apply branding patches 2026-03-09 20:53:04 +00:00
pkg/utils Fix message format 2026-02-19 16:16:47 +00:00
scripts Remove .gitignore 2026-03-10 06:56:47 +00:00
telegram-join-approval-bot@1c48c2a40c Change submodule name 2026-03-10 06:31:20 +00:00
.gitignore Remove mock data 2026-01-28 15:57:23 +00:00
.gitmodules Change submodule name 2026-03-10 06:31:20 +00:00
Dockerfile Change submodule name 2026-03-10 06:31:20 +00:00
go.mod Update telegram-join-approval-bot submodule and apply patches 2026-03-10 06:44:52 +00:00
go.sum initial commit 2026-01-28 15:56:14 +00:00
main.go Update telegram-join-approval-bot submodule and apply patches 2026-03-10 06:44:52 +00:00
README.md Add README.md 2026-03-10 06:31:25 +00:00

Telegram Join Approval Bot

A Telegram bot for managing and approving join requests to private groups with approval workflows, canned responses, and admin controls.

Overview

This bot automates the process of approving new members joining a private Telegram group. When a user requests to join, the bot:

  1. Sends them a prompt to explain why they want to join
  2. Forwards their request to the admin chat with approve/decline/ban buttons
  3. Allows admins to manage requests with customizable decline reasons
  4. Notifies users of the approval decision

Features

  • Automated Join Requests: Intercepts and manages join requests to your target group
  • Admin Approval Workflow: Approve, decline, or ban users with a single click
  • Join Reason Collection: Users must provide a reason before their request reaches admins
  • Canned Responses: Pre-configured decline messages for common rejection reasons
  • Flexible Admin Interface:
    • Approve, decline, or ban users
    • Add custom decline reasons
    • Configure bot messages and settings
    • Organize requests in topic threads
  • Approval Notifications: Optional message sent to approved users
  • Configurable Messages: Customize entry and approval messages
  • User Banning: Ban users for 24 hours with a single action

How It Works

Join Request Flow

User requests to join group
         ↓
Bot sends entry prompt to user
         ↓
Bot notifies admins with join request
    (showing user info and join reason placeholder)
         ↓
User sends their join reason
    (message to bot in private chat)
         ↓
Bot updates admin message with user's reason
         ↓
Admin clicks Approve/Decline/Ban
         ↓
User notified of decision (if configured)
         ↓
User added/rejected/banned from group

Architecture

The bot consists of several key components:

Main Entry Point (main.go)

  • Initializes the bot with config from config.yaml
  • Starts the long polling update loop
  • Routes updates to appropriate handlers

Configuration (config/config.go)

  • Loads settings from config.yaml
  • Auto-generates template config if missing
  • Supports hot-reloading configuration changes

Handlers

  • join.go: Manages join request flow and user responses
  • callbacks.go: Handles inline button actions (approve/decline/ban)
  • admin.go: Processes admin commands for configuration
  • handlers.go: Shared types and utilities

Key Data Structures

// ExtendedChatJoinRequest tracks a user's approval request
type ExtendedChatJoinRequest struct {
    *ChatJoinRequest        // Telegram join request
    JoinReason string       // User's explanation
    JoinRequestMessageID int // Admin notification message ID
}

// Bot maintains runtime state
type Bot struct {
    API BotAPI              // Telegram API client
    Config Config           // Configuration
    WaitingForApproval map  // In-memory user request tracking
}

Configuration

The bot reads from config.yaml in its working directory. On first run, it creates a template:

bot_token: "YOUR_BOT_TOKEN_HERE"        # @BotFather token
admin_chat_id: 0                         # Chat ID where admins review requests
admin_chat_topic_id: 0                   # Optional: Topic ID in admin chat (0 = main)
target_chat_id: 0                        # Private group to protect
entry_message: "Please explain why..."   # Prompt shown to joining users
approval_message: ""                     # Message sent after approval (optional)
send_approval_message: false             # Whether to send approval message
delete_request_after_decision: false     # Auto-delete admin messages after decision
canned_decline_responses:                # Pre-configured decline reasons
  - "Your profile doesn't meet our criteria"
  - "We're at capacity"

Getting Required IDs

Bot Token: Create a bot with @BotFather

Chat IDs:

# Forward a message from the chat to @getidsbot
# It will show you the chat ID

Admin Commands

Admins can use these commands in the admin chat:

/setentrymessage <message>

Change the message shown when users request to join.

/setentrymessage Tell us about yourself and why you want to join!

/setapprovalmessage <message>

Set a message sent to approved users. Must be set before enabling approval notifications.

/setapprovalmessage Welcome to our group! We're excited to have you.

/togglesendapproval

Enable/disable sending the approval message to approved users.

/setadmintopic <topic_id>

Direct admin messages to a specific topic thread (0 = main chat).

/setadmintopic 42

/info

Display current bot configuration.

/edit <new_text>

Reply to a message and use this to edit it. Useful for correcting admin notifications.

/edit User was banned incorrectly

Approval Workflow

Admin Actions

When a user requests to join, an admin sees:

New join #request from @username [123456789]

Join reason: "I'm interested in this community"

With inline buttons:

  • Approve - Add user to group, optionally send approval message
  • Decline - Reject request, show decline reason button panel
  • Ban - Ban user for 24 hours (shows confirmation)

Decline Responses

When declining with canned responses configured:

  1. Admin clicks Decline
  2. Message shows available canned responses as buttons
  3. Admin clicks a canned response
  4. User receives the selected reason
  5. Admin message updates with the reason

Or, admin can reply to a decline message with custom text (with or without / prefix):

[Reply to decline message]
/We can only accept members with 2+ years experience

Deployment

Docker

Build and run the container:

docker build -t telegram-approval-bot .
docker run -it \
  --mount type=bind,source=$PWD/config.yaml,target=/opt/config.yaml \
  telegram-approval-bot

The Dockerfile:

  • Builds a static binary with minimal dependencies
  • Uses Alpine for small image size
  • Runs as unprivileged user (UID 65532)
  • Mounts config as a volume for persistence

Compose Example

version: '3'
services:
  bot:
    build: .
    volumes:
      - ./config.yaml:/opt/config.yaml
    restart: unless-stopped

Implementation Details

State Management

Join requests are tracked in memory using a mutex-protected map:

WaitingForApproval map[int64]*ExtendedChatJoinRequest

When a user provides their join reason, the bot:

  1. Updates the request with their reason
  2. Edits the admin message to show the reason
  3. Keeps the message indexed by message ID for button handling

Update Processing

The bot receives Telegram updates via long polling:

  1. ChatJoinRequest: User requests to join → calls HandleJoinRequest
  2. CallbackQuery: Admin clicks button → calls HandleCallbackQuery
  3. Message: User sends reason or admin command → routes accordingly

Message Formatting

Admin notifications use HTML formatting with:

  • User display name with link
  • Numeric user ID
  • Join reason (HTML-escaped for safety)
  • Admin action history
  • Timestamp information

Error Handling

  • Failed API requests restore the original message
  • Missing user state after restart shows helpful error
  • Invalid callback data is logged without crashing

Development

Dependencies

  • github.com/OvyFlash/telegram-bot-api - Telegram Bot API client
  • go.yaml.in/yaml/v3 - YAML configuration parsing

Go Version

Requires Go 1.25.3+

Building Locally

go build -o telegram-approval-bot ./...
./telegram-approval-bot

Troubleshooting

Bot doesn't respond to join requests

  • Verify target_chat_id is correct
  • Check bot has admin rights in the target group
  • Ensure bot is configured to receive join request updates

Admin messages don't appear

  • Verify admin_chat_id is correct
  • Check bot has message permission in admin chat
  • If using topics, verify admin_chat_topic_id is set

Approve/Decline buttons don't work

  • Bot needs admin rights in target group
  • Join request may have expired (Telegram timeout)
  • Check logs for API errors

Config changes don't apply

  • Some changes require bot restart
  • Use /info to verify current settings
  • Check config.yaml for syntax errors

License

[Specify your license here]