6 KiB
6 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
A Telegram bot built with GramIO that enables role-based mentions in group chats. Users can create custom roles, join/leave them, and mention all role members at once using @mentions or commands.
Development Commands
pnpm dev- Run bot in development mode with hot reloadpnpm start- Run bot in production modepnpm drizzle-kit generate --config=src/shared/database/config.ts- Generate database migrations after schema changespnpm drizzle-kit migrate --config=src/shared/database/config.ts- Apply pending migrations to databasepnpm drizzle-kit studio --config=src/shared/database/config.ts- Open Drizzle Studio for database inspection
Architecture
Core Components
Bot Entry Point (src/index.ts → src/bot/index.ts)
- Bot initialization uses GramIO framework
- Commands are auto-loaded from
src/bot/commands/using@gramio/autoload - Two middleware handlers in
src/bot/index.ts:- Message handler for @mention syntax (e.g.,
@rolename) - triggers role mentions - Command handler for bare commands (e.g.,
/rolename) - also triggers role mentions
- Message handler for @mention syntax (e.g.,
- Bot username is captured on startup to properly handle commands with @botname suffix
Database (PostgreSQL with Drizzle ORM)
- Schema defined in
src/shared/database/schema.ts - Three tables:
roles(id, slug, aliases, chatId),role_members(id, roleId, userId), andchat_configs(id, chatId, roleManagePermission, roleMentionPermission) - Configuration in
src/shared/database/config.ts - Path aliases use
@/*mapping to./src/*
Services (src/shared/services/)
RoleService- All role and role member database operationsMentionService- Handles mentioning all members of a role- Chunks members into groups of 5 to avoid hitting Telegram's limits
- Builds mention entities using GramIO's
mention()helper - Sends multiple messages if role has >5 members, with pagination indicators
ChatConfigService- Manages per-chat permission configuration- Lazy initialization via
getOrCreate()- configs created on first access - Defaults:
all_adminsfor role management,everyonefor mentions
- Lazy initialization via
PermissionService- Centralized permission checking logiccanManageRoles()- Checks if user can add/delete roles based on chat configcanMentionRoles()- Checks if user can trigger role mentions based on chat config
Commands (src/bot/commands/)
- Admin commands require chat admin permissions (checked via
isChatAdmin()) /roleadd <name>- Create new role (permission configurable, updates bot commands dynamically)/roledel- Delete role (permission configurable)/join <name>- Join a role (always available to everyone)/leave <name>- Leave a role (always available to everyone)/myroles- List your roles/roles- List all roles in chat/config- View and configure permissions (any admin can view, owner can change via inline buttons)/reload- Refresh admin cache (any admin)
Role Triggering
- Roles can be triggered two ways:
- Via @mention in any message (e.g., "hey @developers")
- Via bare command (e.g., "/developers" or "/developers@botname")
- Both methods call
MentionService.mentionAll()
Utilities
src/bot/utilities/perms.ts- Permission checking utilitiesisChatAdmin()- Checks if user is admin (uses 1-hour cache)isChatOwner()- Checks if user is chat creator/ownergetAdminInfo()- Returns detailed admin info with granular permissionshasAdminPermission()- Checks specific Telegram admin permissions (can_promote_members, can_change_info, can_manage_chat)refreshAdminCache()- Clears admin cache for a specific chat- Admin cache: 1-hour TTL to reduce Telegram API calls, falls back to stale data on error
- Handles hidden admins including anonymous admin bot ID 1087968824
src/bot/utilities/constants.ts- Role name validation regex and reserved command namessrc/shared/utilities/chunk.ts- Array chunking utility for member batching
Important Patterns
Permission System
- Chat owners can configure permissions via
/configcommand with inline keyboard navigation - Role management options:
everyone,all_admins,admin_can_promote_members,admin_can_change_info,admin_can_manage_chat,only_owner - Role mention options:
everyone,all_admins,only_owner - Permissions checked via
PermissionServicewhich consultschat_configstable - Join/leave functionality always available to everyone (no configuration)
- Admin cache with 1-hour TTL reduces Telegram API calls - use
/reloadto manually refresh
Role Name Validation
- Must match
ROLE_NAME_REGEX: 4-32 characters, letters only - Cannot use
RESERVED_NAMES(built-in command names)
Chat Scope
- All roles are scoped to
chatId- same role name can exist in different chats - Bot only works in groups/supergroups, not private chats
Dynamic Command Registration
- When admin creates/deletes roles, bot updates chat-specific command list via
setMyCommands()with scope type 'chat' - This allows autocomplete for role names in that specific chat
Environment Variables
- Required:
DATABASE_URL,BOT_TOKEN - Optional:
NODE_ENV(defaults to 'production') - Loaded via Node's
loadEnvFile()from.envfile
Database Migrations
After modifying src/shared/database/schema.ts, generate and apply migrations using drizzle-kit with the explicit config path:
pnpm drizzle-kit generate --config=src/shared/database/config.tspnpm drizzle-kit migrate --config=src/shared/database/config.ts
The migration output directory is ./drizzle/.
Current Schema:
roles- Role definitions with slug, aliases, and chatIdrole_members- User memberships in roleschat_configs- Per-chat permission configuration (lazy-initialized)- Enums:
role_manage_permissionandrole_mention_permission - Default values ensure backwards compatibility with existing chats
- Enums: