roleping-bot/CLAUDE.md
devilreef 1eb2200fbe feat: config management
fuck it we're vibecoding now
2025-11-28 13:41:13 +06:00

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 reload
  • pnpm start - Run bot in production mode
  • pnpm drizzle-kit generate --config=src/shared/database/config.ts - Generate database migrations after schema changes
  • pnpm drizzle-kit migrate --config=src/shared/database/config.ts - Apply pending migrations to database
  • pnpm drizzle-kit studio --config=src/shared/database/config.ts - Open Drizzle Studio for database inspection

Architecture

Core Components

Bot Entry Point (src/index.tssrc/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:
    1. Message handler for @mention syntax (e.g., @rolename) - triggers role mentions
    2. Command handler for bare commands (e.g., /rolename) - also triggers role mentions
  • 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), and chat_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 operations
  • MentionService - 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_admins for role management, everyone for mentions
  • PermissionService - Centralized permission checking logic
    • canManageRoles() - Checks if user can add/delete roles based on chat config
    • canMentionRoles() - 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:
    1. Via @mention in any message (e.g., "hey @developers")
    2. Via bare command (e.g., "/developers" or "/developers@botname")
  • Both methods call MentionService.mentionAll()

Utilities

  • src/bot/utilities/perms.ts - Permission checking utilities
    • isChatAdmin() - Checks if user is admin (uses 1-hour cache)
    • isChatOwner() - Checks if user is chat creator/owner
    • getAdminInfo() - Returns detailed admin info with granular permissions
    • hasAdminPermission() - 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 names
  • src/shared/utilities/chunk.ts - Array chunking utility for member batching

Important Patterns

Permission System

  • Chat owners can configure permissions via /config command 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 PermissionService which consults chat_configs table
  • Join/leave functionality always available to everyone (no configuration)
  • Admin cache with 1-hour TTL reduces Telegram API calls - use /reload to 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 .env file

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.ts
  • pnpm drizzle-kit migrate --config=src/shared/database/config.ts

The migration output directory is ./drizzle/.

Current Schema:

  • roles - Role definitions with slug, aliases, and chatId
  • role_members - User memberships in roles
  • chat_configs - Per-chat permission configuration (lazy-initialized)
    • Enums: role_manage_permission and role_mention_permission
    • Default values ensure backwards compatibility with existing chats