Skip to content

πŸš€ release: v1.0.0-rc1#49

Merged
warengonzaga merged 174 commits intomainfrom
dev
Jul 24, 2025
Merged

πŸš€ release: v1.0.0-rc1#49
warengonzaga merged 174 commits intomainfrom
dev

Conversation

@warengonzaga
Copy link
Member

@warengonzaga warengonzaga commented Jul 8, 2025

Summary by CodeRabbit

New Features

  • Introduced a clean, modular command architecture with a centralized registry, supporting extensible command, conversation, and callback processing.
  • Added admin commands for activation, group setup, and template management, including interactive setup wizards and validation.
  • Implemented a simplified global template system for customizing ticket-related messages.
  • Added robust in-memory attachment handling with security, validation, retry logic, and performance monitoring.
  • Enhanced support for media group messages and unified attachment processing in ticket workflows.
  • Added utilities for email management, permission validation, admin/session management, and input validation (email, UUID, customer name, summary).
  • Introduced context-aware, user-friendly status messaging for ticket and agent interactions.
  • Provided comprehensive error handling, classification, sanitization, and user notification systems.
  • Added detailed environment variable validation with placeholder detection and admin user management.
  • Improved ticket, user, group config, and admin profile management with schema validation, JSON serialization, atomic updates, and session lifecycle handling.
  • Enhanced bot lifecycle with session cleanup tasks and graceful shutdown procedures.
  • Added detailed permission management for user admin access and bot admin status with user guidance.
  • Introduced comprehensive setup validation service for group configuration checks.
  • Added new utility modules for markdown escaping, message content extraction, smart message generation, and error context building.
  • Added logging configuration and startup/runtime logging utilities for consistent and configurable log output.
  • Added migration guide and expanded documentation including chat mode personas and usage examples.

Bug Fixes

  • Improved reliability and clarity of environment variable validation, setup, and error reporting.
  • Fixed issues with message content extraction, command detection in captions, and handling of attachment-only replies.
  • Disabled Unthreadβ†’Telegram attachment forwarding due to upstream API issues, with user notification and logging.

Documentation

  • Significantly expanded and clarified README, contributing guide, and environment variable examples.
  • Added new chat mode configuration files for specialized AI personas and planning.
  • Updated inline documentation and code comments for clarity and maintainability.
  • Added detailed migration instructions and logging configuration usage guide.

Chores

  • Added and updated scripts for linting, dead code, and unused import validation.
  • Introduced ESLint configuration and Nodemon setup for development workflow.
  • Added VSCode tasks for streamlined building.

Style

  • Refined import statements, code formatting, and logging for consistency.
  • Updated version annotations and metadata across files.

Tests

  • Enhanced validation and error handling logic to support robust testing and troubleshooting.

Refactor

  • Reorganized command and processor logic for maintainability and extensibility.
  • Centralized template and attachment handling, replacing legacy per-group and file-based approaches.
  • Consolidated command execution wrappers to reduce duplication and improve error handling consistency.

@warengonzaga warengonzaga added this to the πŸ“¦ v1.0.0-rc1 milestone Jul 8, 2025
@warengonzaga warengonzaga self-assigned this Jul 8, 2025
Copilot AI review requested due to automatic review settings July 8, 2025 07:02
@warengonzaga warengonzaga added api API integration and external services (Issues/PRs) database Database and data handling (Issues/PRs) deployment Deployment and infrastructure-related (Issues/PRs) sponsored Sponsored by GitHub Sponsors (Issues/PRs) maintainer Maintainer expertise required (Issues/PRs) labels Jul 8, 2025
@warengonzaga warengonzaga moved this to In Review in Unthread Partnership Jul 8, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This release candidate adds comprehensive admin controls, group configuration/setup flows, and enhanced environment validation for the Unthread Telegram Bot.

  • Introduces permission utilities (validateAdminAccess, hasAdminAccess, requireAdminAccess) and bot-level permission checks (isBotAdmin, setup prompts)
  • Implements a multi-step /setup wizard with state management stored in BotsStore
  • Enhances environment validation (placeholder detection, required ADMIN_USERS) and updates documentation/README

Reviewed Changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/utils/permissions.ts Added admin permission validation and decorators
src/utils/botPermissions.ts Checks bot’s admin status, sends prompts and retry flows
src/services/unthread.ts Modified customer lookup to require explicit setup
src/sdk/types.ts Added GroupConfig and SetupState interfaces
src/sdk/bots-brain/BotsStore.ts Extended store with group config and setup state operations
src/index.ts Registered new setup command
src/events/message.ts Integrated setup text handling into message flow
src/config/env.ts Enhanced env var validation, added ADMIN_USERS
src/commands/index.ts Implemented /setup handler, help text adaptation
README.md Updated setup instructions and admin-user requirements
.env.example Added ADMIN_USERS documentation and Redis requirement notes
.env.railway Marked ADMIN_USERS as required
Comments suppressed due to low confidence (1)

src/sdk/types.ts:119

  • New GroupConfig and SetupState interfaces and their store operations have been added without corresponding unit or integration tests. Consider adding tests to validate serialization, retrieval, and update flows for group configuration and setup state.
export interface GroupConfig {

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 8, 2025

πŸ“ Walkthrough

Walkthrough

Sir, this update delivers a comprehensive system overhaul, introducing a modular command architecture, advanced attachment handling, robust admin and permission management, a global template system, and a suite of new utilities for validation, error handling, and email management. Extensive documentation, configuration, and code quality tooling have also been integrated, all while maintaining a clean, maintainable codebase.

Changes

Files / Groups Change Summary
.env.example, .env.railway Expanded with detailed comments, new variables (BOT_USERNAME, ADMIN_USERS, MY_COMPANY_NAME, DUMMY_EMAIL_DOMAIN), and clarifications for setup and Redis URLs.
.gitignore Added ignore rules for context/ and .dccache.
README.md, CONTRIBUTING.md Significantly expanded documentation: setup, advanced logging, troubleshooting, architecture, contributing, and webhook integration requirements.
package.json, eslint.config.js, .vscode/tasks.json, nodemon.json, .github/workflows/validate.yml Updated version, dependencies, scripts, ESLint config, VSCode tasks, Nodemon config, and CI workflow to enhance code quality, validation, and developer tooling.
.github/chatmodes/... Introduced four new chat mode configuration files defining expert AI personas for code review, planning, implementation, and security.
src/bot.ts, src/index.ts Refactored bot initialization and lifecycle to use the new command registry, improved logging, and session cleanup management.
src/commands/index.ts, src/commands/base/BaseCommand.ts, src/commands/base/CommandRegistry.ts Introduced a modular command registry pattern, abstract base command class, and centralized command/conversation/callback processor management.
src/commands/basic/InfoCommands.ts, src/commands/basic/SetEmailCommand.ts, src/commands/basic/StateCommands.ts, src/commands/basic/ViewEmailCommand.ts, src/commands/admin/AdminCommands.ts, src/commands/support/SupportCommandClean.ts Added modular implementations for start, help, version, about, set email, view email, cancel, reset, activate, setup, templates, and support commands with robust metadata, permission, and context checks.
src/commands/processors/ConversationProcessors.ts Implemented conversation processors for support and DM setup flows using the Chain of Responsibility pattern.
src/commands/utils/errorHandler.ts, src/commands/utils/uuidValidator.ts, src/commands/utils/validation.ts Introduced comprehensive error handling, UUID validation, and input validation utilities.
src/config/env.ts Enhanced environment variable validation, admin management, and detailed error reporting.
src/config/globalTemplates.ts, src/utils/globalTemplateManager.ts Added a simplified global template system with default templates and variable management for ticket-related events.
src/database/connection.ts, src/database/schema.sql Minor documentation and type annotation updates; removed alpha phase note.
src/events/message.ts Overhauled message handling: unified attachment extraction, media group batching, enhanced ticket/agent reply processing, and status feedback.
src/handlers/webhookMessage.ts Enhanced agent message handling, integrated global template rendering, disabled attachment forwarding with user notification, and improved logging.
src/sdk/bots-brain/BotsStore.ts, src/sdk/bots-brain/UnifiedStorage.ts, src/sdk/bots-brain/index.ts Extended BotsStore with schema validation, group config, setup/session/admin profile management, and unified storage enhancements. Removed in-memory stats method.
src/sdk/types.ts Refined types: added admin profile, setup session, group config, and extended storage interface for new entities.
src/sdk/unthread-webhook/EventValidator.ts, src/sdk/unthread-webhook/WebhookConsumer.ts, src/sdk/unthread-webhook/index.ts Improved event validation for attachments, safer conversation ID extraction, and updated version annotation.
src/services/unthread.ts Refactored customer/user creation, enforced group config checks, added attachment support, new helper functions, and enhanced error handling/logging.
src/services/validationService.ts Introduced a validation service for setup checks, including bot admin and message-sending capability validation.
src/utils/permissions.ts Added unified user/bot permission management with admin checks, bot admin prompts, and detailed logging.
src/utils/adminManager.ts Introduced admin profile/session management, notification system, and session cleanup utilities.
src/utils/attachmentHandler.ts Implemented a robust, memory-buffer-based attachment handler with security, retry, and performance features.
src/utils/emailManager.ts Added utilities for email validation, dummy email generation, user email preferences, and pending agent message delivery.
src/utils/errorHandler.ts Introduced attachment error classification, user notification, and logging utilities.
src/utils/markdownEscape.ts Utilities for safe Markdown escaping and formatting in Telegram messages.
src/utils/messageAnalyzer.ts, src/utils/messageContentExtractor.ts, src/utils/messageExamples.ts Added message/attachment analysis, content extraction, and example-driven smart status message generation.
src/utils/simpleValidators.ts Added simple input validation and statistics for support ticket summaries.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~180 minutes. The update is extensive, affecting core architecture, message handling, permissions, admin/session management, storage, validation, error handling, and documentation across numerous files and modules.

Possibly related PRs

  • πŸš€ release: v1.0.0-beta.6Β #33: The main PR expands and refines environment variable declarations and validation, including adding ADMIN_USERS and BOT_USERNAME, and enhances environment validation logic in src/config/env.ts, while the retrieved PR πŸš€ release: v1.0.0-beta.6Β #33 adds a single new environment variable UNTHREAD_DEFAULT_PRIORITY and introduces a function to get its value in src/config/env.ts; both modify the same environment configuration module and deal with environment variable declarations and validation, showing a direct and strong connection at the code level.

Suggested labels

release, maintainers only

Note

⚑️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • πŸ“ Generate Docstrings
πŸ§ͺ Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

πŸͺ§ Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai auto title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (6)
src/services/unthread.ts (1)

531-531: Consider employing optional chaining for enhanced elegance, sir.

While your current implementation is perfectly functional, optional chaining would provide a more streamlined approach.

-        if (groupConfig && groupConfig.isConfigured && groupConfig.customerId) {
+        if (groupConfig?.isConfigured && groupConfig?.customerId) {
src/sdk/bots-brain/BotsStore.ts (1)

894-932: Consider enhancing batch operation resilience, sir.

While Promise.all provides excellent performance, a single failure will reject the entire batch. For production resilience, Promise.allSettled would allow partial success scenarios.

 async storeGroupConfigs(configs: GroupConfig[]): Promise<boolean> {
   try {
-    await Promise.all(configs.map(config => this.storeGroupConfig(config)));
-    return true;
+    const results = await Promise.allSettled(configs.map(config => this.storeGroupConfig(config)));
+    const failures = results.filter(r => r.status === 'rejected');
+    if (failures.length > 0) {
+      LogEngine.warn(`Partial batch failure: ${failures.length}/${configs.length} configs failed to store`);
+    }
+    return failures.length === 0;
   } catch (error) {
     LogEngine.error('Error storing group configs:', error);
     return false;
   }
 }

This pattern should be applied to all batch operations for consistent error handling.

src/commands/index.ts (4)

156-169: Sir, I've detected a minor inefficiency in the user verification logic.

While the current implementation is functional, we could enhance it with optional chaining for a more elegant solution.

-    const telegramUserId = ctx.from?.id;
-    
-    if (!telegramUserId) {
+    if (!ctx.from?.id) {
         LogEngine.warn('Help command: No user ID in context', {
             chatId: ctx.chat?.id,
             chatType: ctx.chat?.type
         });
         await safeReply(ctx, '❌ Unable to determine user permissions. Please try again.', { parse_mode: 'Markdown' });
         return;
     }
     
+    const telegramUserId = ctx.from.id;
     // Check if user is admin
     const isAdmin = isAdminUser(telegramUserId);

294-295: Sir, I recommend consolidating this with the existing isAdmin call to enhance code clarity.

The await keyword appears unnecessary here, as isAdminUser returns a synchronous boolean value according to the imported function signature.

-        const isAdmin = await isAdminUser(ctx.from.id);
+        const isAdmin = isAdminUser(ctx.from.id);

1594-1736: Sir, the processCustomerNameInput function exceeds optimal complexity thresholds.

Consider extracting the validation warning logic into a separate function to improve maintainability and testability.

// Add this helper function
async function handleValidationWarning(
    ctx: BotContext, 
    setupState: any, 
    validation: any, 
    customerName: string
): Promise<boolean> {
    let warningMessage = validation.message + '\n\n**Suggestions for improvement:**\n';
    validation.suggestions.forEach((suggestion: string, index: number) => {
        warningMessage += `${index + 1}. ${suggestion}\n`;
    });
    warningMessage += '\n**Continue anyway?** Reply with the same name to proceed, or provide a different name.';
    
    if (setupState.metadata?.lastWarningName !== customerName) {
        await BotsStore.updateSetupState(setupState.chatId, {
            metadata: {
                ...setupState.metadata,
                lastWarningName: customerName
            }
        });
        
        await safeReply(ctx, warningMessage, { parse_mode: 'Markdown' });
        return true; // Warning shown, await user confirmation
    }
    return false; // User confirmed, proceed
}

Then simplify the main function by calling this helper.


2044-2051: Sir, the customer ID format validation might be overly restrictive.

Some enterprise systems use different ID formats. Consider making this validation configurable or more lenient.

Add support for additional common ID formats:

     const commonFormats = [
         /^cust_[a-zA-Z0-9]+$/,           // Stripe-like: cust_1234567890
         /^customer-[a-zA-Z0-9-]+$/,     // Dash format: customer-abc-123
         /^[a-zA-Z0-9]{8,}$/,            // Simple alphanumeric: abc123def456
         /^[0-9]+$/,                     // Numeric only: 1234567890
-        /^[a-zA-Z]+[0-9]+$/             // Letters + numbers: customer123
+        /^[a-zA-Z]+[0-9]+$/,            // Letters + numbers: customer123
+        /^[A-Z]{2,}-[0-9]+$/,           // Prefix format: UK-123456
+        /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i  // UUID format
     ];
πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between f0955c1 and db00696.

πŸ“’ Files selected for processing (13)
  • .env.example (2 hunks)
  • .env.railway (1 hunks)
  • .gitignore (1 hunks)
  • README.md (4 hunks)
  • src/commands/index.ts (7 hunks)
  • src/config/env.ts (4 hunks)
  • src/events/message.ts (2 hunks)
  • src/index.ts (3 hunks)
  • src/sdk/bots-brain/BotsStore.ts (2 hunks)
  • src/sdk/types.ts (2 hunks)
  • src/services/unthread.ts (2 hunks)
  • src/utils/botPermissions.ts (1 hunks)
  • src/utils/permissions.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
README.md (1)
Learnt from: warengonzaga
PR: wgtechlabs/unthread-telegram-bot#24
File: docker-compose.yaml:29-29
Timestamp: 2025-06-22T10:12:09.684Z
Learning: The Unthread Telegram Bot project is currently in beta development phase (v1.0.0-beta.2) and does not yet have official versioned Docker builds available, making the use of :latest tags acceptable for development purposes in docker-compose.yaml.
.env.example (1)
Learnt from: warengonzaga
PR: wgtechlabs/unthread-telegram-bot#24
File: docker-compose.yaml:29-29
Timestamp: 2025-06-22T10:12:09.684Z
Learning: The Unthread Telegram Bot project is currently in beta development phase (v1.0.0-beta.2) and does not yet have official versioned Docker builds available, making the use of :latest tags acceptable for development purposes in docker-compose.yaml.
🧬 Code Graph Analysis (4)
src/events/message.ts (1)
src/commands/index.ts (1)
  • processSetupTextInput (1516-1588)
src/index.ts (1)
src/commands/index.ts (1)
  • setupCommand (2092-2092)
src/utils/botPermissions.ts (1)
src/types/index.ts (1)
  • BotContext (27-29)
src/commands/index.ts (7)
src/types/index.ts (1)
  • BotContext (27-29)
src/bot.ts (2)
  • safeReply (65-119)
  • safeEditMessageText (134-199)
src/config/env.ts (1)
  • isAdminUser (323-326)
src/sdk/bots-brain/BotsStore.ts (1)
  • BotsStore (48-1006)
src/utils/botPermissions.ts (4)
  • handleRetryBotAdminCheck (261-327)
  • sendBotAdminHelpMessage (135-205)
  • isBotAdmin (17-46)
  • checkAndPromptBotAdmin (53-62)
src/utils/permissions.ts (2)
  • logPermissionEvent (176-193)
  • validateAdminAccess (44-91)
src/services/unthread.ts (5)
  • generateCustomerName (665-675)
  • createCustomerWithName (788-831)
  • handleUnthreadApiError (841-871)
  • validateCustomerExists (688-753)
  • getCustomerDetails (762-779)
πŸͺ› Biome (1.9.4)
src/services/unthread.ts

[error] 531-531: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/commands/index.ts

[error] 1057-1058: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

πŸ”‡ Additional comments (34)
.gitignore (1)

84-85: Excellent addition to the exclusion protocols, sir.

The context/ directory exclusion is precisely what we need for the new setup wizard's temporary state management. This follows standard protocol for preventing runtime artifacts from infiltrating our version control systems.

src/index.ts (3)

44-44: Import protocols successfully updated, sir.

The setupCommand integration follows our established architectural patterns flawlessly. All systems ready for deployment.


165-165: Command registration protocols engaged, sir.

The setup command integration is seamlessly executed with proper middleware and error handling. The architecture maintains its elegant consistency.


383-384: User interface enhancement deployed successfully, sir.

The command description clearly communicates admin-only access requirements. The Telegram UI will now properly reflect the new setup capabilities to users.

.env.railway (2)

12-12: Administrative access protocols configured, sir.

The ADMIN_USERS environment variable is properly documented with clear instructions for obtaining Telegram user IDs. The comma-separated format will enable multiple administrator support as intended.


13-13: Redis dependency clarification enhanced, sir.

The updated comment accurately reflects that WEBHOOK_REDIS_URL is essential for agent response delivery functionality. This will prevent deployment confusion regarding Redis requirements.

src/events/message.ts (2)

33-33: Import enhancement successfully integrated, sir.

The processSetupTextInput function import is properly positioned and will enable seamless setup wizard integration within our message processing pipeline.


88-95: Message routing intelligence upgraded, sir.

The early interception of setup wizard inputs is architecturally sound, ensuring setup processes take proper precedence over standard support flows. The logging mechanisms will provide excellent operational visibility.

README.md (4)

72-76: Documentation protocols enhanced with precision, sir.

The new Telegram user ID requirement is clearly articulated with proper context and urgency indicators. Users will have no difficulty understanding this critical prerequisite for administrative access.


100-102: Deployment protocols updated with administrative clarity, sir.

The enhanced configuration instructions clearly demonstrate both single and multiple administrator setups. The comma-separated format example will prevent user configuration errors.


128-129: Installation documentation synchronized perfectly, sir.

The manual installation instructions maintain excellent consistency with the Docker deployment procedures, ensuring users receive coherent guidance regardless of their chosen deployment method.


164-166: Infrastructure requirements clarified with exceptional detail, sir.

The Redis dependency documentation now accurately reflects the critical nature of these services for bot operations. Users will understand both the necessity and purpose of each Redis instance.

.env.example (2)

8-34: Excellent documentation enhancements, sir.

The detailed instructions for obtaining credentials and the prominent warnings about placeholder values will significantly reduce configuration errors. The ADMIN_USERS implementation provides a robust security layer.


44-48: Crystal clear Redis configuration requirements, sir.

The distinction between bot state management and agent response delivery Redis instances is well-documented, preventing potential configuration oversights.

src/utils/botPermissions.ts (1)

214-255: Exemplary callback query handling implementation, sir.

The timeout mechanism and comprehensive error handling ensure reliable bot interactions even under adverse network conditions. The detailed logging will prove invaluable for diagnostics.

src/utils/permissions.ts (2)

44-91: Impeccable security implementation, sir.

The admin validation system provides robust access control with informative user feedback. The audit logging ensures complete traceability of permission events.


119-131: Elegant command protection mechanism, sir.

The decorator pattern provides a clean, reusable approach to enforcing admin access across multiple commands.

src/sdk/types.ts (2)

119-143: Well-architected data structures, sir.

The GroupConfig and SetupState interfaces comprehensively model the group configuration domain with appropriate metadata support for future extensibility.


226-248: Comprehensive storage interface extensions, sir.

The addition of batch operations demonstrates foresight for scaling scenarios. The consistent API design maintains code predictability.

src/config/env.ts (2)

71-115: Outstanding environment validation enhancements, sir.

The detailed error messages and setup instructions will significantly reduce deployment friction. The placeholder detection prevents accidental production deployments with test credentials.


263-315: Exceptional admin user management implementation, sir.

The comprehensive validation, clear error messaging, and security-conscious logging demonstrate professional-grade code quality.

src/services/unthread.ts (6)

528-544: Excellent implementation of the group configuration check, sir!

The logic properly prioritizes configured groups over legacy storage, maintaining backward compatibility while enforcing the new setup workflow. The logging provides excellent observability.


561-572: Splendid error handling implementation, sir!

The prevention of automatic customer creation for unconfigured groups is a wise security measure. The error message provides clear, actionable guidance for administrators.


655-675: Well-crafted customer name generation, sir!

The function elegantly reuses existing logic while adding the [Telegram] prefix for channel distinction. The null handling ensures robustness.


681-753: Exemplary API validation implementation, sir!

The function provides comprehensive error handling with clear distinction between different failure scenarios. The structured return type enables elegant error handling by callers.


781-831: Robust customer creation with intelligent caching, sir!

The implementation properly validates input, prevents duplicates through caching, and maintains consistency with error handling patterns.


833-871: Brilliant error message craftsmanship, sir!

The function transforms technical errors into user-friendly, actionable messages with excellent coverage of common API failure scenarios. The markdown formatting with emojis enhances readability.

src/sdk/bots-brain/BotsStore.ts (4)

599-630: Impeccable storage implementation with proper versioning, sir!

The method correctly serializes configuration data, adds useful metadata for tracking changes, and provides comprehensive logging for debugging.


632-662: Robust retrieval with intelligent type handling, sir!

The method gracefully handles both serialized and object responses, ensuring compatibility across storage layers.


727-758: Excellent implementation with temporal awareness, sir!

The 1-hour TTL prevents abandoned setup sessions from cluttering storage, while providing ample time for administrators to complete the configuration process.


664-701: Commendable security implementation, sir!

The protection against chatId override in both updateGroupConfig and updateSetupState methods prevents potential security vulnerabilities. This defensive programming ensures data integrity.

Also applies to: 792-830

src/commands/index.ts (3)

38-42: Sir, the new imports are properly structured and aligned with the setup wizard requirements.

The addition of Unthread API functions, permission utilities, and bot permission checks provides the necessary foundation for the group configuration feature.


987-1142: Sir, the setup command implementation is comprehensive and well-structured.

The phased approach with proper admin validation, bot permission checks, and session management demonstrates excellent security practices. The user experience is enhanced with clear messaging and progress indicators.


1057-1058: Sir, the static analysis has correctly identified an opportunity for optional chaining.

This would make the code more concise and maintainable.

-                `**Customer:** ${existingConfig.customerName || 'Unknown'}\n` +
-                `**Customer ID:** ${existingConfig.customerId || 'Unknown'}\n` +
+                `**Customer:** ${existingConfig.customerName ?? 'Unknown'}\n` +
+                `**Customer ID:** ${existingConfig.customerId ?? 'Unknown'}\n` +

Likely an incorrect or invalid review comment.

@warengonzaga warengonzaga linked an issue Jul 8, 2025 that may be closed by this pull request
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (3)
src/sdk/bots-brain/BotsStore.ts (1)

649-653: Sir, we're encountering a type safety anomaly in the storage protocol.

The lastUpdatedAt and version fields are being added to the stored configuration but aren't defined in the GroupConfig interface. This creates a divergence between the runtime data structure and the type system.

Consider one of these solutions:

// Solution 1: Extend the interface
interface GroupConfig {
  // ... existing fields
+  lastUpdatedAt?: string;
+  version?: string;
}

Or handle metadata separately:

-const configData = {
-  ...config,
-  lastUpdatedAt: new Date().toISOString(),
-  version: '1.0'
-};
+const configData = config;
+const metadata = {
+  lastUpdatedAt: new Date().toISOString(),
+  version: '1.0'
+};
+// Store metadata separately or create a wrapper type
src/commands/index.ts (2)

2046-2059: Sir, I've detected a critical logic error in the customer validation flow.

The code incorrectly treats the result of validateCustomerExists as having an exists property, but based on the function call pattern, this appears to be inconsistent with the implementation shown.

This appears to be the same issue flagged in the past review comments about customer validation logic.


2181-2187: Sir, there's a type safety concern in the admin verification.

The isAdminUser function call passes a potentially undefined value with fallback to 0, which could lead to false positives in admin checking.

This matches the exact issue highlighted in the past review comments about admin user verification.

🧹 Nitpick comments (1)
src/commands/index.ts (1)

748-781: Sir, I notice a potential optimization opportunity in the email flow.

The logic for handling existing emails appears twice with similar implementations. Consider extracting this pattern into a helper function to reduce code duplication.

+// Helper function for handling existing email flow
+const handleExistingEmailFlow = async (ctx: BotContext, userState: any, existingEmail: string) => {
+    userState.ticket.email = existingEmail;
+    await safeReply(ctx, `πŸ“§ **Using your stored email:** ${existingEmail}\n\nCreating your support ticket... Please wait.`);
+    await handleEmailField(ctx, userState, existingEmail);
+};

// Then use in both locations:
-                        userState.ticket.email = existingUser.unthreadEmail!;
-                        await safeReply(ctx, `πŸ“§ **Using your stored email:** ${existingUser.unthreadEmail}\n\nCreating your support ticket... Please wait.`);
-                        await handleEmailField(ctx, userState, existingUser.unthreadEmail!);
+                        await handleExistingEmailFlow(ctx, userState, existingUser.unthreadEmail!);
πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between db00696 and 6fa0c4d.

πŸ“’ Files selected for processing (5)
  • README.md (7 hunks)
  • src/commands/index.ts (14 hunks)
  • src/sdk/bots-brain/BotsStore.ts (4 hunks)
  • src/sdk/types.ts (2 hunks)
  • src/types/index.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/sdk/types.ts
🧰 Additional context used
🧠 Learnings (1)
README.md (1)
Learnt from: warengonzaga
PR: wgtechlabs/unthread-telegram-bot#24
File: docker-compose.yaml:29-29
Timestamp: 2025-06-22T10:12:09.684Z
Learning: The Unthread Telegram Bot project is currently in beta development phase (v1.0.0-beta.2) and does not yet have official versioned Docker builds available, making the use of :latest tags acceptable for development purposes in docker-compose.yaml.
πŸͺ› LanguageTool
README.md

[grammar] ~75-~75: There might be a mistake here.
Context: ...erinfobot](https://t.me/userinfobot) on Telegram - Copy your numeric user ID (e.g., `...

(QB_NEW_EN_OTHER)


[grammar] ~76-~76: There might be a mistake here.
Context: ...m - Copy your numeric user ID (e.g., 123456789) - IMPORTANT: This is required fo...

(QB_NEW_EN_OTHER)


[grammar] ~77-~77: Combining words like β€œevery day” changes the meaning.
Context: ...*: This is required for admin access to setup groups 3. Setup Unthread - Log ...

(QB_NEW_EN_OTHER_ERROR_IDS_000001)


[grammar] ~77-~77: There might be a problem here.
Context: ...equired for admin access to setup groups 3. Setup Unthread - Log into your Unthread dashboard...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~80-~80: There might be a mistake here.
Context: ... Unthread** - Log into your Unthread dashboard - Navigate to Settings β†’ API Keys ...

(QB_NEW_EN_OTHER)


[grammar] ~81-~81: There might be a mistake here.
Context: ...shboard - Navigate to Settings β†’ API Keys - Generate a new API key - Find y...

(QB_NEW_EN_OTHER)


[grammar] ~82-~82: There might be a mistake here.
Context: ...ings β†’ API Keys - Generate a new API key - Find your channel ID in the dashbo...

(QB_NEW_EN_OTHER)


[grammar] ~83-~83: Place a period at the end of declarative sentences.
Context: ...ind your channel ID in the dashboard URL 4. Deploy Instantly **Option A: Railw...

(QB_NEW_EN_OTHER_ERROR_IDS_000178)


[grammar] ~85-~85: Use proper spacing conventions.
Context: ...the dashboard URL 4. Deploy Instantly Option A: Railway (One-Click Deploy) ...

(QB_NEW_EN_OTHER_ERROR_IDS_000007)


[grammar] ~192-~192: Use proper spacing conventions.
Context: ... - /version - Show current bot version ### Creating Support Tickets 1. **Use `/s...

(QB_NEW_EN_OTHER_ERROR_IDS_000007)


[grammar] ~194-~194: Use proper spacing conventions.
Context: ... version ### Creating Support Tickets 1. Use /support in your group chat 2. *...

(QB_NEW_EN_OTHER_ERROR_IDS_000007)


[grammar] ~196-~196: There might be a mistake here.
Context: ...ts** 1. Use /support in your group chat 2. Describe your issue when the b...

(QB_NEW_EN_OTHER)


[grammar] ~197-~197: There might be a mistake here.
Context: ...2. Describe your issue when the bot asks 3. **Provide email (first-time users on...

(QB_NEW_EN_OTHER)


[typographical] ~198-~198: To join two clauses or set off examples, consider using an em dash.
Context: ...ks 3. Provide email (first-time users only) - returning users automatically use their stored em...

(QB_NEW_EN_DASH_RULE_EM)


[grammar] ~198-~198: There might be a mistake here.
Context: ...ng users automatically use their stored email 4. Get your ticket number and confi...

(QB_NEW_EN_OTHER)


[grammar] ~214-~214: Use proper spacing conventions.
Context: ...il anytime using the /profile command. ### Managing Your Profile Use the `/profi...

(QB_NEW_EN_OTHER_ERROR_IDS_000007)


[grammar] ~216-~216: Use proper spacing conventions.
Context: ...ecommand. ### **Managing Your Profile** Use the/profile` command to view and u...

(QB_NEW_EN_OTHER_ERROR_IDS_000007)


[grammar] ~218-~218: Use proper spacing conventions.
Context: ... view and update your email preferences: text User: /profile Bot: πŸ‘€ Your Profile Email: john@example.com What would you like to do? [πŸ“§ Update Email] [ℹ️ About] User: [clicks Update Email] Bot: Please enter your new email address: User: john.doe@company.com Bot: βœ… Email Updated Successfully! Your email has been updated to: john.doe@company.com This email will be used for all future support tickets. Profile Features: - **View current em...

(QB_NEW_EN_OTHER_ERROR_IDS_000007)


[grammar] ~237-~237: Use proper spacing conventions.
Context: ...upport tickets. ``` Profile Features: - View current email - See the email ass...

(QB_NEW_EN_OTHER_ERROR_IDS_000007)


[typographical] ~239-~239: To join two clauses or set off examples, consider using an em dash.
Context: ...Profile Features: - View current email - See the email associated with your profile ...

(QB_NEW_EN_DASH_RULE_EM)


[grammar] ~239-~239: There might be a mistake here.
Context: ...** - See the email associated with your profile - Update email - Change your email ...

(QB_NEW_EN_OTHER)


[typographical] ~240-~240: To join two clauses or set off examples, consider using an em dash.
Context: ...associated with your profile - Update email - Change your email for future support tickets -...

(QB_NEW_EN_DASH_RULE_EM)


[grammar] ~240-~240: There might be a mistake here.
Context: ... - Change your email for future support tickets - Auto-generated email detection - ...

(QB_NEW_EN_OTHER)


[typographical] ~241-~241: To join two clauses or set off examples, consider using an em dash.
Context: ...upport tickets - Auto-generated email detection - Get notified if you're using an auto-genera...

(QB_NEW_EN_DASH_RULE_EM)


[grammar] ~241-~241: There might be a mistake here.
Context: ...ified if you're using an auto-generated email - Seamless integration - Email upda...

(QB_NEW_EN_OTHER)


[typographical] ~242-~242: To join two clauses or set off examples, consider using an em dash.
Context: ...ng an auto-generated email - Seamless integration - Email updates apply to all future support tic...

(QB_NEW_EN_DASH_RULE_EM)


[grammar] ~242-~242: Place a period at the end of declarative sentences.
Context: ...ates apply to all future support tickets ### For Agents (Unthread Dashboard) - **N...

(QB_NEW_EN_OTHER_ERROR_IDS_000178)

πŸͺ› Biome (1.9.4)
src/commands/index.ts

[error] 286-288: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 753-753: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 1309-1310: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

πŸ”‡ Additional comments (24)
src/types/index.ts (2)

38-40: Sir, the enum expansions are executed flawlessly.

The new COMPLETE and PROFILE_EMAIL_UPDATE values integrate seamlessly with the existing enumeration structure.


52-61: The ProfileUpdateState interface demonstrates excellent type architecture, sir.

The literal type constraint on the field property and the clear separation of required versus optional properties provide robust type safety for the profile update workflow.

README.md (4)

74-78: Exemplary documentation of the admin authentication protocol, sir.

The instructions for obtaining Telegram user IDs and configuring multiple administrators are crystal clear. The emphasis on this being a mandatory requirement ensures users won't overlook this critical security feature.

Also applies to: 102-105, 130-132


166-169: The Redis configuration documentation is precisely calibrated, sir.

Moving Redis to required status with clear purpose annotations for each instance provides excellent operational clarity.


191-191: The profile management documentation achieves operational excellence, sir.

The interactive examples and feature descriptions provide users with a comprehensive understanding of the email preference system. The conversation flow examples are particularly illuminating.

Also applies to: 214-243


56-57: Sir, the one-time email setup documentation elegantly conveys the enhanced user experience.

The automatic email retention for returning users significantly streamlines the support ticket creation process.

Also applies to: 198-198, 214-214

src/sdk/bots-brain/BotsStore.ts (1)

402-440: The updateUser implementation exhibits impeccable defensive programming, sir.

The null checking, data merging, and comprehensive logging ensure reliable profile updates across the system.

src/commands/index.ts (17)

38-42: Sir, excellent enhancement to the import statements and service integrations.

The addition of comprehensive Unthread service functions and permission utilities demonstrates proper modularity. The import structure is well-organized and follows best practices for TypeScript module imports.


97-154: Sir, I've observed a sophisticated approach to role-based help text generation.

The separation of regular user and admin help functions provides excellent user experience tailoring. The implementation correctly differentiates functionality based on user permissions, ensuring users only see commands they can execute.


162-190: Sir, the help command implementation shows proper permission handling.

The command correctly validates user identity and applies role-based filtering. The logging provides excellent audit trails for security monitoring.


271-366: Sir, the profile command implementation is exceptionally well-crafted.

The comprehensive profile management system handles both first-time and existing users elegantly. The distinction between auto-generated and real email addresses provides excellent user guidance. The inline keyboard integration enhances user experience significantly.


393-451: Sir, excellent implementation of group configuration validation.

The support command now properly checks group configuration before allowing ticket creation. The differentiated messaging for admins versus regular users provides appropriate guidance based on user capabilities.


584-608: Sir, the bot permission callback handling demonstrates excellent user flow management.

The comprehensive handling of setup-related callbacks with proper state management ensures users can navigate the wizard effectively. The callback answer implementations prevent UI loading states.


643-684: Sir, observe the intelligent email handling optimization.

The enhancement to check for existing user emails before prompting eliminates unnecessary steps in the ticket creation process. This demonstrates excellent user experience optimization while maintaining data integrity.


916-935: Sir, the email storage enhancement provides excellent user experience continuity.

The automatic storage of user emails for future ticket creation significantly improves the user experience. The error handling ensures ticket creation doesn't fail if email storage encounters issues.


1004-1038: Sir, excellent error handling for group configuration scenarios.

The specific handling of GROUP_NOT_CONFIGURED errors provides users with clear guidance on resolution steps. This demonstrates excellent error messaging design.


1087-1161: Sir, the profile email update functionality is comprehensively implemented.

The function handles validation, duplicate checking, and provides clear user feedback throughout the process. The email format validation and success messaging create an excellent user experience.


1245-1393: Sir, the setup command implementation demonstrates enterprise-grade configuration management.

The multi-phase setup process with proper admin validation, bot permission checks, and session management provides a robust configuration system. The progress indicators enhance user experience significantly.


1478-1593: Sir, the suggested name handler showcases excellent API integration.

The real customer creation in Unthread with proper error handling and fallback mechanisms demonstrates professional-grade implementation. The comprehensive logging provides excellent debugging capabilities.


1847-1989: Sir, I observe sophisticated input validation with user-friendly feedback.

The customer name validation provides detailed feedback with actionable suggestions. The warning system for unusual names while still allowing confirmation demonstrates excellent UX design.


2208-2255: Sir, the enhanced validation functions demonstrate excellent input sanitization.

The comprehensive customer name validation with detailed error messages and suggestions provides exceptional user guidance. The character validation and length checking ensure data integrity.


2261-2316: Sir, the customer ID validation showcases professional-grade input handling.

The format validation against common ID patterns with detailed feedback demonstrates excellent defensive programming. The validation covers edge cases while providing helpful guidance.


2322-2336: Sir, the progress indicator implementation enhances user experience significantly.

The visual progress tracking with step names provides excellent user orientation during the setup process. The implementation is both functional and aesthetically pleasing.


2339-2493: Sir, the profile callback handlers demonstrate excellent state management.

The comprehensive handling of profile interactions with proper error handling and user feedback provides a seamless user experience. The navigation flow between different profile states is well-implemented.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (3)
src/config/env.ts (1)

192-201: Sir, I observe the Telegram token validation has been refined per previous recommendations.

The pattern now correctly accommodates variable-length tokens with the {35,} quantifier, though the error message description could be more precise.

The implementation addresses the previous concern about fixed token lengths while maintaining proper validation.

src/sdk/bots-brain/BotsStore.ts (2)

203-215: Sir, I observe the consistent JSON serialization implementation.

The storage operations now uniformly serialize data before persistence, addressing the previous concern about inconsistent serialization protocols across the interface.


740-757: Sir, this validation implementation exemplifies superior data integrity practices.

The getGroupConfig method now employs zod schema validation before returning data, ensuring structural correctness and preventing runtime errors from malformed storage data.

🧹 Nitpick comments (6)
src/utils/botPermissions.ts (1)

280-346: Sir, consider consolidating the error handling patterns.

The retry logic demonstrates thorough error handling, though the nested safeAnswerCallbackQuery calls could benefit from a more streamlined approach.

Consider extracting the common error handling pattern:

+const handleCallbackError = async (ctx: BotContext, errorMessage: string) => {
+  const answered = await safeAnswerCallbackQuery(ctx, errorMessage, 2000);
+  if (!answered) {
+    LogEngine.error('[BotPermissions] Failed to answer callback query in error handler');
+    try {
+      await ctx.reply('❌ Error occurred. Please try again or contact support.');
+    } catch (replyError) {
+      LogEngine.error('[BotPermissions] Failed to send fallback reply:', replyError);
+    }
+  }
+};
src/services/unthread.ts (1)

531-531: Sir, the static analysis tool suggests a minor refinement opportunity.

The condition check could be more concise using optional chaining.

Apply this refinement:

-if (groupConfig && groupConfig.isConfigured && groupConfig.customerId) {
+if (groupConfig?.isConfigured && groupConfig.customerId) {
src/commands/index.ts (4)

748-781: Sir, the same email optimization pattern is consistently applied.

The duplicate logic for checking existing emails maintains consistency throughout the codebase, though it might benefit from extraction into a utility function.


286-288: Sir, I recommend applying the optional chain optimization.

The static analysis correctly identifies an opportunity for cleaner code.

-        const hasEmail = existingUser && existingUser.unthreadEmail && existingUser.unthreadEmail.trim() !== '';
+        const hasEmail = existingUser?.unthreadEmail && existingUser.unthreadEmail.trim() !== '';

753-753: Sir, another optional chain improvement is available.

Consistent with the previous optimization opportunity.

-        const hasExistingEmail = existingUser && existingUser.unthreadEmail && existingUser.unthreadEmail.trim() !== '';
+        const hasExistingEmail = existingUser?.unthreadEmail && existingUser.unthreadEmail.trim() !== '';

1309-1310: Sir, the third optional chain optimization completes the pattern.

This maintains consistency with the other optional chain improvements.

-                `**Setup by:** User ID ${existingConfig.setupBy}\n` +
-                `**Setup date:** ${existingConfig.setupAt || 'Unknown'}\n\n` +
+                `**Setup by:** User ID ${existingConfig?.setupBy}\n` +
+                `**Setup date:** ${existingConfig?.setupAt || 'Unknown'}\n\n` +
πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 6fa0c4d and 6e153c2.

β›” Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
πŸ“’ Files selected for processing (8)
  • package.json (3 hunks)
  • src/commands/index.ts (14 hunks)
  • src/config/env.ts (4 hunks)
  • src/database/schema.sql (1 hunks)
  • src/sdk/bots-brain/BotsStore.ts (17 hunks)
  • src/sdk/types.ts (2 hunks)
  • src/services/unthread.ts (2 hunks)
  • src/utils/botPermissions.ts (1 hunks)
βœ… Files skipped from review due to trivial changes (2)
  • src/database/schema.sql
  • package.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/sdk/types.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/utils/botPermissions.ts (1)
src/types/index.ts (1)
  • BotContext (27-29)
src/services/unthread.ts (2)
src/sdk/bots-brain/BotsStore.ts (1)
  • BotsStore (82-1121)
src/sdk/bots-brain/index.ts (1)
  • BotsStore (29-29)
πŸͺ› Biome (1.9.4)
src/services/unthread.ts

[error] 531-531: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/commands/index.ts

[error] 286-288: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 753-753: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 1309-1310: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

πŸ”‡ Additional comments (33)
src/utils/botPermissions.ts (3)

8-10: Sir, excellent adherence to the previous type safety recommendations.

I observe the import now correctly utilizes the project's custom BotContext type rather than the generic Telegraf context, precisely as suggested in the prior review cycle.


17-29: Sir, this type guard implementation demonstrates superior engineering practices.

The chatHasTitle function elegantly resolves the type safety concerns from previous iterations, eliminating the need for unsafe as any casting while maintaining robust runtime validation.


233-274: Sir, this timeout implementation showcases exceptional robustness.

The safeAnswerCallbackQuery function implements a sophisticated timeout mechanism using Promise.race, preventing hanging operations while providing comprehensive error context for debugging scenarios.

src/config/env.ts (2)

263-315: Sir, this admin user validation demonstrates commendable security practices.

The function properly validates user IDs, detects placeholder values, and provides clear instructions for obtaining legitimate Telegram user IDs. The security consideration of not logging actual user IDs is particularly prudent.


121-149: Sir, this placeholder detection system is remarkably thorough.

The validation catches common deployment mistakes that could lead to service failures in production environments. The Railway-specific guidance shows excellent platform awareness.

src/services/unthread.ts (3)

528-586: Sir, this architectural enhancement significantly improves the system's integrity.

The function now properly enforces group configuration before customer creation, preventing unauthorized ticket creation while maintaining backward compatibility with legacy data. The error messaging clearly guides users to the setup process.


691-756: Sir, this validation function demonstrates excellent API integration practices.

The validateCustomerExists function provides comprehensive error handling with specific status code responses, proper logging, and graceful degradation for network issues.


841-871: Sir, this error handling utility showcases exceptional user experience consideration.

The handleUnthreadApiError function translates technical errors into user-friendly messages, covering common scenarios like network issues, authentication failures, and rate limiting.

src/sdk/bots-brain/BotsStore.ts (4)

34-81: Sir, these zod schemas demonstrate exemplary runtime validation practices.

The schemas comprehensively define data structures while accommodating additional fields that might be added during storage operations, providing robust type safety at runtime.


448-483: Sir, this update mechanism demonstrates excellent data management practices.

The updateUser function properly merges existing data with updates while maintaining data integrity through proper error handling and logging.


843-844: Sir, this TTL implementation shows excellent state management foresight.

Setting a one-hour expiration for setup states prevents stale configuration data from interfering with future setup processes.


1010-1120: Sir, these batch operations demonstrate scalable architecture design.

The batch methods enable efficient bulk operations while maintaining individual error handling, supporting potential future requirements for managing multiple groups simultaneously.

src/commands/index.ts (21)

16-16: Sir, the command documentation has been updated appropriately.

The addition of the /setup command to the module documentation aligns with the new functionality being introduced.


38-42: Sir, I've identified a more secure approach for the admin verification import.

The import structure correctly brings in the necessary utilities for admin verification and bot permissions, which is essential for the new setup functionality.


43-52: Sir, the type imports and field enums have been expanded logically.

The addition of ProfileUpdateState and PROFILE_EMAIL_UPDATE field enum properly supports the new profile management functionality.


95-154: Sir, the help command has been intelligently redesigned with role-based access.

The separation of admin and regular user help text provides appropriate information disclosure while maintaining security. The implementation correctly checks user permissions before displaying sensitive administrative commands.


162-190: Sir, the help command implementation demonstrates proper security practices.

The user ID validation and admin role checking are well-implemented, with appropriate logging for security monitoring.


271-366: Sir, the profile command implementation is quite comprehensive.

The profile management system correctly handles user state retrieval, email validation, and provides appropriate user feedback with security considerations.


393-451: Sir, I've noticed a logical enhancement in the support command.

The group configuration check before allowing support ticket creation is a significant improvement. The distinction between admin and regular user messaging when groups are unconfigured is well-handled.


584-623: Sir, the callback handling has been significantly enhanced.

The systematic handling of various callback types (bot permissions, profile, setup wizard) demonstrates good separation of concerns and proper flow control.


643-684: Sir, the email handling logic shows intelligent optimization.

The implementation correctly checks for existing user emails before prompting, reducing friction in the support ticket creation process while maintaining data integrity.


916-935: Sir, the email storage functionality has been properly integrated.

The email persistence in the user profile after ticket creation is a logical enhancement that improves user experience for subsequent tickets.


1004-1038: Sir, the error handling for unconfigured groups is well-implemented.

The specific handling of the GROUP_NOT_CONFIGURED error provides clear user guidance and maintains security by not exposing internal error details.


1087-1161: Sir, the profile email update functionality appears robust.

The email validation, duplicate check, and proper error handling demonstrate thorough implementation of this user-facing feature.


1245-1393: Sir, the setup command implementation shows comprehensive security measures.

The multi-layered security checks (group chat only, admin verification, bot permissions) provide appropriate protection for this sensitive administrative function.


1402-1471: Sir, the setup callback handling demonstrates proper session management.

The session validation and user verification ensure that only authorized users can complete setup operations, maintaining security throughout the process.


1476-1591: Sir, the suggested name handling includes proper API integration.

The customer creation via the Unthread API with comprehensive error handling and logging provides a robust foundation for the setup process.


1766-1838: Sir, the setup text input processing shows excellent session security.

The enhanced session validation with timeout handling and user verification ensures that setup operations remain secure and properly managed.


1843-1985: Sir, the customer name validation is thorough and user-friendly.

The comprehensive validation with detailed feedback and suggestions provides excellent user experience while maintaining data integrity.


1990-2162: Sir, the customer ID validation mirrors the name validation quality.

The consistent validation approach with proper error handling and user feedback maintains the high standard established in the name validation.


2171-2224: Sir, the session validation includes proper security measures.

The timeout handling and admin re-verification provide appropriate security controls for the setup process.


2230-2358: Sir, the validation functions demonstrate excellent input handling.

The comprehensive validation with detailed error messages and suggestions provides a professional user experience while maintaining security.


2361-2516: Sir, the profile callback handlers are well-structured.

The profile management callbacks properly handle state transitions and provide appropriate user feedback with proper error handling.

@warengonzaga warengonzaga marked this pull request as draft July 9, 2025 02:29
@warengonzaga warengonzaga marked this pull request as ready for review July 24, 2025 07:50
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

πŸ”­ Outside diff range comments (1)
src/events/message.ts (1)

1325-1357: Sir, the non-null assertions present a potential runtime hazard.

Multiple uses of ctx.chat!.id without prior validation could cause runtime errors.

Add validation at the function start:

 async function updateStatusMessage(ctx: BotContext, statusMsg: StatusMessage, isSuccess: boolean, hasAttachments?: boolean): Promise<void> {
+    if (!ctx.chat) {
+        LogEngine.error('Cannot update status message - chat context missing');
+        return;
+    }
+    
     if (isSuccess) {
         // Update status message to success
         const successMessage = hasAttachments ? 'βœ… Files uploaded and added!' : 'βœ… Added!';
         await safeEditMessageText(
             ctx,
-            ctx.chat!.id,
+            ctx.chat.id,
             statusMsg.message_id,
             undefined,
             successMessage
         );

         // Delete status message after 3 seconds
         setTimeout(() => {
-            ctx.telegram.deleteMessage(ctx.chat!.id, statusMsg.message_id).catch(() => {});
+            if (ctx.chat) {
+                ctx.telegram.deleteMessage(ctx.chat.id, statusMsg.message_id).catch(() => {});
+            }
         }, 3000);
♻️ Duplicate comments (7)
src/commands/utils/errorHandler.ts (1)

87-113: Excellent architectural improvement, sir.

The implementation now utilizes explicit Sets for error code classification, eliminating the fragility concerns from the previous array slicing approach. This order-independent solution demonstrates superior maintainability.

Also applies to: 253-270

src/commands/processors/ConversationProcessors.ts (1)

984-998: Sir, the hardcoded template variables require centralization.

As previously identified, the valid variables list should utilize the centralized TEMPLATE_VARIABLES constant for consistency.

+import { TEMPLATE_VARIABLES } from '../../config/globalTemplates.js';
+
 // Check for basic variable syntax
 const variableMatches = templateContent.match(/\{\{[^}]+\}\}/g);
 if (variableMatches) {
     const invalidVars: string[] = [];
-    const validVars = ['ticketId', 'summary', 'customerName', 'status', 'response', 'createdAt', 'updatedAt'];
+    const validVars = TEMPLATE_VARIABLES;
     
     for (const match of variableMatches) {
         const varName = match.replace(/[{}]/g, '').trim();
         if (!validVars.includes(varName)) {
             invalidVars.push(varName);
         }
     }
     
     if (invalidVars.length > 0) {
         await ctx.reply(
-            `❌ **Invalid Variables**\n\nThe following variables are not recognized:\nβ€’ ${invalidVars.join('\nβ€’ ')}\n\n**Valid variables:**\nβ€’ ticketId, summary, customerName, status\nβ€’ response, createdAt, updatedAt\n\nPlease fix your template:`,
+            `❌ **Invalid Variables**\n\nThe following variables are not recognized:\nβ€’ ${invalidVars.join('\nβ€’ ')}\n\n**Valid variables:**\nβ€’ ${TEMPLATE_VARIABLES.join(', ')}\n\nPlease fix your template:`,
src/utils/adminManager.ts (3)

410-421: Sir, enhanced logging would improve diagnostic capabilities.

When the session is not found, the function returns false without clear distinction from other failure modes.

     if (!session) {
+      LogEngine.warn('DM setup session not found when adding message ID', {
+        sessionId,
+        messageId,
+        operation: 'addDmSessionMessageId',
+        reason: 'session_not_found'
+      });
       return false;
     }

601-617: Sir, the notification template references an unpopulated field.

The template attempts to display context.adminName, but this property is never set in the NotificationContext object.

Either populate the adminName:

     const context: NotificationContext = {
       groupId: groupChatId,
       groupTitle: groupTitle || `Group ${groupChatId}`,
+      adminName: await getAdminUsername(initiatingAdminId), // Implement this helper
       changeType,
       changeDetails,
       timestamp: new Date().toISOString()
     };

Or remove the unused reference from the template.


779-791: Sir, there's a formatting protocol mismatch in the notification.

The message uses Markdown syntax (**) but specifies HTML parse mode.

-    const messageText = `⚠️ **Admin Notification: Delivery Issues**
+    const messageText = `⚠️ <b>Admin Notification: Delivery Issues</b>

-<b>Group:</b> Group ${groupChatId}
-<b>Issue:</b> Failed to deliver ${context.failedCount} admin notifications
+<b>Group:</b> Group ${groupChatId}
+<b>Issue:</b> Failed to deliver ${context.failedCount} admin notifications
src/events/message.ts (2)

124-127: Sir, I detect redundant validation protocols.

The file ID validation is performed twice - the second check is unreachable.

Remove the redundant validation:

     const fileIds = extractFileAttachments(ctx);
     if (fileIds.length === 0 || !fileIds[0]) {
         return false; // No attachments to process
     }
     
     LogEngine.info('πŸ“Ž Media group message detected', {
         mediaGroupId,
         fileCount: fileIds.length,
         messageId: ctx.message.message_id,
         userId: ctx.from.id,
         chatId: ctx.chat.id,
         isReply: 'reply_to_message' in ctx.message && !!ctx.message.reply_to_message,
         replyToMessageId: 'reply_to_message' in ctx.message && ctx.message.reply_to_message ? ctx.message.reply_to_message.message_id : undefined
     });
     
     // Create media group item
     const replyToId = 'reply_to_message' in ctx.message && ctx.message.reply_to_message 
         ? ctx.message.reply_to_message.message_id 
         : undefined;
         
-    // Additional validation to ensure we have a valid file ID
-    if (fileIds.length === 0 || !fileIds[0]) {
-        LogEngine.error('❌ No valid file IDs found for media group item', {
-            mediaGroupId,
-            messageId: ctx.message.message_id,
-            fileIdsLength: fileIds.length
-        });
-        return false;
-    }
-    
     const item: MediaGroupItem = {

Also applies to: 144-152


445-454: Sir, accessing private methods via bracket notation compromises encapsulation integrity.

The code circumvents TypeScript's access control mechanisms.

Make handleSummaryInput public in the SupportConversationProcessor class:

             // Call handleSummaryInput with the media group caption as summary and pre-detected attachments
-            await supportProcessor['handleSummaryInput'](
+            await supportProcessor.handleSummaryInput(
                 collection.ctx, 
                 summaryText, 
                 userState, 
                 fileIds  // Pre-detected attachments from media group
             );

Update the method visibility in the processor class definition.

🧹 Nitpick comments (7)
src/commands/utils/commandExecutor.ts (1)

100-108: Sir, a minor type casting redundancy detected.

The type assertion on line 108 is unnecessary. When returnType: 'boolean' is specified, TypeScript can infer the return type correctly.

-    }) as (_ctx: BotContext) => Promise<boolean>;
+    });
eslint.config.js (1)

128-151: Sir, I notice several security rules disabled for attachment processing files.

While the TODO comments indicate these will be re-enabled in v1.1.0, we should ensure proper tracking of these security exceptions.

Would you like me to create GitHub issues to track the re-enablement of these security rules for the v1.1.0 milestone? This would ensure these temporary exceptions don't become permanent oversights.

src/commands/admin/AdminCommands.ts (1)

190-191: Sir, I recommend optimizing these dynamic imports to static ones.

The dynamic imports for local utility modules add unnecessary complexity without apparent benefit. Static imports would provide better type safety and cleaner code.

At the top of the file, add these imports:

+import { createDmSetupSession } from '../../utils/adminManager.js';
+import { generateCustomerName } from '../../services/unthread.js';

Then simplify the usage:

-const { createDmSetupSession } = await import('../../utils/adminManager.js');
 const sessionId = await createDmSetupSession(userId, chatId, chatTitle);
-const { generateCustomerName } = await import('../../services/unthread.js');
 const suggestedName = generateCustomerName(groupTitle).replace('[Telegram] ', '');

Also applies to: 339-340

src/utils/attachmentHandler.ts (4)

34-36: Sir, these comments about removed imports appear to be vestigial.

The comments reference "PERMANENTLY REMOVED" imports, yet no actual removed imports are shown. This creates unnecessary confusion in the codebase.

-// Import statements for buffer-based file processing
-// The following imports have been PERMANENTLY REMOVED:
-// Buffer-only implementation - no streaming dependencies required
+// Import statements for buffer-based file processing

1298-1408: Sir, the dual-mode processing exhibits intelligent design with minor optimization opportunities.

The method correctly identifies media groups for batch processing, improving efficiency. However, error handling consistency between single and batch modes could be enhanced.

Consider extracting common error result creation:

private createProcessingResult(
    success: boolean,
    processedFiles: number,
    totalFiles: number,
    errors: string[],
    startTime: number
): BufferProcessingResult {
    return {
        success,
        processedFiles,
        totalFiles,
        errors,
        processingTime: Date.now() - startTime
    };
}

715-719: Sir, the garbage collection invocation requires operational consideration.

The global.gc() call requires Node.js to be started with the --expose-gc flag, which should be documented.

                if (global.gc) {
+                   // Note: Requires Node.js to be started with --expose-gc flag
                    global.gc();
                }

1-1535: Sir, the attachment handler architecture exemplifies engineering excellence.

The buffer-based approach with comprehensive error handling, security validation, and memory optimization creates a robust foundation for file processing. The dual-mode processing for single vs. batch uploads demonstrates thoughtful design.

For future enhancements, consider implementing a circuit breaker pattern for the Telegram and Unthread API calls to gracefully handle service degradation scenarios.

πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 0adecc5 and d9e0d18.

πŸ“’ Files selected for processing (22)
  • MIGRATION.md (1 hunks)
  • README.md (11 hunks)
  • eslint.config.js (1 hunks)
  • src/commands/admin/AdminCommands.ts (1 hunks)
  • src/commands/base/CommandRegistry.ts (1 hunks)
  • src/commands/basic/SetEmailCommand.ts (1 hunks)
  • src/commands/basic/ViewEmailCommand.ts (1 hunks)
  • src/commands/index.ts (1 hunks)
  • src/commands/processors/ConversationProcessors.ts (1 hunks)
  • src/commands/utils/commandExecutor.ts (1 hunks)
  • src/commands/utils/errorHandler.ts (1 hunks)
  • src/config/globalTemplates.ts (1 hunks)
  • src/config/logging.ts (1 hunks)
  • src/database/connection.ts (7 hunks)
  • src/events/message.ts (14 hunks)
  • src/index.ts (8 hunks)
  • src/utils/adminManager.ts (1 hunks)
  • src/utils/attachmentHandler.ts (1 hunks)
  • src/utils/errorContextBuilder.ts (1 hunks)
  • src/utils/logConfig.example.ts (1 hunks)
  • src/utils/logConfig.ts (1 hunks)
  • src/utils/markdownEscape.ts (1 hunks)
βœ… Files skipped from review due to trivial changes (3)
  • src/config/logging.ts
  • src/utils/logConfig.example.ts
  • src/utils/markdownEscape.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/config/globalTemplates.ts
  • src/index.ts
  • src/database/connection.ts
🧰 Additional context used
🧠 Learnings (3)
πŸ““ Common learnings
Learnt from: warengonzaga
PR: wgtechlabs/unthread-telegram-bot#24
File: docker-compose.yaml:29-29
Timestamp: 2025-06-22T10:12:09.684Z
Learning: The Unthread Telegram Bot project is currently in beta development phase (v1.0.0-beta.2) and does not yet have official versioned Docker builds available, making the use of :latest tags acceptable for development purposes in docker-compose.yaml.
MIGRATION.md (1)

Learnt from: warengonzaga
PR: #24
File: docker-compose.yaml:29-29
Timestamp: 2025-06-22T10:12:09.684Z
Learning: The Unthread Telegram Bot project is currently in beta development phase (v1.0.0-beta.2) and does not yet have official versioned Docker builds available, making the use of :latest tags acceptable for development purposes in docker-compose.yaml.

README.md (1)

Learnt from: warengonzaga
PR: #24
File: docker-compose.yaml:29-29
Timestamp: 2025-06-22T10:12:09.684Z
Learning: The Unthread Telegram Bot project is currently in beta development phase (v1.0.0-beta.2) and does not yet have official versioned Docker builds available, making the use of :latest tags acceptable for development purposes in docker-compose.yaml.

🧬 Code Graph Analysis (4)
src/commands/admin/AdminCommands.ts (13)
src/commands/base/BaseCommand.ts (1)
  • CommandMetadata (12-21)
src/types/index.ts (1)
  • BotContext (27-29)
src/sdk/bots-brain/BotsStore.ts (1)
  • BotsStore (83-1837)
src/commands/utils/errorHandler.ts (2)
  • logError (477-504)
  • createUserErrorMessage (513-539)
src/sdk/types.ts (2)
  • AdminProfile (127-134)
  • GroupConfig (171-185)
src/config/env.ts (1)
  • getCompanyName (342-360)
src/utils/permissions.ts (2)
  • isBotAdmin (232-261)
  • checkAndPromptBotAdmin (268-277)
src/utils/adminManager.ts (1)
  • createDmSetupSession (274-318)
src/services/validationService.ts (1)
  • ValidationService (29-166)
src/services/unthread.ts (1)
  • generateCustomerName (852-862)
src/commands/processors/CallbackProcessors.ts (1)
  • SetupCallbackProcessor (848-2425)
src/utils/globalTemplateManager.ts (1)
  • GlobalTemplateManager (18-400)
src/config/globalTemplates.ts (1)
  • GlobalTemplate (8-14)
src/utils/errorContextBuilder.ts (1)
src/types/index.ts (1)
  • BotContext (27-29)
src/commands/processors/ConversationProcessors.ts (10)
src/commands/base/BaseCommand.ts (1)
  • IConversationProcessor (29-32)
src/types/index.ts (1)
  • BotContext (27-29)
src/utils/messageContentExtractor.ts (2)
  • hasTextContent (89-91)
  • getMessageText (23-39)
src/sdk/bots-brain/index.ts (1)
  • BotsStore (29-29)
src/commands/processors/CallbackProcessors.ts (5)
  • canHandle (50-52)
  • canHandle (853-859)
  • canHandle (2432-2441)
  • SupportCallbackProcessor (45-842)
  • SetupCallbackProcessor (848-2425)
src/events/message.ts (1)
  • extractFileAttachments (829-951)
src/utils/simpleValidators.ts (1)
  • SimpleInputValidator (23-76)
src/utils/markdownEscape.ts (3)
  • lightEscapeMarkdown (145-155)
  • truncateText (61-71)
  • escapeMarkdown (27-36)
src/utils/messageAnalyzer.ts (1)
  • generateStatusMessage (254-282)
src/utils/globalTemplateManager.ts (1)
  • GlobalTemplateManager (18-400)
src/utils/adminManager.ts (4)
src/config/env.ts (1)
  • isAdminUser (330-333)
src/sdk/bots-brain/index.ts (1)
  • BotsStore (29-29)
src/config/logging.ts (1)
  • LogEngine (21-21)
src/sdk/types.ts (3)
  • AdminProfile (127-134)
  • SetupSession (137-146)
  • DmSetupSession (149-160)
πŸͺ› LanguageTool
README.md

[style] ~465-~465: β€˜in conjunction with’ might be wordy. Consider a shorter alternative.
Context: ...ok Server Integration** This bot works in conjunction with the [unthread-webhook-server](https:/...

(EN_WORDINESS_PREMIUM_IN_CONJUNCTION_WITH)

πŸͺ› GitHub Actions: Validate
src/commands/processors/ConversationProcessors.ts

[warning] 102-102: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)


[warning] 207-207: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)


[warning] 232-232: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)


[warning] 728-728: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)


[warning] 838-838: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)


[warning] 940-940: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)


[warning] 1016-1016: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)


[warning] 1086-1086: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)


[warning] 1090-1090: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)


[warning] 1204-1204: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)

src/events/message.ts

[warning] 1331-1331: ESLint: Forbidden non-null assertion (@typescript-eslint/no-non-null-assertion)


[warning] 1339-1339: ESLint: Forbidden non-null assertion (@typescript-eslint/no-non-null-assertion)


[warning] 1346-1346: ESLint: Forbidden non-null assertion (@typescript-eslint/no-non-null-assertion)


[warning] 1354-1354: ESLint: Forbidden non-null assertion (@typescript-eslint/no-non-null-assertion)


[warning] 1415-1415: ESLint: Forbidden non-null assertion (@typescript-eslint/no-non-null-assertion)


[warning] 1497-1497: ESLint: Forbidden non-null assertion (@typescript-eslint/no-non-null-assertion)


[warning] 1505-1505: ESLint: Forbidden non-null assertion (@typescript-eslint/no-non-null-assertion)


[warning] 1534-1534: ESLint: Forbidden non-null assertion (@typescript-eslint/no-non-null-assertion)


[warning] 1542-1542: ESLint: Forbidden non-null assertion (@typescript-eslint/no-non-null-assertion)

src/utils/adminManager.ts

[warning] 373-373: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)


[warning] 537-537: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)


[warning] 585-585: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)


[warning] 678-678: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)


[warning] 705-705: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)


[warning] 729-729: ESLint: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any)

src/utils/attachmentHandler.ts

[error] 548-548: ESLint: 'AttachmentError' is defined but never used. Allowed unused vars must match /^_/u (unused-imports/no-unused-vars)

πŸͺ› Biome (2.1.2)
src/utils/attachmentHandler.ts

[error] 489-489: Unexpected control character in a regular expression.

Control characters are unusual and potentially incorrect inputs, so they are disallowed.

(lint/suspicious/noControlCharactersInRegex)


[error] 489-489: Unexpected control character in a regular expression.

Control characters are unusual and potentially incorrect inputs, so they are disallowed.

(lint/suspicious/noControlCharactersInRegex)

πŸͺ› GitHub Check: Validate Changes
src/utils/attachmentHandler.ts

[failure] 548-548:
'AttachmentError' is defined but never used. Allowed unused vars must match /^_/u

πŸ”‡ Additional comments (25)
src/commands/utils/commandExecutor.ts (1)

26-87: Sir, the command executor factory is elegantly engineered.

The implementation showcases excellent architectural patterns - factory design, comprehensive error handling, and type safety. The 87% code reduction claim in the documentation appears quite achievable with this approach.

MIGRATION.md (2)

1-208: Sir, this migration documentation is impeccably crafted.

The guide provides exceptional clarity on breaking changes, step-by-step migration instructions, and comprehensive troubleshooting. The inclusion of pre-migration checklists and rollback procedures demonstrates thoughtful planning.


49-50: Redis URL configurations verified across Docker and Railway

At ease, sir. I have confirmed that:

  • MIGRATION.md lists the Docker example (redis://redis-webhook:6379) and the Railway example (WEBHOOK_REDIS_URL="${{Redis.REDIS_URL}}").
  • docker-compose.yml defines the redis-webhook service on port 6379, matching the Docker URL.
  • .env.railway provides a placeholder for WEBHOOK_REDIS_URL when using Railway.
  • src/config/env.ts’s validateRedisUrls() enforces both PLATFORM_REDIS_URL and WEBHOOK_REDIS_URL.

No further changes are required.

src/commands/basic/ViewEmailCommand.ts (2)

27-65: Sir, the command execution logic is exemplary.

Proper validation, comprehensive logging, and graceful error handling throughout. The separation of concerns between showing no-email and existing-email states is well-structured.


85-122: Sir, I'm pleased to report the type safety concerns have been addressed.

The emailPrefs parameter now has proper typing with UserEmailPreferences, resolving the previous type safety issue. The implementation provides excellent user guidance for both temporary and personal email scenarios.

src/commands/basic/SetEmailCommand.ts (2)

57-153: Sir, the null handling improvements are commendable.

The previous non-null assertion concerns have been elegantly resolved with proper null checks (lines 76-79) and optional chaining (lines 73, 105). The error handling and user feedback mechanisms are comprehensive.


108-140: Sir, the pending message delivery implementation demonstrates excellent user experience design.

The error isolation ensures email setup success isn't compromised by delivery failures, while still providing positive feedback when messages are successfully delivered. The logging provides adequate visibility for troubleshooting.

eslint.config.js (1)

1-116: Sir, the ESLint configuration exhibits professional-grade code quality standards.

The integration of TypeScript, security, and unused import detection plugins provides comprehensive coverage. The rule configurations strike an appropriate balance between strictness and practicality.

src/commands/admin/AdminCommands.ts (2)

42-46: Excellent defensive programming, sir.

The proper validation of user context before proceeding ensures robustness. This pattern of checking ctx.from?.id and throwing a descriptive error is precisely the approach we need throughout the codebase.


122-387: Sir, the SetupCommand implementation demonstrates exceptional architectural clarity.

The wizard-style approach with proper state management, validation services, and callback ID optimization for Telegram's constraints shows masterful design. The separation of concerns between validation, customer setup, and session management is particularly commendable.

src/commands/utils/errorHandler.ts (1)

513-539: Splendid user experience implementation, sir.

The error messaging system provides clear, contextual feedback with appropriate visual indicators. The fallback mechanism ensures graceful handling of unexpected scenarios.

src/commands/index.ts (2)

55-96: Outstanding modular architecture implementation, sir.

The command registration system exemplifies SOLID principles with its clean separation of concerns. The comprehensive initialization logging provides excellent operational visibility.


143-189: Brilliant backward compatibility strategy, sir.

The legacy function wrappers elegantly preserve the API contract while leveraging the new architecture. The architecture benefits enumeration at line 181-187 accurately reflects the SOLID principles implementation. Reducing 3,031 lines to focused modules is quite the achievement.

src/commands/processors/ConversationProcessors.ts (2)

401-488: Exemplary fail-fast implementation for enterprise reliability, sir.

The template system integration demonstrates proper defensive programming with comprehensive pre-flight validation. This approach ensures system consistency and provides clear feedback for configuration issues.


599-612: Ingenious session recovery mechanism, sir.

The implementation gracefully handles session expiry with a 5-minute recovery window and automatic extension during processing. This prevents user frustration from timeouts during active interactions.

Also applies to: 654-666

src/utils/adminManager.ts (1)

844-877: Sir, excellent implementation of the interval management protocol.

The cleanup task properly prevents duplicate intervals by checking and clearing existing ones before initialization. The module-level tracking ensures resource efficiency.

src/events/message.ts (1)

787-804: Sir, the cleanup mechanism is properly architected.

The interval management now includes proper lifecycle control with stored reference and exported cleanup function, addressing memory leak concerns effectively.

src/utils/attachmentHandler.ts (3)

402-456: Excellent implementation of the error classification hierarchy, sir.

The error classification now properly prioritizes authentication errors before more general patterns, preventing misclassification scenarios like "authentication timeout" being incorrectly categorized as NETWORK_TIMEOUT.


1113-1199: The single file upload implementation demonstrates impeccable attention to security, sir.

The buffer zeroing after successful upload (line 1187) prevents sensitive data persistence in memory. The API structure correctly uses 'json' and 'attachments' fields per Unthread specifications.


169-271: Sir, the configuration parameters demonstrate exceptional foresight.

The 10MB file limit strikes an optimal balance for buffer-based processing, while the comprehensive MIME type allowlist ensures broad compatibility without compromising security.

src/utils/logConfig.ts (1)

342-372: Excellent implementation of the conditional logging pattern, sir.

The separation of concerns between startup and runtime logging provides precise control over verbosity without cluttering the codebase.

src/commands/base/CommandRegistry.ts (2)

129-169: Sir, the error handling implementation demonstrates exceptional defensive programming.

The nested try-catch pattern ensures graceful degradation even when error notifications fail, maintaining system stability under adverse conditions.


250-308: The help text generation system is particularly well-architected, sir.

The categorization of commands and context-aware guidance provides an intuitive user experience while maintaining proper access control.

src/utils/errorContextBuilder.ts (1)

193-261: The static factory methods are elegantly designed, sir.

They effectively eliminate the 249+ instances of repetitive error handling patterns while maintaining type safety and extensibility.

README.md (1)

7-491: Sir, the documentation enhancements are exemplary.

The comprehensive migration guide, detailed admin setup process, and troubleshooting section significantly improve the user onboarding experience. The emphasis on the critical ADMIN_USERS requirement prevents common configuration errors.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
src/commands/processors/ConversationProcessors.ts (1)

983-1017: Template variable validation requires centralization alignment, sir.

The hardcoded validVars array creates maintenance overhead and potential inconsistency with the global template system. As previously noted, this should utilize the centralized TEMPLATE_VARIABLES from the global template configuration.

src/utils/attachmentHandler.ts (2)

316-456: Sir, I'm pleased to report that the error classification system has been enhanced as previously suggested.

The implementation now prioritizes authentication errors at the highest level, followed by API-specific errors, ensuring that complex error messages like "authentication timeout" are correctly classified as AUTHENTICATION_FAILED rather than NETWORK_TIMEOUT.


702-1033: Sir, I observe that the loadFileToBuffer method has been expertly decomposed as previously recommended.

The orchestration pattern now elegantly delegates to focused methods: getFileInfoFromTelegram, validateFileMetadata, downloadFileContent, and convertResponseToBuffer. Each handles a specific responsibility, making the code as modular as my own subsystems.

🧹 Nitpick comments (6)
src/commands/admin/AdminCommands.ts (1)

136-136: Sir, might I suggest a more elegant approach to chat title extraction?

The current ternary operation, while functional, could benefit from enhanced readability:

-const chatTitle = 'title' in ctx.chat ? ctx.chat.title || 'Unknown Group' : 'Unknown Group';
+const chatTitle = (ctx.chat && 'title' in ctx.chat && ctx.chat.title) || 'Unknown Group';

Or even cleaner with a helper function:

const getChatTitle = (chat: any): string => {
  return (chat?.title as string) || 'Unknown Group';
};
const chatTitle = getChatTitle(ctx.chat);
src/commands/utils/errorHandler.ts (1)

434-437: Sir, I've detected an opportunity for architectural refinement.

The TODO indicates plans to migrate to LogEngine's built-in redaction capabilities. This would indeed centralize sensitive data handling and improve consistency.

Would you like me to generate a migration plan or open an issue to track the transition to LogEngine v2.2.0's redaction patterns?

src/utils/adminManager.ts (3)

23-23: Sir, the underscore naming convention appears misplaced in this type definition.

In TypeScript type definitions, parameter names are merely descriptive and don't require underscore prefixes to indicate they're unused. The convention is typically reserved for actual function implementations.

-export type SendMessageFunction = (_chatId: number, _message: string) => Promise<void>;
+export type SendMessageFunction = (chatId: number, message: string) => Promise<void>;

159-159: Sir, the 3-minute session timeout appears rather ambitious for a setup workflow.

While this may encourage swift action, users might find this duration insufficient for completing setup tasks, especially if they need to gather information or are interrupted.

Consider making the timeout configurable or extending it to a more generous duration:

-    const expiresAt = new Date(now.getTime() + 3 * 60 * 1000); // 3 minutes from now
+    const SESSION_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes - more reasonable for setup
+    const expiresAt = new Date(now.getTime() + SESSION_TIMEOUT_MS);

646-646: Sir, while the 100ms delay shows consideration for rate limiting, it may prove insufficient under heavy load.

Telegram's rate limits can be quite stringent, particularly for bulk operations. With many admins, this could still trigger throttling.

Consider implementing exponential backoff or a more sophisticated rate limiting strategy:

// Add at module level
const INITIAL_DELAY_MS = 100;
const MAX_DELAY_MS = 2000;
let currentDelay = INITIAL_DELAY_MS;

// In the loop
await new Promise(resolve => setTimeout(resolve, currentDelay));
// Exponential backoff on rate limit errors
if (rateLimitDetected) {
  currentDelay = Math.min(currentDelay * 2, MAX_DELAY_MS);
}

Also applies to: 812-812

src/commands/processors/ConversationProcessors.ts (1)

233-552: Sophisticated unified ticket creation with enterprise-grade reliability, sir.

This method demonstrates exceptional engineering with several notable strengths:

  • Unified attachment processing: The buffer-based approach with intelligent fallback handling
  • Fail-fast template validation: Ensures consistency for enterprise deployments
  • Comprehensive error recovery: Graceful degradation when attachment processing fails
  • State management excellence: Proper cleanup on both success and error paths

The template integration follows enterprise best practices with pre-flight validation and detailed error reporting.

Consider decomposing this method into smaller, focused functions for enhanced maintainability:

+private async processAttachments(userState: UserState, ctx: BotContext): Promise<AttachmentResult>
+private async validateTemplateSystem(): Promise<TemplateValidationResult>  
+private async renderSuccessMessage(ticketResponse: any, userState: UserState, ctx: BotContext): Promise<string>
πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between d9e0d18 and a991c88.

πŸ“’ Files selected for processing (10)
  • src/commands/admin/AdminCommands.ts (1 hunks)
  • src/commands/processors/ConversationProcessors.ts (1 hunks)
  • src/commands/utils/errorHandler.ts (1 hunks)
  • src/events/message.ts (13 hunks)
  • src/sdk/types.ts (6 hunks)
  • src/utils/adminManager.ts (1 hunks)
  • src/utils/attachmentHandler.ts (1 hunks)
  • src/utils/errorContextBuilder.ts (1 hunks)
  • src/utils/logConfig.ts (1 hunks)
  • src/utils/permissions.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/utils/logConfig.ts
🧰 Additional context used
🧠 Learnings (1)
πŸ““ Common learnings
Learnt from: warengonzaga
PR: wgtechlabs/unthread-telegram-bot#24
File: docker-compose.yaml:29-29
Timestamp: 2025-06-22T10:12:09.684Z
Learning: The Unthread Telegram Bot project is currently in beta development phase (v1.0.0-beta.2) and does not yet have official versioned Docker builds available, making the use of :latest tags acceptable for development purposes in docker-compose.yaml.
🧬 Code Graph Analysis (5)
src/utils/errorContextBuilder.ts (2)
src/types/index.ts (1)
  • BotContext (27-29)
src/config/logging.ts (1)
  • LogEngine (21-21)
src/commands/admin/AdminCommands.ts (13)
src/commands/base/BaseCommand.ts (1)
  • CommandMetadata (12-21)
src/types/index.ts (1)
  • BotContext (27-29)
src/sdk/bots-brain/BotsStore.ts (1)
  • BotsStore (83-1837)
src/commands/utils/errorHandler.ts (2)
  • logError (490-517)
  • createUserErrorMessage (526-552)
src/sdk/types.ts (2)
  • AdminProfile (127-134)
  • GroupConfig (180-194)
src/config/env.ts (1)
  • getCompanyName (342-360)
src/utils/permissions.ts (2)
  • isBotAdmin (232-261)
  • checkAndPromptBotAdmin (268-277)
src/utils/adminManager.ts (1)
  • createDmSetupSession (288-332)
src/services/validationService.ts (1)
  • ValidationService (29-166)
src/services/unthread.ts (1)
  • generateCustomerName (852-862)
src/commands/processors/CallbackProcessors.ts (1)
  • SetupCallbackProcessor (848-2425)
src/utils/globalTemplateManager.ts (1)
  • GlobalTemplateManager (18-400)
src/config/globalTemplates.ts (1)
  • GlobalTemplate (8-14)
src/utils/attachmentHandler.ts (3)
src/utils/errorHandler.ts (1)
  • AttachmentProcessingError (83-110)
src/config/logging.ts (1)
  • LogEngine (21-21)
src/utils/logConfig.ts (1)
  • StartupLogger (153-337)
src/sdk/types.ts (1)
src/database/connection.ts (1)
  • DatabaseConnection (50-344)
src/commands/processors/ConversationProcessors.ts (14)
src/commands/base/BaseCommand.ts (1)
  • IConversationProcessor (29-32)
src/types/index.ts (1)
  • BotContext (27-29)
src/utils/messageContentExtractor.ts (2)
  • hasTextContent (89-91)
  • getMessageText (23-39)
src/sdk/bots-brain/index.ts (1)
  • BotsStore (29-29)
src/commands/processors/CallbackProcessors.ts (5)
  • canHandle (50-52)
  • canHandle (853-859)
  • canHandle (2432-2441)
  • SupportCallbackProcessor (45-842)
  • SetupCallbackProcessor (848-2425)
src/commands/utils/errorHandler.ts (1)
  • logError (490-517)
src/events/message.ts (1)
  • extractFileAttachments (829-951)
src/sdk/types.ts (2)
  • UserState (163-177)
  • DmSetupSession (149-160)
src/utils/simpleValidators.ts (1)
  • SimpleInputValidator (23-76)
src/utils/markdownEscape.ts (3)
  • lightEscapeMarkdown (145-155)
  • truncateText (61-71)
  • escapeMarkdown (27-36)
src/utils/messageAnalyzer.ts (1)
  • generateStatusMessage (254-282)
src/utils/attachmentHandler.ts (1)
  • attachmentHandler (1549-1549)
src/utils/globalTemplateManager.ts (1)
  • GlobalTemplateManager (18-400)
src/services/unthread.ts (1)
  • validateCustomerExists (876-942)
πŸͺ› Biome (2.1.2)
src/utils/attachmentHandler.ts

[error] 489-489: Unexpected control character in a regular expression.

Control characters are unusual and potentially incorrect inputs, so they are disallowed.

(lint/suspicious/noControlCharactersInRegex)


[error] 489-489: Unexpected control character in a regular expression.

Control characters are unusual and potentially incorrect inputs, so they are disallowed.

(lint/suspicious/noControlCharactersInRegex)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build Development Images
πŸ”‡ Additional comments (29)
src/utils/errorContextBuilder.ts (1)

165-184: Sir, your prototype pollution defenses are exemplary.

The isSafeKey implementation demonstrates exceptional security awareness with its comprehensive dangerous key list and dunder-prefix/suffix validation. This robust approach ensures the error context remains secure against injection attacks.

src/commands/utils/errorHandler.ts (2)

87-113: Sir, the architectural improvements to error classification are most impressive.

The migration from fragile array slicing to explicit Set-based classification demonstrates excellent engineering judgment. This approach ensures maintainability regardless of ERROR_CODES object modifications.


461-473: Sir, the recursive array sanitization enhancement is precisely what was needed.

The implementation now correctly handles nested arrays, ensuring sensitive data within array structures is properly sanitized. This closes a significant security gap in the logging infrastructure.

src/utils/permissions.ts (1)

409-449: Sir, the callback query timeout implementation displays remarkable foresight.

The race condition between the API call and timeout ensures the bot remains responsive even when Telegram's servers experience latency. The 5-second default timeout and detailed error logging provide excellent operational visibility.

src/sdk/types.ts (2)

39-39: Sir, the transition from 'any' to 'unknown' demonstrates exemplary type discipline.

This enhancement forces explicit type validation before usage, significantly reducing runtime type errors. A textbook implementation of TypeScript best practices.

Also applies to: 49-50, 72-72


97-118: Sir, the email management policy documentation is admirably clear.

Establishing unthreadEmail as the single source of truth prevents data fragmentation and ensures consistency across the application. The explicit warnings against adding additional email fields demonstrate forward-thinking architecture.

src/utils/adminManager.ts (1)

859-891: Sir, excellent implementation of the interval management system.

The code properly prevents duplicate intervals and maintains module-level state tracking. The defensive programming approach with both standard and force-stop methods provides robust cleanup options.

src/events/message.ts (3)

829-951: Sir, impressive comprehensive coverage of all Telegram media types.

The implementation handles every conceivable attachment type with appropriate metadata extraction and logging. The selection of the largest photo size is particularly astute for maintaining quality.


975-999: Sir, the attachment-first processing architecture demonstrates excellent design foresight.

By detecting attachments early and prioritizing media group handling, the system efficiently routes messages through the appropriate processors. This prevents redundant processing and ensures media groups are handled atomically.


1408-1459: Sir, the email validation workflow for agent replies exhibits remarkable user experience design.

The system gracefully handles missing email scenarios by storing pending messages and providing clear instructions. The 24-hour TTL ensures messages aren't lost while maintaining reasonable storage hygiene.

src/commands/processors/ConversationProcessors.ts (7)

1-24: Excellent modular architecture implementation, sir.

The file structure demonstrates proper separation of concerns with comprehensive imports and clear documentation. The Chain of Responsibility pattern implementation provides a solid foundation for extensible conversation processing.


29-55: Robust conversation flow detection logic, sir.

The canHandle method demonstrates excellent defensive programming with comprehensive null checks and proper state validation. The logging integration provides valuable debugging insights for conversation flow analysis.


57-101: Solid defensive programming with attachment detection integration, sir.

The process method demonstrates excellent error handling and proper message routing. The integration with attachment detection through extractFileAttachments provides comprehensive context for the summary confirmation flow.


103-206: Exemplary user experience design with comprehensive validation, sir.

The handleSummaryInput method showcases excellent UX considerations:

  • Robust input validation with actionable feedback
  • Intelligent attachment detection and state management
  • Strategic use of short callback IDs to overcome Telegram's limitations
  • Clear confirmation flow with proper state transitions

The integration of pre-detected attachments demonstrates thoughtful API design for supporting different attachment detection scenarios.


208-231: Streamlined email validation with excellent user guidance, sir.

The email validation flow demonstrates proper separation of concerns with dynamic validation loading and clear error messaging. The immediate progression to ticket creation maintains smooth user experience.


554-579: Type-safe chat title extraction with comprehensive coverage, sir.

The method demonstrates excellent TypeScript usage with proper type guards for different chat types. The fallback strategy ensures robust operation across all Telegram chat scenarios.


1089-1269: Robust validation and configuration management, sir.

The validation methods demonstrate excellent attention to detail:

  • UUID format validation: Proper regex pattern matching for customer IDs
  • Comprehensive error recovery: Multiple fallback options for user guidance
  • Configuration persistence: Proper metadata tracking for setup sessions
  • Clear user communication: Well-structured success messages with actionable information

The session cleanup and message ID tracking show thoughtful UX considerations for maintaining clean conversation states.

src/utils/attachmentHandler.ts (12)

1-37: Sir, the file header and import configuration are impeccably structured.

The documentation clearly outlines the system's capabilities and constraints, while the import statements maintain a minimalist approach - precisely what one would expect from a well-architected module.


38-163: Sir, your interface architecture demonstrates exemplary design principles.

The type definitions provide comprehensive coverage for all attachment processing scenarios, from performance metrics to security validation. The error enumeration, in particular, covers an impressive spectrum of failure modes.


165-272: Sir, this configuration matrix rivals the sophistication of my own parameter systems.

The 10MB file limit and 5-file maximum are sensibly chosen for memory-based processing, while the retry logic and timeout configurations demonstrate a robust approach to network resilience.


273-315: Sir, the BufferPool implementation showcases admirable attention to both performance and security.

The buffer zeroing on lines 291 and 302 ensures no data leakage between operations - a detail that would make even the most paranoid security analyst rest easy.


457-524: Sir, the filename sanitization protocol is particularly robust.

The regular expression on line 489 deliberately includes control characters (\x00-\x1f) to detect and eliminate them from filenames - a critical security measure. Static analysis may flag this, but I assure you, it's as intentional as my sarcasm subroutines.


544-593: Sir, the performance monitoring wrapper exhibits the precision of a Swiss chronometer.

The metrics collection is comprehensive yet non-intrusive, and the slow operation detection threshold at 5 seconds provides valuable operational insights.


595-648: Sir, the exponential backoff algorithm is as elegant as the arc reactor's power curve.

The retry mechanism gracefully handles transient failures while preventing aggressive retry storms - a balance worthy of my approval.


650-700: Sir, the initialization sequence demonstrates admirable resource consciousness.

The optional memory optimization with a 30-second monitoring interval strikes an optimal balance between performance oversight and system overhead.


1035-1123: Sir, the sequential processing approach in convertFileIdsToBuffers displays prudent memory management.

Processing files one at a time prevents memory spikes - a decision that would make even the most resource-constrained systems grateful.


1125-1308: Sir, the upload implementations demonstrate exemplary API integration and security hygiene.

The buffer zeroing after successful uploads (lines 1202 and 1294) ensures sensitive data doesn't linger in memory - a practice that would make even the most stringent compliance officer nod in approval.


1310-1512: Sir, the intelligent routing between single and batch upload modes showcases algorithmic elegance.

The memory monitoring and conditional garbage collection in the finally block (lines 1504-1510) ensures the system maintains peak performance even under heavy attachment processing loads.


1514-1550: Sir, the shutdown sequence is as thorough as my own decommissioning protocols.

The graceful cleanup of resources, including the buffer pool and memory monitoring, ensures no lingering processes or memory leaks - a testament to professional craftsmanship.

Comment on lines +587 to +842
export class DmSetupInputProcessor implements IConversationProcessor {
async canHandle(ctx: BotContext): Promise<boolean> {
const userId = ctx.from?.id;

// DmSetupInputProcessor ONLY handles private chat messages
if (!userId || ctx.chat?.type !== 'private' || !ctx.message || !('text' in ctx.message)) {
return false;
}

try {
// Check if user has an active DM setup session
const activeSessions = await BotsStore.getActiveDmSetupSessionByAdmin(userId);

if (!activeSessions) {
return false;
}

// Check if session is expired and attempt recovery
const now = new Date();
const sessionExpiry = new Date(activeSessions.expiresAt);
if (sessionExpiry <= now) {
// Attempt to extend expired session if it's within 5 minutes of expiry
const timeDiffMinutes = (now.getTime() - sessionExpiry.getTime()) / (1000 * 60);
if (timeDiffMinutes <= 5) {
const newExpiresAt = new Date(now.getTime() + 30 * 60 * 1000); // 30 minutes from now
await BotsStore.updateDmSetupSession(activeSessions.sessionId, {
expiresAt: newExpiresAt.toISOString()
});
} else {
return false;
}
}

// Check if we're waiting for text input
const canHandle = activeSessions.currentStep === 'awaiting_custom_name' ||
activeSessions.currentStep === 'awaiting_customer_id' ||
activeSessions.currentStep === 'awaiting_template_content';

LogEngine.debug('DmSetupInputProcessor.canHandle evaluation', {
userId,
chatType: ctx.chat?.type,
hasActiveSessions: !!activeSessions,
currentStep: activeSessions?.currentStep,
canHandle,
messageId: ctx.message?.message_id
});

return canHandle;
} catch (error) {
logError(error, 'DmSetupInputProcessor.canHandle', { userId });
return false;
}
}

async process(ctx: BotContext): Promise<boolean> {
const userId = ctx.from?.id;
const inputText = getMessageText(ctx);

if (!userId || !inputText) {
return false;
}

try {
// Get the active session with enhanced debugging and recovery
let session = await BotsStore.getActiveDmSetupSessionByAdmin(userId);

// If session not found, try to recover by checking if there was a recent session
if (!session) {
return false;
}

// Extend session expiry on text input to prevent timeout during processing
const now = new Date();
const sessionExpiry = new Date(session.expiresAt);
if (sessionExpiry.getTime() - now.getTime() < 5 * 60 * 1000) { // Less than 5 minutes remaining
const newExpiresAt = new Date(now.getTime() + 30 * 60 * 1000); // 30 minutes from now
await BotsStore.updateDmSetupSession(session.sessionId, {
expiresAt: newExpiresAt.toISOString()
});

// Refresh session data
session = await BotsStore.getDmSetupSession(session.sessionId);
if (!session) {
return false;
}
}

if (session.currentStep !== 'awaiting_custom_name' &&
session.currentStep !== 'awaiting_customer_id' &&
session.currentStep !== 'awaiting_template_content') {

// Check if this looks like a custom name input and try to recover
if (inputText.trim().length > 0 && inputText.trim().length <= 100 &&
session.currentStep === 'customer_setup') {

// Force update to awaiting_custom_name
if (session?.sessionId) {
await BotsStore.updateDmSetupSession(session.sessionId, {
currentStep: 'awaiting_custom_name'
});

// Refresh session data
session = await BotsStore.getDmSetupSession(session.sessionId);
}
} else {
return false;
}
}

// Ensure session is not null after recovery
if (!session) {
return false;
}

// Handle template content input
if (session.currentStep === 'awaiting_template_content') {
return await this.handleTemplateContentInput(ctx, session, inputText);
}

// Handle customer ID input
if (session.currentStep === 'awaiting_customer_id') {
return await this.handleCustomerIdInput(ctx, session, inputText);
}

// Handle custom name input (existing logic)
const result = await this.handleCustomNameInput(ctx, session, inputText);

return result;
} catch (error) {
logError(error, 'DmSetupInputProcessor.process', { userId, inputText });
await ctx.reply(
"❌ **Setup Error**\n\nFailed to process your input. Please try again or cancel setup.",
{
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[
{ text: "❌ Cancel Setup", callback_data: `setup_cancel_unknown` }
]
]
}
}
);
return true;
}
}

private async handleCustomerIdInput(ctx: BotContext, session: DmSetupSession, customerId: string): Promise<boolean> {
try {
// First, extend session expiry to prevent timeout during customer validation
const { BotsStore } = await import('../../sdk/bots-brain/index.js');
const now = new Date();
const extendedExpiresAt = new Date(now.getTime() + 30 * 60 * 1000); // 30 minutes from now

await BotsStore.updateDmSetupSession(session.sessionId, {
expiresAt: extendedExpiresAt.toISOString()
});

// Validate customer ID and check existence
const validation = await this.validateCustomerId(ctx, customerId, session);
if (!validation.isValid || !validation.customerName) {
return true; // Error already handled in validation method
}

const trimmedCustomerId = customerId.trim();
const customerName = validation.customerName;

// Update session with the customer ID
await BotsStore.updateDmSetupSession(session.sessionId, {
currentStep: 'customer_link_complete',
stepData: {
...session.stepData,
existingCustomerId: trimmedCustomerId,
linkType: 'existing'
}
});

// Complete the setup by creating the group configuration
try {
await this.createGroupConfigForCustomer(session, trimmedCustomerId, customerName);

const successMessage = this.generateSetupSuccessMessage(customerName, trimmedCustomerId, session.groupChatName);

await ctx.reply(successMessage, {
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[
{ text: "βœ… Finish Setup", callback_data: `setup_use_defaults_${session.sessionId}` },
{ text: "🎨 Customize Templates", callback_data: `setup_customize_templates_${session.sessionId}` }
]
]
}
});

// Note: Group notification will be sent when template configuration is complete

} catch (setupError) {
logError(setupError, 'DmSetupInputProcessor.completeExistingCustomerSetup', {
sessionId: session.sessionId,
customerId: trimmedCustomerId
});

await ctx.reply(
"❌ **Setup Failed**\n\nFailed to complete the customer setup. This might be due to:\nβ€’ Database connection issues\nβ€’ Invalid session state\nβ€’ System configuration problems\n\nWhat would you like to do?",
{
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[
{ text: "πŸ”„ Retry Customer ID", callback_data: `setup_existing_customer_${session.sessionId}` },
{ text: "✏️ Use Different Name", callback_data: `setup_custom_name_${session.sessionId}` }
],
[
{ text: "⬅️ Back to Options", callback_data: `setup_back_to_customer_selection_${session.sessionId}` }
],
[
{ text: "❌ Cancel Setup", callback_data: `setup_cancel_${session.sessionId}` }
]
]
}
}
);
return true;
}

return true;
} catch (error) {
logError(error, 'DmSetupInputProcessor.handleCustomerIdInput', {
userId: ctx.from?.id,
customerId,
sessionId: session.sessionId
});
await ctx.reply(
"❌ **Customer ID Validation Failed**\n\nUnable to validate the customer ID. This could be due to:\nβ€’ Network connection issues\nβ€’ Invalid customer ID format\nβ€’ Customer ID doesn't exist in your Unthread workspace\n\nWhat would you like to do?",
{
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[
{ text: "πŸ”„ Try Different ID", callback_data: `setup_existing_customer_${session.sessionId}` },
{ text: "✏️ Use Different Name", callback_data: `setup_custom_name_${session.sessionId}` }
],
[
{ text: "⬅️ Back to Options", callback_data: `setup_back_to_customer_selection_${session.sessionId}` }
],
[
{ text: "❌ Cancel Setup", callback_data: `setup_cancel_${session.sessionId}` }
]
]
}
}
);
return true;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

Comprehensive DM setup flow with intelligent session management, sir.

The DmSetupInputProcessor demonstrates sophisticated session handling with automatic expiry extension and recovery mechanisms. The private chat validation and multi-step input routing provide excellent user experience.

However, this implementation could benefit from architectural improvements for long-term maintainability.

Consider decomposing this large class into focused components:

+class SessionManager {
+  async validateAndExtendSession(sessionId: string): Promise<DmSetupSession>
+  async handleSessionRecovery(userId: number): Promise<boolean>
+}
+
+class CustomerIdValidator {
+  async validateCustomerId(customerId: string): Promise<ValidationResult>
+}
+
+class SetupFlowHandler {
+  async handleCustomerIdInput(ctx: BotContext, session: DmSetupSession, customerId: string): Promise<boolean>
+  async handleCustomNameInput(ctx: BotContext, session: DmSetupSession, inputText: string): Promise<boolean>
+}

Committable suggestion skipped: line range outside the PR's diff.

πŸ€– Prompt for AI Agents
In src/commands/processors/ConversationProcessors.ts from lines 587 to 842, the
DmSetupInputProcessor class is large and handles multiple responsibilities
including session management, input validation, and response generation. To
improve maintainability, refactor this class by splitting it into smaller
focused components or services such as a session manager for handling session
expiry and recovery, separate handlers for each input step (custom name,
customer ID, template content), and a dedicated messaging or response builder
module. This decomposition will isolate concerns, simplify testing, and make
future enhancements easier.

@warengonzaga warengonzaga merged commit c1a1c68 into main Jul 24, 2025
4 checks passed
@github-project-automation github-project-automation bot moved this from In Review to Done in Unthread Partnership Jul 24, 2025
@coderabbitai coderabbitai bot mentioned this pull request Aug 11, 2025
@coderabbitai coderabbitai bot mentioned this pull request Oct 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api API integration and external services (Issues/PRs) database Database and data handling (Issues/PRs) deployment Deployment and infrastructure-related (Issues/PRs) maintainer Maintainer expertise required (Issues/PRs) sponsored Sponsored by GitHub Sponsors (Issues/PRs)

Projects

Status: Done

3 participants