Technical Documentation

1. SYSTEM OVERVIEW

1.1 General Description

The Telegram Subscription Manager Bot is a comprehensive, production-ready solution for managing paid subscriptions to private Telegram channels and groups using cryptocurrency payments. The system automates the entire subscription lifecycle: from trial periods and payment processing to access management and renewal reminders.

This bot integrates seamlessly with the TON (The Open Network) blockchain to process USDT (Tether) payments, automatically verifies transactions, grants or revokes channel and group access based on subscription status, and provides both Telegram-based and web-based administration interfaces.

1.2 General Architecture

  • Backend: Node.js runtime with Express.js (v5.2.1) for web API endpoints and Telegraf (v4.16.3) for Telegram Bot API interactions
  • Database: PostgreSQL (via pg v8.16.3) for persistent storage, with automatic fallback to JSON file storage if database is unavailable
  • Payments: TON Center API (v2) integration for real-time USDT transaction verification on the TON blockchain
  • Deployment: Compatible with Render, Vercel, Railway, Heroku, or any VPS hosting Node.js applications
  • Admin Interface: Modern web dashboard (vanilla JavaScript) accessible via /admin route, secured with session-based authentication
  • Multi-Channel & Group Support: Manages multiple private Telegram channels and groups simultaneously with individual access control

1.3 Core Features

  • Automated Payment Processing: Generates unique payment links, verifies blockchain transactions, and automatically grants access upon payment confirmation
  • Trial Period Management: Configurable free trial periods for new users added to channels or groups
  • Subscription Renewals: Automatic handling of subscription renewals with expiration date extension
  • Grace Periods: Temporary access extensions for users who need extra time to pay
  • Whitelisting: Permanent free access for moderators, teachers, or special users
  • Exchange Rate Management: Automatic or manual RUB/USDT exchange rate updates
  • Background Automation: Scheduled tasks for payment verification (every 5 minutes) and subscription expiration checks (every hour)
  • Comprehensive Admin Tools: Both Telegram commands and web dashboard for complete bot management

1.4 Main Use Cases

  1. Content Creator: Monetize private Telegram channels and groups with premium content, courses, or exclusive materials
  2. Paid Community: Manage subscription-based Telegram communities with monthly or custom-duration subscriptions
  3. Educational Service: Provide access to educational resources, courses, or tutoring via private channels and groups
  4. B2B SaaS: Deploy multiple instances for different clients or resell as a white-label solution
  5. Membership Platform: Create membership tiers with different subscription durations and pricing

2. DETAILED TECHNICAL ARCHITECTURE

2.1 File Structure

telegram-subscription-bot/
├── index.js # Main entry point (2000+ lines)
│   ├── Express configuration (web server)
│   ├── Telegraf configuration (Telegram bot)
│   ├── User session management
│   ├── Telegram command handlers
│   ├── Periodic payment verification system
│   ├── Subscription and expiration management
│   ├── REST API for admin dashboard
│   └── Admin authentication routes
│
├── services/
│   ├── tonService.js # TON/USDT payment management service
│   │   ├── Telegram Wallet payment link generation
│   │   ├── Transaction verification via TON Center API
│   │   ├── Pending payment management
│   │   ├── RUB/USDT conversion with auto exchange rate
│   │   └── Subscription renewal processing
│   │
│   ├── channelService.js # Telegram channel and group management service
│   │   ├── Grant/revoke access to private channels and groups
│   │   ├── Invitation link creation
│   │   ├── Member status verification
│   │   └── Ban management
│   │
│   └── database.js # PostgreSQL database service
│       ├── Connection with connection pool
│       ├── Auto-detect Supabase pooler (IPv4/IPv6)
│       ├── Tables: subscriptions, grace_periods, user_channels,
│       │   whitelisted_users, trial_access, payments, settings
│       └── Fallback to file storage if DB unavailable
│
├── public/admin/ # Web administration interface
│   ├── index.html # Main dashboard page
│   ├── app.js # Frontend JavaScript logic
│   └── styles.css # CSS styles
│
├── data/ # Persistent storage (if no DB)
│   ├── state.json # Subscriptions, trials, whitelist state
│   └── settings.json # Bot settings
│
└── Configuration files
    ├── package.json # Node.js dependencies
    ├── .env # Environment variables (not versioned)
    └── env.example # Environment variables template

2.2 Technology Stack

  • Runtime: Node.js (version 14+)
  • Bot Framework: Telegraf v4.16.3
  • Web Framework: Express v5.2.1
  • Database: PostgreSQL (via pg v8.16.3)
  • HTTP Client: Axios v1.13.2
  • Sessions: express-session v1.18.2
  • Security: bcryptjs v3.0.3
  • Configuration: dotenv v17.2.3

2.3 Main Data Flows

Flow 1: New User Added to Channel or Group

  1. User added to channel or group → Telegram event "chat_member" or "new_chat_members"
  2. Bot detects addition → handleUserAddedToManagedChat()
  3. Bot records user's initial channels and groups → userChannels Map
  4. Bot starts trial period → trialAccess Map (configurable duration, default 2 days)
  5. Bot sends welcome message with "Subscribe" button
  6. Bot saves state → saveStateSoon() (debounced)

Flow 2: Payment Process

  1. User clicks "Subscribe" → Action callback "subscribe"
  2. Bot generates payment link → tonService.generatePaymentLink()
  3. Creates unique comment: "subscription_{userId}{timestamp}"
  4. Calculates USDT amount from RUB (if configured)
  5. Generates Telegram Wallet link: "https://t.me/wallet?startapp=transfer_..."
  6. Stores pending payment → pendingPayments Map
  7. User pays via Telegram Wallet → Transaction on TON blockchain
  8. Bot verifies payment (every 5 min or manually)
  9. Calls TON Center API → getTransactions()
  10. Searches for transaction with matching comment
  11. Verifies amount (90% tolerance)
  12. If payment found → processPayment()
  13. Calculates expiration date (adds to end of existing subscription if renewal)
  14. Stores subscription → userSubscriptions Map + DB if available
  15. Grant access → channelService.grantAccess() for each initial channel
  16. Sends confirmation notification
  17. Cleans up pending payment

Flow 3: Periodic Expiration Verification

  1. Interval every hour → setInterval(..., 60 * 60 * 1000)
  2. For each subscription:
    • Checks if expired (expiresAt < Date.now())
    • Checks grace period (gracePeriods Map)
    • Checks whitelist (whitelistedUsers Set)
    • If expired AND no grace AND not whitelisted:
      • → Sends expiration notification
      • → Revoke access → channelService.revokeAccess()
      • → Removes from userSubscriptions
  3. For each trial:
    • Checks if expired
    • If < 24h remaining AND not yet reminded → Sends reminder
    • If expired → Revoke access + Remove trial
  4. For each active subscription:
    • Checks if X days before expiration (renewalReminderDays)
    • If yes AND not yet notified → Sends renewal reminder

3. DETAILED FEATURES

3.1 User Features (via Telegram)

3.1.1 /start Command

Trigger: User sends /start command or clicks the "Start" button in Telegram

Functionality:

  • Saves user profile information (username, firstName, lastName) to userProfiles Map for future reference
  • Displays a personalized welcome message with subscription information
  • If user has an active subscription:
    • Shows subscription expiration date
    • Displays "Status" and "Renew" buttons for quick access
    • Indicates remaining days until expiration
  • If no active subscription:
    • Shows "🔔 Subscribe" button to initiate payment process
    • Displays trial period information if applicable

Implementation: Handler located in index.js at bot.start() callback

Example Usage:

User: /start
Bot: Welcome! Your subscription expires on 2024-02-15.
     [Status] [Renew]

3.1.2 Subscribe Button (Action Callback)

Trigger: User clicks the inline "🔔 Subscribe" button

Functionality:

  • Calls tonService.generatePaymentLink(userId) to create a unique payment reference
  • Generates a unique payment comment in format: subscription_{userId}_{timestamp}
  • Calculates USDT amount from RUB using current exchange rate
  • Creates a Telegram Wallet deep link: https://t.me/wallet?startapp=transfer_{walletAddress}_{amount}_{comment}
  • Stores pending payment information in pendingPayments Map
  • Displays comprehensive payment instructions including:
    • TON wallet address
    • Amount in USDT (with 6 decimal precision)
    • Amount in RUB (if configured)
    • Unique payment comment that must be included in transaction
    • Direct "Pay with Telegram Wallet" button (opens Telegram Wallet app)
    • "🔄 Check Payment" button for manual verification

Implementation: Handler located in index.js at bot.action('subscribe') callback

Payment Comment Format: subscription_123456789_1704067200000 (userId + timestamp)

3.1.3 Payment Verification

Trigger: User clicks "🔄 Check Payment" button or sends /check_payment command

Functionality:

  • Immediately calls tonService.checkPayment(userId) to verify payment on blockchain
  • Polls TON Center API's getTransactions endpoint
  • Searches for transactions matching:
    • Timestamp after payment request was created
    • Comment containing subscription_{userId}
    • Amount within 90% tolerance of expected amount
    • Destination address matching configured wallet
  • If payment found:
    • Calls tonService.processPayment(userId, currentSubscription)
    • Calculates new expiration date (extends existing subscription if renewal)
    • Saves subscription to userSubscriptions Map and database
    • Grants access to all user's initial channels via channelService.grantAccess()
    • Sends confirmation notification with expiration date
    • Clears pending payment entry
  • If payment not found: Displays "Payment not yet detected. Please wait a few minutes and try again."

Implementation: Handler located in index.js at bot.action('check_payment') and bot.command('check_payment')

Automatic Verification: Payments are also checked automatically every 5 minutes via background interval

Important: Telegram Wallet Availability

This service integrates with Telegram Wallet for payment processing. Please ensure that Telegram Wallet is available in your country. However, you have full flexibility: You can receive payments to any platform or wallet you prefer, and your subscribers can send payments from any compatible payment method—as long as they follow the bot's instructions and use the correct payment address.

3.1.4 /status Command

Trigger: User sends /status command

Functionality:

  • Retrieves user's subscription status from userSubscriptions Map
  • Checks if subscription is active (expiration date in future)
  • Displays comprehensive status information:
    • Subscription status: "Active" or "Expired"
    • Expiration date and time (formatted)
    • Remaining days until expiration (if active)
    • Grace period information (if active)
    • Whitelist status (if applicable)
  • If no subscription exists: Shows "No active subscription" message

Implementation: Handler located in index.js at bot.command('status') callback

Example Output:

📊 Subscription Status

✅ Status: Active
📅 Expires: February 15, 2024 at 10:30 AM
⏰ Remaining: 12 days

Your subscription is active and you have access to all channels.

3.2 Administrator Features (via Telegram)

Access Control: All admin commands require the user's Telegram ID to match ADMIN_ID environment variable. Commands are rejected with an error message if unauthorized.

3.2.1 /settings Command

Trigger: Admin sends /settings command

Functionality:

  • Displays complete bot configuration and statistics
  • Shows payment configuration:
    • Subscription amount in RUB
    • Subscription amount in USDT (calculated)
    • Current USDT to RUB exchange rate
    • Exchange rate auto-update status
  • Shows subscription settings:
    • Subscription duration in days
    • Trial period duration
    • Renewal reminder days (days before expiration to send reminder)
  • Lists all configured channels and groups:
    • Channel and group IDs
    • Channel and group labels (if configured)
    • Total number of channels and groups
  • Displays database status:
    • Connection status (Connected / Not Connected)
    • Storage method (Database / File)
  • Shows real-time statistics:
    • Active subscriptions count
    • Total users count
    • Whitelisted users count
    • Total revenue (if database available)

Implementation: Handler located in index.js at bot.command('settings') callback

Example Output:

⚙️ Bot Settings

💰 Payment Configuration:
   • Amount: 90.00 RUB (1.00 USDT)
   • Exchange Rate: 1 USDT = 90.00 RUB
   • Auto Update: Disabled

⏱️ Subscription Settings:
   • Duration: 30 days
   • Trial Period: 2 days
   • Renewal Reminder: 5 days before expiration

📢 Channels:
   • Configured: 3 channel(s)
   • CHAT 1 english (-1003520607330)
   • CHAT 2 english (-1003620447473)
   • CHAT 3 english (-1003565861542)

🗄️ Database:
   • Status: ✅ Connected

📊 Statistics:
   • Active subscriptions: 15
   • Total users: 42
   • Whitelisted users: 3
   • Total revenue: 1350.00 USDT

✅ All systems operational!

3.2.2 Configuration Commands

All configuration commands save changes immediately to the database (if available) or settings file. No bot restart is required.

/set_amount <amount_in_rub>

Description: Changes the subscription amount in Russian Rubles (RUB)

Usage: /set_amount 100

Parameters:

  • amount_in_rub: Subscription amount in RUB (minimum 0.01, must be a valid number)

Functionality:

  • Validates the amount (must be positive number)
  • Updates botSettings.subscriptionAmountRub
  • Recalculates USDT amount based on current exchange rate
  • Saves to database/file immediately
  • Confirms change with success message

Examples:

  • /set_amount 90 - Set subscription to 90 RUB
  • /set_amount 150.5 - Set subscription to 150.50 RUB
/set_duration <days>

Description: Changes the subscription duration in days

Usage: /set_duration 30

Parameters:

  • days: Number of days for subscription (minimum 1, must be integer)

Functionality:

  • Validates the duration (must be positive integer)
  • Updates botSettings.subscriptionDurationDays
  • Saves to database/file immediately
  • Confirms change with success message

Examples:

  • /set_duration 30 - Set to 30 days (monthly)
  • /set_duration 7 - Set to 7 days (weekly)
  • /set_duration 90 - Set to 90 days (quarterly)
/set_trial <days>

Description: Changes the free trial period duration in days

Usage: /set_trial 2

Parameters:

  • days: Number of trial days (minimum 0 to disable, must be integer)

Functionality:

  • Validates the trial duration (must be non-negative integer)
  • Updates botSettings.trialDays and recalculates TRIAL_MS
  • Saves to database/file immediately
  • Confirms change with success message

Examples:

  • /set_trial 2 - Set to 2 days trial
  • /set_trial 7 - Set to 7 days trial
  • /set_trial 0 - Disable trial period
/set_reminder <days>

Description: Changes when users receive renewal reminders before subscription expiration

Usage: /set_reminder 5

Parameters:

  • days: Number of days before expiration to send reminder (minimum 0 to disable, must be integer)

Functionality:

  • Validates the reminder days (must be non-negative integer)
  • Updates botSettings.renewalReminderDays and RENEWAL_REMINDER_DAYS
  • Saves to database/file immediately
  • Confirms change with success message

Examples:

  • /set_reminder 5 - Remind 5 days before expiration
  • /set_reminder 7 - Remind 7 days before expiration
  • /set_reminder 0 - Disable renewal reminders

3.2.3 User Management Commands

/whitelist [user_id]

Description: Adds a user to the whitelist, granting permanent free access to all channels and groups

Usage:

  • /whitelist 123456789 - Whitelist specific user by ID
  • Reply to user's message with /whitelist - Whitelist the replied user

Parameters:

  • user_id: Telegram user ID (optional if replying to message)

Functionality:

  • Adds user ID to whitelistedUsers Set
  • Saves to database/file immediately
  • User gains permanent access without payment requirement
  • User will not be removed even if subscription expires
  • Useful for moderators, teachers, or special users
  • Confirms action with success message

Examples:

  • /whitelist 123456789 - Whitelist user with ID 123456789
  • Reply to message: /whitelist - Whitelist the user who sent the message
/unwhitelist [user_id]

Description: Removes a user from the whitelist, requiring them to pay for access

Usage:

  • /unwhitelist 123456789 - Remove specific user by ID
  • Reply to user's message with /unwhitelist - Remove the replied user

Parameters:

  • user_id: Telegram user ID (optional if replying to message)

Functionality:

  • Removes user ID from whitelistedUsers Set
  • Saves to database/file immediately
  • User will need to pay to maintain access
  • User's subscription will be checked normally during expiration checks
  • Confirms action with success message
/grace <user_id> <days>

Description: Adds a temporary grace period for a user, preventing removal even if subscription expires

Usage: /grace 123456789 3

Parameters:

  • user_id: Telegram user ID
  • days: Number of days for grace period (must be positive integer)

Functionality:

  • Calculates grace period expiration timestamp
  • Adds entry to gracePeriods Map
  • Saves to database/file immediately
  • User will not be removed during grace period, even if subscription expired
  • Useful when user notifies admin they will pay late
  • Confirms action with success message showing expiration date

Example: /grace 123456789 3 - Give user 3 days grace period

/grace_user <days>

Description: Adds a grace period for a user (convenient when replying to their message)

Usage: Reply to user's message with /grace_user 5

Parameters:

  • days: Number of days for grace period (must be positive integer)

Functionality:

  • Extracts user ID from the replied message
  • Same functionality as /grace command
  • More convenient when managing users in a chat

Example:

  1. User sends a message in chat
  2. Admin replies: /grace_user 5
  3. User gets 5-day grace period automatically

3.3 Automatic Features (Background Processes)

These features run automatically in the background without user intervention, ensuring the bot maintains subscription states, verifies payments, and manages access continuously.

3.3.1 Payment Verification (Every 5 Minutes)

Interval: setInterval(..., 5 * 60 * 1000) - Runs every 5 minutes

Process:

  1. Retrieves all user IDs with pending payments from tonService.getPendingUserIds()
  2. For each user ID:
    • Calls tonService.checkPayment(userId) to verify payment on blockchain
    • If payment found:
      • Processes payment via tonService.processPayment(userId, currentSubscription)
      • Calculates new expiration date (extends if renewal)
      • Saves subscription to database and in-memory Map
      • Grants access to all user's initial channels
      • Sends confirmation notification to user
      • Clears pending payment entry
      • Records payment in payments table (if database available)

Implementation: Located in index.js as a setInterval callback

Error Handling: All errors are caught and logged, preventing the interval from stopping

Performance: Only checks users with pending payments, minimizing API calls to TON Center

3.3.2 Subscription and Trial Expiration Verification (Every Hour)

Interval: setInterval(..., 60 * 60 * 1000) - Runs every hour

Process:

  1. Subscription Expiration Check:
    • Iterates through all entries in userSubscriptions Map
    • For each subscription:
      • Checks if expiresAt < Date.now() (expired)
      • Checks if user is in grace period (gracePeriods Map)
      • Checks if user is whitelisted (whitelistedUsers Set)
      • If expired AND no grace period AND not whitelisted:
        • Sends expiration notification to user
        • Revokes access from all user's channels via channelService.revokeAccess()
        • Removes subscription from userSubscriptions Map
        • Updates database (if available)
  2. Trial Expiration Check:
    • Iterates through all entries in trialAccess Map
    • For each trial:
      • Checks if expiresAtMs < Date.now() (expired)
      • If less than 24 hours remaining AND not yet reminded:
        • Sends 24-hour reminder notification
        • Sets reminded24h: true flag
      • If expired:
        • Sends expiration notification
        • Revokes access from all user's channels
        • Removes trial from trialAccess Map
        • Updates database (if available)
  3. Renewal Reminders:
    • Iterates through all active subscriptions
    • For each subscription:
      • Calculates days until expiration
      • If days until expiration equals renewalReminderDays AND not yet notified:
        • Checks renewalNotificationsSent Set to avoid duplicates
        • Sends renewal reminder notification
        • Adds user to renewalNotificationsSent Set

Implementation: Located in index.js as a setInterval callback

Notification Messages:

  • Expiration: "Your subscription has expired. Please renew to continue access."
  • Trial 24h reminder: "Your trial expires in 24 hours. Subscribe now to continue access."
  • Trial expiration: "Your trial period has ended. Subscribe to regain access."
  • Renewal reminder: "Your subscription expires in X days. Renew now to avoid interruption."

3.3.3 Exchange Rate Auto-Update (Every 15 Minutes, if Enabled)

Interval: setInterval(..., 15 * 60 * 1000) - Runs every 15 minutes

Condition: Only runs if botSettings.exchangeRateAuto === true

Process:

  1. Calls refreshExchangeRateIfEnabled() function
  2. Fetches USD/RUB exchange rate from external API:
    • Primary source: https://api.exchangerate-api.com/v4/latest/USD (free, no API key)
    • Extracts RUB rate from response: response.data.rates.RUB
    • Assumes USDT ≈ USD (standard assumption)
  3. Validates the rate:
    • Must be a finite positive number
    • If invalid, keeps current rate and logs warning
  4. If valid:
    • Updates botSettings.usdtToRubRate
    • Sets botSettings.exchangeRateLastUpdatedMs = Date.now()
    • Saves to database/file via saveSettings()
    • Logs success message with new rate

Error Handling: If API call fails, keeps current rate and logs error (does not crash)

Configuration: Can be enabled/disabled via EXCHANGE_RATE_AUTO environment variable or admin settings

3.4 Web Administration Interface

The web admin interface provides a comprehensive dashboard for managing the bot, viewing statistics, and configuring settings through a user-friendly web interface accessible at https://your-domain.com/admin.

3.4.1 Authentication

Login Route: POST /admin/api/auth/login

Request Body:

{
  "password": "your_admin_password"
}

Functionality:

  • Compares provided password with ADMIN_PASSWORD environment variable
  • If correct: Creates session via express-session and returns { success: true }
  • If incorrect: Returns { success: false, error: "Invalid password" }
  • Session cookie settings:
    • httpOnly: true - Prevents JavaScript access
    • sameSite: 'lax' - CSRF protection
    • maxAge: 24 * 60 * 60 * 1000 - 24 hours expiration
    • secure: false - Set to true in production with HTTPS

Logout Route: POST /admin/api/auth/logout

Functionality: Destroys session and returns { success: true }

Check Route: GET /admin/api/auth/check

Functionality: Returns { authenticated: true/false } based on session status

Middleware: All admin API routes (except auth routes) use requireAuth() middleware to verify session

3.4.2 Statistics Dashboard

Route: GET /admin/api/stats

Authentication: Required (session-based)

Response:

{
  "activeSubscriptions": 15,
  "totalRevenue": 1350.00,  // in USDT (if database available)
  "totalUsers": 42,
  "whitelistedUsers": 3
}

Data Sources:

  • If database available: Queries subscriptions and payments tables
  • If database unavailable: Calculates from in-memory Maps (userSubscriptions, whitelistedUsers)
  • Revenue calculation: Sums all amounts from payments table

3.4.3 User Management

Route: GET /admin/api/users

Authentication: Required

Response: Array of user objects with complete information:

[
  {
    "userId": "123456789",
    "username": "john_doe",
    "displayName": "John Doe",
    "avatarUrl": "/admin/api/avatars/123456789",
    "subscriptionStatus": "active",  // active | expired | trial | no_subscription
    "userType": "paid",  // paid | whitelisted | trial | member | admin
    "expiresAt": 1704067200000,
    "expiresAtFormatted": "2024-01-01 10:00:00",
    "channels": [
      {
        "channelId": "-1003520607330",
        "label": "CHAT 1 english"
      }
    ],
    "gracePeriod": {
      "active": true,
      "expiresAt": 1704153600000,
      "expiresAtFormatted": "2024-01-02 10:00:00"
    }
  }
]

Optimizations:

  • Profile Lookup Batching: Limits to 10 Telegram API calls per request to avoid rate limiting
  • Avatar Lookup Batching: Limits to 10 photo lookups per request
  • Profile Caching: Uses userProfiles Map to cache user information
  • Avatar Proxy: Serves avatars via /admin/api/avatars/:userId to avoid exposing BOT_TOKEN to frontend

Avatar Proxy Route: GET /admin/api/avatars/:userId

Functionality:

  • Fetches user profile photos from Telegram API (server-side)
  • Streams image data to client
  • Prevents BOT_TOKEN exposure to frontend
  • Returns 404 if user has no avatar

3.4.4 Settings Management

Get Settings Route: GET /admin/api/settings

Response:

{
  "subscriptionAmountRub": 90.0,
  "usdtToRubRate": 90.0,
  "exchangeRateAuto": false,
  "exchangeRateSourceUrl": "https://api.exchangerate-api.com/v4/latest/USD",
  "exchangeRateLastUpdatedMs": null,
  "subscriptionDurationDays": 30,
  "trialDays": 2,
  "renewalReminderDays": 5
}

Update Settings Route: POST /admin/api/settings

Request Body: Partial settings object (only include fields to update):

{
  "subscriptionAmountRub": 100.0,
  "subscriptionDurationDays": 30
}

Validatable Settings:

  • subscriptionAmountRub: Must be positive number (minimum 0.01)
  • usdtToRubRate: Must be positive number (minimum 0.01)
  • exchangeRateAuto: Boolean
  • exchangeRateSourceUrl: Must be valid URL string
  • subscriptionDurationDays: Must be positive integer (minimum 1)
  • trialDays: Must be non-negative integer (minimum 0)
  • renewalReminderDays: Must be non-negative integer (minimum 0)

Functionality:

  • Validates all provided settings
  • Merges with existing settings
  • Saves to database (priority) or file (fallback)
  • Updates in-memory botSettings object
  • Recalculates derived values (e.g., TRIAL_MS)
  • Returns updated settings object

3.4.5 Whitelist Management

Get Whitelist Route: GET /admin/api/whitelist

Response: Array of whitelisted user IDs:

["123456789", "987654321", "555666777"]

Add to Whitelist Route: POST /admin/api/whitelist

Request Body:

{
  "userId": "123456789"
}

Functionality:

  • Adds user ID to whitelistedUsers Set
  • Saves to database/file
  • Returns success confirmation

Remove from Whitelist Route: DELETE /admin/api/whitelist/:userId

Functionality:

  • Removes user ID from whitelistedUsers Set
  • Saves to database/file
  • Returns success confirmation

3.4.6 Grace Period Management

Add Grace Period Route: POST /admin/api/users/:userId/grace

Request Body:

{
  "days": 3
}

Functionality:

  • Calculates grace period expiration timestamp
  • Adds entry to gracePeriods Map
  • Saves to database/file
  • Returns grace period information with expiration date

3.4.7 Payment History

Route: GET /admin/api/payments

Authentication: Required

Response: Array of payment records (limited to 100 most recent):

[
  {
    "id": 1,
    "userId": "123456789",
    "transactionHash": "abc123...",
    "amount": 1000000,  // in USDT smallest unit
    "currency": "USDT",
    "paidAt": 1704067200000,
    "paidAtFormatted": "2024-01-01 10:00:00",
    "createdAt": 1704067200000
  }
]

Data Source: Only available if database is connected (queries payments table)

Limitation: Returns maximum 100 most recent payments, ordered by paid_at descending

4. CONFIGURATION AND ENVIRONMENT VARIABLES

All configuration is managed through environment variables, which can be set in a .env file (for local development) or in your hosting platform's environment variable settings (for production). The bot uses the dotenv package to load these variables at startup.

4.1 Required Variables

These variables must be set for the bot to function. Missing required variables will cause the bot to fail at startup.

Telegram Bot Configuration

Variable Type Description How to Obtain
BOT_TOKEN string, required Telegram bot token obtained from @BotFather. This token authenticates your bot with Telegram's API. 1. Open Telegram and message @BotFather
2. Send /newbot
3. Follow instructions to create bot
4. Copy the token provided
ADMIN_ID number, required Your Telegram User ID. Only this user can execute admin commands. Must be a numeric ID, not username. 1. Open Telegram and message @userinfobot
2. Send /start
3. Bot will reply with your User ID (numeric)

Telegram Channels and Groups Configuration

Variable Type Description Format Example
CHANNEL_IDS string, required Comma-separated list of private Telegram channel and group IDs that the bot will manage. The bot must be added as an administrator to these channels and groups with "Invite users" and "Ban users" permissions. -1003520607330,-1003620447473,-1003565861542
Note: No spaces between IDs, use commas only
CHANNEL_LABELS string, optional Human-readable labels for each channel and group, displayed in admin interface and messages. Format: channelId:label,channelId:label -1003520607330:Premium Channel 1,-1003620447473:VIP Group 2
Note: Labels can contain spaces and special characters

How to Get Channel and Group IDs:

  1. Add @userinfobot to your channel or group
  2. Forward any message from the channel or group to @userinfobot
  3. The bot will reply with the channel or group ID (starts with -100)
  4. Alternatively, use @getidsbot or check channel/group info via Telegram API

TON / USDT Payment Configuration

Variable Type Description Default Value
TON_API_URL string, required Base URL for TON Center API v2. This is the API used to verify USDT transactions on the TON blockchain. https://toncenter.com/api/v2
TON_API_KEY string, required API key for TON Center. Required for accessing transaction data. Free tier allows 1 request per second. - (must be obtained from TON Center)
TON_WALLET_ADDRESS string, required Your TON wallet address that will receive USDT payments. Must be a valid TON address (starts with UQ, EQ, or kQ). - (must be your wallet address)

How to Get TON Center API Key:

  1. Visit https://toncenter.com
  2. Sign up for a free account
  3. Navigate to API section
  4. Generate an API key
  5. Copy the key (starts with alphanumeric characters)

How to Get TON Wallet Address:

  1. Install a TON wallet (e.g., Tonkeeper, TON Wallet)
  2. Create or import a wallet
  3. Copy your wallet address (usually displayed in wallet app)
  4. Ensure the wallet supports USDT on TON network

Subscription Configuration

Variable Type Description Default Value
SUBSCRIPTION_AMOUNT_RUB number, required Subscription price in Russian Rubles (RUB). This amount will be converted to USDT using the exchange rate for actual payment. 90.0
USDT_TO_RUB_RATE number, required Exchange rate: 1 USDT = X RUB. Used to convert RUB subscription amount to USDT for payment. Can be updated automatically if EXCHANGE_RATE_AUTO is enabled. 90.0
EXCHANGE_RATE_AUTO boolean, optional Enable automatic exchange rate updates. If true, the bot will fetch USD/RUB rate from external API every 15 minutes and update USDT_TO_RUB_RATE automatically. false
EXCHANGE_RATE_SOURCE_URL string, optional URL for exchange rate API. Default uses exchangerate-api.com (free, no API key). Can be changed to use different exchange rate providers. https://api.exchangerate-api.com/v4/latest/USD
SUBSCRIPTION_DURATION_DAYS number, required Duration of subscription in days. When a user pays, their subscription will be active for this many days. Can be changed via admin commands without restart. 30
TRIAL_DAYS number, required Free trial period duration in days. When a user is added to a channel or group, they automatically get this many days of free access. Set to 0 to disable trials. 2
RENEWAL_REMINDER_DAYS number, required Number of days before subscription expiration to send renewal reminder notification. Set to 0 to disable reminders. 5

Database Configuration (Optional but Recommended)

Note: Database is optional. If not configured, the bot will use JSON file storage in the data/ directory. However, database is strongly recommended for production use as it provides better reliability and data persistence.

Variable Type Description Default Value
DB_HOST string, optional PostgreSQL database hostname. For Supabase, this is usually db.xxxxx.supabase.co. For local development, use localhost. localhost
DB_PORT number, optional PostgreSQL database port. Standard PostgreSQL port is 5432. For Supabase pooler, use 6543. 5432
DB_NAME string, optional Name of the PostgreSQL database. The bot will create all necessary tables automatically on first connection. vikkybot
DB_USER string, optional PostgreSQL database username. For Supabase, this is usually postgres. postgres
DB_PASSWORD string, optional PostgreSQL database password. Keep this secure and never commit to version control. -
DB_SSL boolean, optional Enable SSL/TLS for database connection. Required for most cloud database providers (Supabase, Render, etc.). Set to true for production. false
DB_USE_POOLER string, optional Use Supabase connection pooler. Options: auto (auto-detect), true (force pooler), false (direct connection). Pooler uses port 6543 and supports IPv4, which works better on Render and similar platforms. auto
DB_FORCE_IPV4 boolean, optional Force IPv4 for database connections. Recommended for Render and platforms that may have IPv6 connectivity issues. Helps avoid ENETUNREACH errors. true
DB_CONNECT_TIMEOUT_MS number, optional Database connection timeout in milliseconds. Increase this value if you experience timeout errors on cold starts (e.g., Supabase on Render). 10000 (10 seconds)

Admin Dashboard Configuration

Variable Type Description Default Value
ADMIN_PASSWORD string, required Password for accessing the web admin dashboard at /admin. Use a strong, unique password in production. ⚠️ CHANGE THIS IN PRODUCTION! admin123 ⚠️ MUST CHANGE
SESSION_SECRET string, required Secret key for signing session cookies. Should be a long, random string. Used by express-session to prevent session tampering. Generate a secure random string (64+ characters recommended). - (must be set)

How to Generate SESSION_SECRET:

  • Use Node.js: require('crypto').randomBytes(64).toString('hex')
  • Use online generator: Any secure random string generator
  • Use command line: openssl rand -hex 64

4.2 Complete .env File Example

Below is a complete example of a .env file with all configuration options. Copy this template and replace the placeholder values with your actual credentials.

# ============================================
# Telegram Bot Configuration
# ============================================
# Get BOT_TOKEN from @BotFather on Telegram
BOT_TOKEN=7998967333:AAEalbcIsUxISHxRTdwPHmS_2xU3oweJHe8

# Get ADMIN_ID from @userinfobot on Telegram
ADMIN_ID=348924425

# ============================================
# Telegram Channels and Groups Configuration
# ============================================
# Multiple channels and groups (comma-separated, no spaces)
# Get channel/group IDs by forwarding a message from channel or group to @userinfobot
CHANNEL_IDS=-1003520607330,-1003620447473,-1003565861542

# Channel and group labels for display (format: channelId:label,channelId:label)
# Optional: Makes channels and groups easier to identify in admin interface
CHANNEL_LABELS=-1003520607330:Premium Channel 1,-1003620447473:VIP Group 2,-1003565861542:Exclusive Channel 3

# ============================================
# USDT Payment Configuration (USDT on TON network)
# ============================================
# TON Center API base URL (usually don't change this)
TON_API_URL=https://toncenter.com/api/v2

# Get TON_API_KEY from https://toncenter.com
TON_API_KEY=5fa0f64bed5747f92b5b254fe08dca10c5f923daf57bf458e125dec993a8a7a3

# Your TON wallet address that will receive payments
# Get this from your TON wallet app (Tonkeeper, TON Wallet, etc.)
TON_WALLET_ADDRESS=UQD3_0o0m3ep4Gx63IubK2b0Xz3XoAKoWkkI20ws8Cz465fi

# ============================================
# Subscription Pricing Configuration
# ============================================
# Subscription price in Russian Rubles (RUB)
# This will be converted to USDT using the exchange rate below
SUBSCRIPTION_AMOUNT_RUB=90.0

# Exchange rate: 1 USDT = X RUB
# Update this manually or enable auto-update below
USDT_TO_RUB_RATE=90.0

# Enable automatic exchange rate updates (true/false)
# If true, fetches rate from external API every 15 minutes
EXCHANGE_RATE_AUTO=false

# Exchange rate API URL (free tier, no API key needed)
EXCHANGE_RATE_SOURCE_URL=https://api.exchangerate-api.com/v4/latest/USD

# ============================================
# Subscription Duration and Trial Configuration
# ============================================
# Subscription duration in days (how long each subscription lasts)
SUBSCRIPTION_DURATION_DAYS=30

# Free trial period in days (set to 0 to disable)
TRIAL_DAYS=2

# Days before expiration to send renewal reminder (set to 0 to disable)
RENEWAL_REMINDER_DAYS=5

# ============================================
# Database Configuration (PostgreSQL)
# Optional: If not set, bot uses JSON file storage
# Strongly recommended for production use
# ============================================
# Database hostname (for Supabase: db.xxxxx.supabase.co)
DB_HOST=db.xxxxx.supabase.co

# Database port (5432 for direct, 6543 for pooler)
DB_PORT=5432

# Database name
DB_NAME=telegram_subscription_bot

# Database username (usually 'postgres' for Supabase)
DB_USER=postgres

# Database password (keep secure!)
DB_PASSWORD=your_db_password_here

# Enable SSL for database connection (required for cloud providers)
DB_SSL=true

# Use Supabase connection pooler (auto/true/false)
# Recommended: 'auto' (auto-detects) or 'true' for Supabase
DB_USE_POOLER=auto

# Force IPv4 for database connections (recommended for Render)
DB_FORCE_IPV4=true

# Connection timeout in milliseconds (increase if experiencing timeouts)
DB_CONNECT_TIMEOUT_MS=10000

# ============================================
# Admin Dashboard Configuration
# ============================================
# Password for web admin dashboard at /admin
# ⚠️ CHANGE THIS TO A STRONG PASSWORD IN PRODUCTION!
ADMIN_PASSWORD=your_secure_password_here_change_this

# Secret for signing session cookies
# Generate with: require('crypto').randomBytes(64).toString('hex')
SESSION_SECRET=your_session_secret_change_this_to_random_64_char_string

# ============================================
# Server Configuration
# ============================================
# Port for Express web server (default: 3000)
PORT=3000

# Node environment (development/production)
NODE_ENV=production

Important Notes:

  • Never commit your .env file to version control (it should be in .gitignore)
  • Replace all placeholder values with your actual credentials
  • Use strong, unique passwords for ADMIN_PASSWORD and DB_PASSWORD
  • Generate a secure random string for SESSION_SECRET
  • For production, ensure NODE_ENV=production is set

5. EXTERNAL API INTEGRATIONS

The bot integrates with several external APIs to provide its functionality. This section documents each integration, including endpoints used, authentication methods, rate limits, and implementation details.

5.1 Telegram Bot API (via Telegraf)

Official Documentation: https://core.telegram.org/bots/api

Library Used: Telegraf v4.16.3 - A modern framework for building Telegram bots in Node.js

Authentication: Uses BOT_TOKEN from environment variables, automatically handled by Telegraf

API Methods Used:

  • bot.telegram.sendMessage(chatId, text, options): Send text messages to users or channels
  • bot.telegram.getChatMember(chatId, userId): Check if a user is a member of a chat/channel
  • bot.telegram.banChatMember(chatId, userId): Ban a user from a chat/channel (used to revoke access)
  • bot.telegram.unbanChatMember(chatId, userId): Unban a user from a chat/channel (used before granting access)
  • bot.telegram.createChatInviteLink(chatId, options): Create an invite link for a private channel
  • bot.telegram.getChat(chatId): Get information about a chat/channel
  • bot.telegram.getChatAdministrators(chatId): Get list of administrators in a chat/channel
  • bot.telegram.getUserProfilePhotos(userId, options): Get user profile photos for avatar display
  • bot.telegram.getFile(fileId): Get file information and download URL

Rate Limits:

  • Maximum 30 messages per second per bot
  • Telegraf automatically handles rate limiting and retries
  • If rate limit is exceeded, requests are queued and retried automatically

Update Method: The bot uses polling (bot.launch()) to receive updates from Telegram. This means the bot continuously polls Telegram's servers for new messages and events. Alternative: Webhooks (not implemented) would require a public HTTPS endpoint.

Event Handlers:

  • bot.start(): Handles /start command
  • bot.command('commandName'): Handles specific commands
  • bot.action('callbackData'): Handles inline button callbacks
  • bot.on('chat_member'): Handles user join/leave events in channels and groups

5.2 TON Center API

Official Documentation: https://toncenter.com/api/v2/

Base URL: https://toncenter.com/api/v2

Authentication: API key passed in X-API-Key header with value from TON_API_KEY environment variable

Purpose: Verify USDT transactions on the TON blockchain to confirm payments

Endpoints Used:

  • GET /getTransactions: Retrieve recent transactions for a wallet address
    • Parameters:
      • address: TON wallet address (from TON_WALLET_ADDRESS)
      • limit: Maximum number of transactions to return (default: 100)
      • to_lt: Transaction logical time to start from (0 for latest)
      • archival: Whether to include archived transactions (false for faster queries)
    • Response: Array of transaction objects containing:
      • transaction_id: Unique transaction identifier
      • in_msg: Incoming message data (contains comment and amount)
      • utime: Unix timestamp of transaction
      • fee: Transaction fee

Rate Limits:

  • Free Tier: 1 request per second
  • Paid Tiers: Higher limits available (see TON Center pricing)
  • Implementation: The bot respects rate limits by checking payments every 5 minutes (not every second)

Payment Verification Process:

  1. Retrieve last 100 transactions from wallet using getTransactions
  2. Filter by timestamp: Only consider transactions after payment request was created
  3. Filter by comment: Transaction comment must contain subscription_{userId} pattern
  4. Verify amount: Transaction amount must be ≥ 90% of expected amount (allows for small discrepancies)
  5. Verify destination: Transaction must be to the configured wallet address
  6. If all conditions met: Payment is confirmed and subscription is activated

Error Handling:

  • Network errors: Retried with exponential backoff
  • API errors: Logged and payment check is skipped (will retry on next interval)
  • Invalid responses: Validated before processing, errors logged

5.3 Exchange Rate API (Optional)

Service: exchangerate-api.com (free tier, no API key required)

Endpoint: GET https://api.exchangerate-api.com/v4/latest/USD

Purpose: Automatically update USDT to RUB exchange rate

Response Format:

{
  "base": "USD",
  "date": "2024-01-01",
  "rates": {
    "RUB": 90.5,
    "EUR": 0.92,
    ...
  }
}

Usage:

  • Fetches USD/RUB exchange rate from the API
  • Assumes USDT ≈ USD (standard assumption in cryptocurrency markets)
  • Updates usdtToRubRate in bot settings
  • Saves updated rate to database/file

Update Frequency: Every 15 minutes (if EXCHANGE_RATE_AUTO=true)

Fallback Behavior:

  • If API call fails: Keeps current configured rate
  • If response is invalid: Logs warning and keeps current rate
  • If rate is not a positive number: Rejects update and keeps current rate

Alternative Sources: Can be configured to use different exchange rate APIs by changing EXCHANGE_RATE_SOURCE_URL

5.4 Telegram File API

Endpoint: https://api.telegram.org/file/bot{BOT_TOKEN}/{file_path}

Purpose: Proxy for serving user avatars in the admin dashboard

Implementation:

  • Admin dashboard route: GET /admin/api/avatars/:userId
  • Server-side proxy that:
    1. Fetches user profile photos from Telegram API (using BOT_TOKEN server-side)
    2. Downloads the image file
    3. Streams the image to the client

Security Benefits:

  • Prevents BOT_TOKEN exposure to frontend JavaScript
  • Requires admin authentication (session-based)
  • Server-side validation of user IDs

Performance:

  • Limits to 10 avatar lookups per request to avoid rate limiting
  • Caches profile photos in userProfiles Map
  • Returns 404 if user has no avatar

6. DATA MANAGEMENT AND PERSISTENCE

The bot uses a hybrid storage approach: in-memory data structures (Maps and Sets) for fast access during runtime, with automatic persistence to either PostgreSQL database (preferred) or JSON files (fallback). This ensures both performance and data durability.

6.1 In-Memory Data Structures (Maps/Sets)

These data structures are loaded into memory at startup and kept synchronized with persistent storage. They provide O(1) lookup performance for critical operations.

userSubscriptions (Map<userId, subscription>)

Purpose: Fast storage of active user subscriptions

Structure:

{
  subscriptionId: "ton_123456_abc123",  // Unique subscription identifier
  expiresAt: 1234567890000,              // Expiration timestamp (milliseconds)
  createdAt: 1234567890000,             // Creation timestamp (milliseconds)
  transactionHash: "abc123...",          // TON blockchain transaction hash
  isRenewal: false                       // Whether this is a renewal or new subscription
}

Usage:

  • Quick lookup of subscription status for any user
  • Used in expiration checks to determine if subscription is still active
  • Updated when payment is confirmed or subscription expires

Persistence: Saved to data/state.json and PostgreSQL subscriptions table (if database available)

gracePeriods (Map<userId, expiryTimestamp>)

Purpose: Temporary grace periods that prevent user removal even if subscription expires

Structure: userId → expiryTimestamp (milliseconds since epoch)

Example: 123456789 → 1704153600000 (user 123456789 has grace until timestamp 1704153600000)

Usage:

  • Checked during expiration verification to prevent removal
  • Allows users extra time to pay without losing access
  • Automatically removed when grace period expires

Persistence: Saved to data/state.json and PostgreSQL grace_periods table

userChannels (Map<userId, [channelId1, channelId2, ...]>)

Purpose: Tracks which channels and groups a user was initially added to

Structure: userId → array of channel and group IDs

Example: 123456789 → ["-1003520607330", "-1003620447473"]

Usage:

  • Stored when user is first added to a managed channel or group
  • Used to grant access to all initial channels and groups when payment is confirmed
  • Used to revoke access from all channels and groups when subscription expires

Persistence: Saved to data/state.json and PostgreSQL user_channels table

trialAccess (Map<userId, {expiresAtMs, reminded24h}>)

Purpose: Tracks free trial periods for new users

Structure:

{
  expiresAtMs: 1234567890000,  // Trial expiration timestamp (milliseconds)
  reminded24h: false            // Whether 24-hour reminder has been sent
}

Usage:

  • Created automatically when user is added to a channel or group (if trial enabled)
  • Checked hourly for expiration
  • Used to send 24-hour reminder before trial ends
  • Removed when trial expires or user subscribes

Persistence: Saved to data/state.json and PostgreSQL trial_access table

whitelistedUsers (Set<userId>)

Purpose: Users with permanent free access (moderators, teachers, special users)

Structure: Set of user IDs, e.g., Set([123456, 789012, 555666])

Usage:

  • Checked during expiration verification to prevent removal
  • Users in whitelist never need to pay
  • Can be added/removed via admin commands or web interface

Persistence: Saved to data/state.json and PostgreSQL whitelisted_users table

pendingPayments (Map<userId, {timestamp, amount, comment, checked, currency}>)

Purpose: Tracks payments that are awaiting blockchain confirmation

Structure:

{
  timestamp: 1234567890000,                    // When payment was requested
  amount: 1000000,                             // Amount in USDT smallest unit (6 decimals)
  comment: "subscription_123456_1234567890",   // Unique payment comment
  checked: false,                               // Whether payment has been verified
  currency: "USDT"                             // Payment currency
}

Usage:

  • Created when user clicks "Subscribe" button
  • Used by background payment checker to verify transactions
  • Removed when payment is confirmed or manually cleared

Persistence: In-memory only (lost on restart, but recreated if user clicks "Check Payment" again)

Location: Stored in services/tonService.js as part of the TON service

6.2 PostgreSQL Database Schema

All tables are automatically created on first database connection if they don't exist. The bot uses the pg library for PostgreSQL interactions with connection pooling.

Table: subscriptions

Purpose: Stores active user subscriptions

CREATE TABLE subscriptions (
  user_id BIGINT PRIMARY KEY,              -- Telegram user ID (unique per user)
  subscription_id TEXT,                     -- Unique subscription identifier
  expires_at BIGINT NOT NULL,              -- Expiration timestamp (milliseconds)
  created_at BIGINT NOT NULL,              -- Creation timestamp (milliseconds)
  transaction_hash TEXT,                   -- TON blockchain transaction hash
  is_renewal BOOLEAN DEFAULT FALSE         -- Whether this is a renewal
);

CREATE INDEX idx_subscriptions_expires_at ON subscriptions(expires_at);

Indexes: Index on expires_at for fast expiration queries

Table: grace_periods

Purpose: Stores temporary grace periods for users

CREATE TABLE grace_periods (
  user_id BIGINT PRIMARY KEY,              -- Telegram user ID
  expires_at BIGINT NOT NULL               -- Grace period expiration timestamp (milliseconds)
);

Table: user_channels

Purpose: Maps users to their initial channels and groups (many-to-many relationship)

CREATE TABLE user_channels (
  user_id BIGINT NOT NULL,                 -- Telegram user ID
  channel_id TEXT NOT NULL,                -- Telegram channel ID
  PRIMARY KEY (user_id, channel_id)        -- Composite primary key
);

Note: One user can have multiple channels, one channel can have multiple users

Table: whitelisted_users

Purpose: Stores users with permanent free access

CREATE TABLE whitelisted_users (
  user_id BIGINT PRIMARY KEY,              -- Telegram user ID
  added_at BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()) * 1000  -- When user was whitelisted
);

Table: trial_access

Purpose: Tracks free trial periods for users

CREATE TABLE trial_access (
  user_id BIGINT PRIMARY KEY,              -- Telegram user ID
  expires_at_ms BIGINT NOT NULL,           -- Trial expiration timestamp (milliseconds)
  reminded_24h BOOLEAN DEFAULT FALSE       -- Whether 24-hour reminder was sent
);

Table: payments

Purpose: Historical record of all confirmed payments

CREATE TABLE payments (
  id SERIAL PRIMARY KEY,                   -- Auto-incrementing payment ID
  user_id BIGINT NOT NULL,                 -- Telegram user ID
  transaction_hash TEXT NOT NULL,          -- TON blockchain transaction hash
  amount BIGINT NOT NULL,                  -- Amount in USDT smallest unit (6 decimals)
  currency TEXT DEFAULT 'USDT',            -- Payment currency
  paid_at BIGINT NOT NULL,                 -- When payment was made (timestamp, milliseconds)
  created_at BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()) * 1000  -- Record creation time
);

CREATE INDEX idx_payments_user_id ON payments(user_id);
CREATE INDEX idx_payments_paid_at ON payments(paid_at);

Indexes: Indexes on user_id and paid_at for fast queries

Usage: Used for revenue calculations and payment history in admin dashboard

Table: settings

Purpose: Stores bot configuration settings as key-value pairs

CREATE TABLE settings (
  key TEXT PRIMARY KEY,                    -- Setting key (e.g., 'bot_settings')
  value JSONB NOT NULL,                    -- Setting value as JSON
  updated_at BIGINT NOT NULL DEFAULT EXTRACT(EPOCH FROM NOW()) * 1000  -- Last update timestamp
);

Usage: Stores bot settings with key 'bot_settings' and value as JSON object containing all configuration

JSONB Benefits: Allows efficient querying and indexing of JSON data in PostgreSQL

6.3 File Storage (Fallback if Database Unavailable)

If PostgreSQL database is not configured or unavailable, the bot automatically falls back to JSON file storage in the data/ directory. This ensures the bot continues to function even without a database.

File: data/state.json

Purpose: Stores all user state data (subscriptions, trials, grace periods, channels, whitelist)

Structure:

{
  "userSubscriptions": {
    "123456": {
      "subscriptionId": "ton_123456_abc123",
      "expiresAt": 1234567890000,
      "createdAt": 1234567890000,
      "transactionHash": "abc123...",
      "isRenewal": false
    }
  },
  "gracePeriods": {
    "123456": 1234567890000
  },
  "userChannels": {
    "123456": ["-1003520607330", "-1003620447473"]
  },
  "trialAccess": {
    "123456": {
      "expiresAtMs": 1234567890000,
      "reminded24h": false
    }
  },
  "whitelistedUsers": [123456, 789012],
  "userProfiles": {
    "123456": {
      "username": "john_doe",
      "firstName": "John",
      "lastName": "Doe",
      "updatedAt": 1234567890000
    }
  },
  "savedAt": "2024-01-01T00:00:00.000Z"
}

Auto-Creation: File is automatically created if it doesn't exist

Auto-Save: Saved automatically when state changes (with debouncing to prevent excessive writes)

File: data/settings.json

Purpose: Stores bot configuration settings

Structure:

{
  "subscriptionAmountRub": 90.0,
  "usdtToRubRate": 90.0,
  "exchangeRateAuto": false,
  "exchangeRateSourceUrl": "https://api.exchangerate-api.com/v4/latest/USD",
  "exchangeRateLastUpdatedMs": null,
  "subscriptionDurationDays": 30,
  "trialDays": 2,
  "renewalReminderDays": 5
}

Auto-Creation: File is automatically created with default values if it doesn't exist

Auto-Save: Saved immediately when settings are changed via admin commands or web interface

6.4 Persistence Strategy

The bot uses a smart persistence strategy that prioritizes database storage but gracefully falls back to file storage when needed.

Storage Priority

  1. Database (Primary): If database is available and connected, all data is saved to PostgreSQL
  2. File Storage (Fallback): If database is unavailable, data is saved to JSON files in data/ directory

Startup Process

  1. Attempts to connect to PostgreSQL database (if configured)
  2. If database connection succeeds:
    • Creates tables if they don't exist
    • Loads data from database into in-memory Maps/Sets
    • If data/state.json exists and is newer than database data, syncs file data to database
  3. If database connection fails:
    • Logs warning message
    • Falls back to file storage
    • Loads data from data/state.json and data/settings.json
    • Bot continues to function normally

Write Operations

  • Immediate Writes: Settings changes are saved immediately (both to DB and file if DB unavailable)
  • Debounced Writes: State changes use saveStateSoon() function with 500ms debounce to prevent excessive file writes
  • Dual Write: When database is available, data is written to both database and file (for redundancy)

Data Synchronization

  • On startup: If both database and file exist, database takes priority
  • If file is newer than database: File data is synced to database (one-time migration)
  • During runtime: Database is always the source of truth if available

Performance Considerations

  • In-memory Maps/Sets provide O(1) lookup performance
  • Database queries use indexes for fast expiration checks
  • File writes are debounced to prevent I/O bottlenecks
  • State is only saved when changes occur (not on every read)

7. SECURITY AND PERMISSIONS

7.1 Admin Authentication

Method: Simple password authentication stored in ADMIN_PASSWORD environment variable

Session Management:

  • Uses express-session for session management
  • Session cookies configured with:
    • httpOnly: true - Prevents JavaScript access to cookies
    • sameSite: 'lax' - CSRF protection
    • maxAge: 24 * 60 * 60 * 1000 - 24-hour session expiration
    • secure: false - Set to true in production with HTTPS

Protected Routes: All routes under /admin/api/* (except /auth/*) use requireAuth() middleware to verify session

⚠️ Recommended Improvement: Use bcrypt to hash passwords (bcryptjs is already installed but not currently used for password hashing)

7.2 Token Security

  • BOT_TOKEN: Never exposed to frontend. Avatar proxy route (/admin/api/avatars/:userId) handles Telegram API calls server-side
  • TON_API_KEY: Stored only server-side in environment variables, never sent to client
  • SESSION_SECRET: Used to sign session cookies, preventing tampering. Must be a strong, random string
  • Database Credentials: Stored in environment variables, never logged or exposed

7. Input Validation

  • Admin Commands: All admin commands verify ctx.from.id === ADMIN_ID before execution
  • Settings Parameters: All settings are validated for type, min/max values, and format before saving
  • User IDs: Parsed with parseInt() and validated (checked for NaN, must be positive integers)
  • API Requests: Request bodies are validated before processing
  • SQL Injection Prevention: Uses parameterized queries via pg library

7.4 Error Handling

  • Try-Catch Blocks: All async operations are wrapped in try-catch blocks to prevent crashes
  • Error Logging: Errors are logged with console.error() for debugging
  • Graceful Degradation: If database is unavailable, bot continues with file storage without crashing
  • Rate Limiting: Automatically handled by Telegraf for Telegram API calls
  • API Error Handling: Network errors and API failures are caught and logged, with retry logic where appropriate

8. DEPLOYMENT AND HOSTING

8.1 Prerequisites

  • Node.js 14+ installed
  • Telegram account with bot created via @BotFather
  • TON Center account with API key
  • TON wallet configured
  • (Optional) PostgreSQL database (Supabase, Render, etc.)

8.2 Deployment on Render

  1. Create Render account: https://render.com
  2. Connect GitHub/GitLab repository
  3. Create Web Service:
    • Name: telegram-subscription-bot (or any name you prefer)
    • Environment: Node
    • Build Command: npm install
    • Start Command: npm start
    • Plan: Free (or paid to avoid sleep)
  4. Configure environment variables: Copy all variables from .env
  5. Deploy: Render builds and starts automatically
  6. Health check: Route /health for monitoring

8.3 Deployment on Other Platforms

  • Vercel: Compatible (serverless functions)
  • Railway: Compatible (direct deployment)
  • Heroku: Compatible (Git deployment)
  • VPS: Compatible (PM2 recommended for process management)

8.4 Database Configuration (Supabase)

  1. Create Supabase project: https://supabase.com
  2. Retrieve credentials: Host, port, database, user, password
  3. Configure variables:
    • DB_HOST=db.xxxxx.supabase.co
    • DB_SSL=true
    • DB_USE_POOLER=auto (recommended to avoid IPv6 issues)
  4. Tables created automatically: The bot creates tables on first startup

8.5 Monitoring and Logs

  • Render Logs: Accessible via Render dashboard
  • Health check: GET /health returns { status: 'ok', timestamp: ... }
  • Console logs: All important events are logged

9. LIMITATIONS AND CONSIDERATIONS

9.1 Technical Limitations

  • Ephemeral file storage: On Render (Free plan), files are lost on restart → Use database in production
  • Telegram rate limiting: 30 messages/second max per bot
  • TON Center rate limiting: Free plan = 1 req/sec
  • Polling vs Webhooks: The bot uses polling (no Telegram webhook configured)
  • Payment verification: Delay up to 5 minutes (verification interval)

9.2 Functional Limitations

  • Single wallet: All payments go to the same wallet (no multi-wallet support)
  • Single amount: No multiple subscription plans (only one configured price)
  • No refunds: No automatic refund system
  • No invoices: No PDF invoice generation
  • No email notifications: Only Telegram notifications

9.3 SaaS Considerations

To transform into a "simple" SaaS where users just enter their info and the bot starts automatically, it would require:

  • Automatic Telegram bot creation:
    • Use unofficial BotFather API (risky)
    • Or guided step-by-step process with verifications
  • Automatic channel configuration:
    • User must create channels manually
    • User must add bot as admin manually
    • Cannot be fully automated (Telegram API limitations)
  • Automatic TON wallet creation:
    • Possible via TON API (complex)
    • Or guide user to create wallet
  • Automatic deployment:
    • Use Render/Vercel API to create services
    • Generate GitHub repo with user config
    • Deploy automatically
  • Multi-tenant architecture:
    • Alternative: Single bot managing multiple "tenants"
    • Each user has their isolated configuration space
    • Resource sharing (less expensive)

9.4 Production Recommendations

  • ✅ Use PostgreSQL database (not file storage)
  • ✅ Change default ADMIN_PASSWORD
  • ✅ Use strong SESSION_SECRET (64 random characters)
  • ✅ Enable EXCHANGE_RATE_AUTO for up-to-date exchange rates
  • ✅ Monitor logs for errors
  • ✅ Regular database backups
  • ⚠️ Consider paid TON Center plan if many users
  • ⚠️ Consider paid Render plan to avoid sleep (Free plan goes to sleep after inactivity)

10. TECHNICAL ROADMAP FOR SAAS

10.1 Phase 1: Guided Configuration Assistant (Recommended)

Objective: Web wizard that guides the user step by step

Features:

  • Step 1 - Telegram Bot Creation:
    • Clear instructions with screenshots
    • Form to enter BOT_TOKEN
    • Automatic token verification (connection test)
  • Step 2 - Channel Configuration:
    • Instructions to create channels
    • Instructions to add bot as admin
    • Form to enter CHANNEL_IDS
    • Automatic verification (can bot access channels?)
  • Step 3 - TON Configuration:
    • Instructions to create TON Center account
    • Form to enter TON_API_KEY and TON_WALLET_ADDRESS
    • Automatic verification (test API call)
  • Step 4 - Subscription Configuration:
    • Form for amount, duration, trial period
    • Parameter preview
  • Step 5 - Deployment:
    • Option A: Generate GitHub repo with config
    • Option B: Deploy automatically via Render API
    • Final instructions

Technical Stack:

  • Frontend: React/Next.js for the wizard
  • Backend: Express API for verifications and config generation
  • Deployment: Render/Vercel API for automatic service creation

10.2 Phase 2: Multi-Tenant Architecture

Objective: Single bot managing multiple users (tenants)

Required Modifications:

  • Tenants table in DB:
    CREATE TABLE tenants (
      id SERIAL PRIMARY KEY,
      user_id BIGINT, -- Telegram user ID of owner
      bot_token TEXT,
      channel_ids TEXT[],
      ton_api_key TEXT,
      ton_wallet_address TEXT,
      settings JSONB,
      created_at TIMESTAMP
    );
  • Message routing:
    • Identify which tenant manages which channel
    • Route commands to the correct context
  • Data isolation:
    • All in-memory Maps become Map<tenantId, Map<userId, ...>>
    • Or use DB only (simpler)
  • Management interface:
    • Dashboard to create/manage multiple bots
    • Each user can have multiple instances

Advantages:

  • Resource sharing (less expensive)
  • Single deployment to maintain
  • Simpler scaling

Disadvantages:

  • More complex to develop
  • Risk of confusion if multiple tenants use same channels
  • Telegram rate limiting shared between all tenants

10.3 Phase 3: Complete Automation

Objective: User just enters their info, everything happens automatically

Technical Challenges:

  • Telegram bot creation:
    • Unofficial BotFather API (risky, may be blocked)
    • Alternative: Semi-automated process with verifications
  • Channel creation:
    • Impossible via Telegram API (user must create manually)
    • Solution: Very clear instructions + automatic verification
  • TON wallet creation:
    • Possible via TON API but complex
    • Alternative: Guide user or use third-party service
  • Automatic deployment:
    • ✅ Possible via Render/Vercel API
    • Generate GitHub repo automatically
    • Create Render service automatically
    • Configure environment variables automatically

Technical Stack:

  • GitHub API: Create repo, push code
  • Render API: Create web service, configure env vars
  • TON API: Create wallet (if possible)
  • Telegram API: Verify token, verify channel access

11. TESTING AND TROUBLESHOOTING

11.1 Tests to Perform

  • Bot creation test: Verify that BOT_TOKEN works
  • Channel addition test: Verify that bot can access channels
  • Payment test: Perform a real payment and verify detection
  • Expiration test: Wait for trial/subscription expiration and verify revoke
  • Admin dashboard test: Verify authentication and all routes
  • Database test: Verify that data is properly saved

11.2 Common Issues and Solutions

Bot won't start

  • Cause: Missing or incorrect environment variables
  • Solution: Check .env, check error logs

Payments not detected

  • Cause: Incorrect TON_API_KEY, incorrect wallet address, blockchain delay
  • Solution: Verify credentials, wait 5 minutes, use "Check Payment"

User not added to channel

  • Cause: Bot not admin of channel, incorrect CHANNEL_ID, insufficient permissions
  • Solution: Verify that bot is admin with "Invite users" and "Ban users" permissions

DB connection failed

  • Cause: Incorrect credentials, IPv6 network issue, timeout
  • Solution: Verify credentials, enable DB_USE_POOLER=auto for Supabase, increase DB_CONNECT_TIMEOUT_MS

Admin dashboard inaccessible

  • Cause: Incorrect password, expired session
  • Solution: Verify ADMIN_PASSWORD, reconnect

12. METRICS AND ANALYTICS

12.1 Available Metrics

  • Active subscriptions: Number of users with non-expired subscription
  • Total users: Total number of users who have had a subscription
  • Whitelisted users: Number of users with permanent free access
  • Total revenue: Sum of all payments (if DB available)
  • Recent payments: History of the last 100 payments

12.2 Where to Find Metrics

  • Admin dashboard: Route /admin/api/stats
  • Telegram command: /settings (displays basic statistics)
  • Database: Tables subscriptions, payments for advanced analytics

12.3 Advanced Analytics (to implement)

  • Growth charts (new subscribers per day)
  • Conversion rate (trials → payments)
  • Retention rate (renewals)
  • Revenue by period (day/week/month)

13. USER DOCUMENTATION

13.1 End User Guide (for subscribers)

  • How to start the bot (/start)
  • How to subscribe (Subscribe button)
  • How to pay (Telegram Wallet instructions)
  • How to verify payment
  • How to check status (/status)
  • FAQ (payment not detected, expiration, etc.)

13.2 Administrator Guide

  • Initial configuration (environment variables)
  • Available Telegram commands
  • Using the admin dashboard
  • User management (whitelist, grace period)
  • Modifying settings
  • Deployment and maintenance

14. POSSIBLE FUTURE IMPROVEMENTS

14.1 Features

  • Multiple subscription plans (monthly, quarterly, annual)
  • Promo codes / discounts
  • Referral system
  • Email notifications in addition to Telegram
  • PDF invoice generation
  • Multi-currency support (not just RUB/USDT)
  • Refund system
  • Advanced analytics with charts
  • Data export (CSV/JSON)

14.2 Technical Improvements

  • Telegram webhooks (instead of polling) for better performance
  • Redis cache for sessions and frequent data
  • Queue system (Bull/BullMQ) for asynchronous tasks
  • Unit and integration tests
  • CI/CD pipeline
  • Monitoring with Sentry
  • Structured logging (Winston)
  • Public REST API for third-party integrations

14.3 UX Improvements

  • More modern admin interface (React with Material-UI)
  • Push notifications for important events
  • Integrated support chat
  • Interactive documentation
  • Video tutorials

15. CONCLUSION

This comprehensive technical documentation provides all the information necessary to understand, maintain, and extend the Telegram TON Subscription Bot system. The system is fully functional in its current state and can be enhanced to become a complete SaaS solution with full automation of configuration and deployment.

Key Takeaways

  • Modular and Extensible Architecture: Clean separation of concerns with service-based design (TON service, channel service, database service)
  • Multi-Channel & Group Support: Granular management of multiple Telegram channels and groups with individual access control
  • Robust Blockchain Payment System: Automated USDT payment verification on TON network with transaction matching and amount tolerance
  • Comprehensive Administration Interface: Both Telegram commands and web dashboard for complete bot management
  • Flexible Persistence: Database-first approach with automatic fallback to file storage for reliability
  • Production-Ready: With minor security adjustments (bcrypt password hashing, HTTPS), the system is ready for production deployment

Recommended Next Steps

  • Security Enhancements: Implement bcrypt password hashing for ADMIN_PASSWORD (bcryptjs is already installed)
  • Testing: Add unit tests and integration tests for critical functionality (payment verification, subscription management)
  • SaaS Wizard: Create a guided configuration wizard for SaaS deployment (web interface for initial setup)
  • Multi-Tenant Architecture: If needed, implement multi-tenant support for managing multiple bot instances
  • Monitoring and Alerting: Add comprehensive monitoring (Sentry, logging) and alerting for production environments
  • Documentation: Create user-facing documentation and video tutorials for end users

Support and Maintenance

This documentation serves as a complete reference for developers working with the codebase. For questions or issues, refer to the relevant sections:

  • Configuration Issues: See Section 4 (Configuration and Environment Variables)
  • Payment Problems: See Section 5.2 (TON Center API) and Section 11 (Testing & Troubleshooting)
  • Deployment Questions: See Section 8 (Deployment and Hosting)
  • Command Reference: See Section 3 (Detailed Features) for all user and admin commands
  • API Integration: See Section 5 (External API Integrations) for API details

Thank you for using the Telegram TON Subscription Bot! This system provides a solid foundation for managing paid subscriptions to Telegram channels and groups using cryptocurrency payments.