Skip to content

feat: telegram bot#48

Merged
hmbanan666 merged 3 commits intomainfrom
telegram
Aug 5, 2025
Merged

feat: telegram bot#48
hmbanan666 merged 3 commits intomainfrom
telegram

Conversation

@hmbanan666
Copy link
Copy Markdown
Collaborator

@hmbanan666 hmbanan666 commented Aug 5, 2025

Summary by CodeRabbit

  • New Features
    • Introduced Telegram bot integration for the web app, enabling basic interaction and admin notifications via Telegram.
  • Chores
    • Added new environment variable placeholders for Telegram integration.
    • Updated dependencies to include the "grammy" library for Telegram bot support.

@hmbanan666 hmbanan666 self-assigned this Aug 5, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Aug 5, 2025

Walkthrough

A Telegram bot integration was introduced into the web application. This involved adding new environment variables, updating the Nuxt runtime configuration, installing the grammy library, and implementing a Nitro plugin and service for bot initialization and message handling. Supporting dependency catalog updates were also made.

Changes

Cohort / File(s) Change Summary
Environment Variables
apps/web-app/.env.example
Added placeholders for NUXT_TELEGRAM_WASABI_VISTA_TOKEN and NUXT_TELEGRAM_ADMIN_ID under a new "Telegram" section.
Nuxt Configuration
apps/web-app/nuxt.config.ts
Introduced a telegram object in runtimeConfig with properties for the bot token and admin ID.
Bot Plugin
apps/web-app/server/plugins/03.telegram.ts
Added a Nitro plugin that conditionally initializes the Telegram bot in production using the runtime configuration.
Bot Service
apps/web-app/server/services/telegram/wasabi-vista.ts
Implemented Telegram bot logic: singleton management, message handling including /start command with access code generation, and admin notification utility.
Dependencies - App
apps/web-app/package.json
Added the grammy library as a dependency.
Dependencies - Workspace
pnpm-workspace.yaml
Registered grammy with version ^1.37.0 in the workspace catalog.

Sequence Diagram(s)

sequenceDiagram
    participant NitroPlugin as Nitro Plugin
    participant RuntimeConfig as Runtime Config
    participant BotService as Telegram Bot Service
    participant TelegramAPI as Telegram API
    participant Admin as Admin User

    NitroPlugin->>RuntimeConfig: Load telegram config
    NitroPlugin->>BotService: useCreateWasabiVistaBot(token)
    BotService->>TelegramAPI: Start long polling
    TelegramAPI-->>BotService: Receives message
    BotService->>TelegramAPI: Reply based on message type
    BotService->>Admin: notifyWasabiVistaAdmin(message)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Poem

A bunny hops with code so bright,
Telegram bots now join the night.
With tokens set and configs neat,
A greeting sent, replies complete.
Dependencies tucked in, ready to go—
The admin gets a message, in the flow!
🐰📨

Note

⚡️ Unit Test Generation is now available in beta!

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


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4e1814d and c70ed15.

📒 Files selected for processing (3)
  • apps/web-app/.env.example (1 hunks)
  • apps/web-app/server/plugins/03.telegram.ts (1 hunks)
  • apps/web-app/server/services/telegram/wasabi-vista.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/web-app/.env.example
  • apps/web-app/server/plugins/03.telegram.ts
  • apps/web-app/server/services/telegram/wasabi-vista.ts
⏰ 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
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch telegram

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 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.
  • 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.

Support

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

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 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.

@socket-security
Copy link
Copy Markdown

socket-security bot commented Aug 5, 2025

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addeddrizzle-cuid2@​2.1.07710010083100
Addeddate-fns@​4.1.01001009180100
Addeddrizzle-orm@​0.44.4981008799100
Addeddotenv@​17.2.19910010094100
Addedeslint@​9.32.09710010094100
Addeddrizzle-kit@​0.31.4991009698100

View full report

Copy link
Copy Markdown

@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: 4

🧹 Nitpick comments (5)
apps/web-app/.env.example (1)

23-25: LGTM! Optional: Consider reordering for consistency.

The Telegram environment variables are correctly formatted and follow the NUXT_ prefix convention.

If you prefer strict alphabetical ordering within sections, you could reorder as suggested by the linter:

 # Telegram
-NUXT_TELEGRAM_WASABI_VISTA_TOKEN=
 NUXT_TELEGRAM_ADMIN_ID=
+NUXT_TELEGRAM_WASABI_VISTA_TOKEN=

However, the current logical grouping (token first, then admin ID) is also reasonable.

apps/web-app/server/plugins/03.telegram.ts (2)

4-7: LGTM! Consider adding debug logging for non-production environments.

The production-only guard is appropriate for a Telegram bot that should only run in production.

Consider adding debug logging to clarify why the plugin exits early:

 export default defineNitroPlugin(() => {
   if (process.env.NODE_ENV !== 'production') {
+    useLogger('plugin-start-telegram').info('Skipping Telegram bot in non-production environment')
     return
   }

17-21: LGTM! Clean bot initialization and logging.

The bot startup and success logging provide good visibility into the plugin's operation.

The comment mentions "bots" (plural) but only one bot is started. Consider updating for accuracy:

-  // Start the bots (using long polling)
+  // Start the bot (using long polling)
apps/web-app/server/services/telegram/wasabi-vista.ts (2)

1-6: Consider thread safety for the singleton bot instance.

The global bot variable could lead to race conditions if multiple requests try to initialize the bot simultaneously in a concurrent environment.

Consider adding a mutex or using a more robust singleton pattern:

+import { Bot } from 'grammy'
+
+const logger = useLogger('telegram:wasabi-vista')
+const { telegram } = useRuntimeConfig()
+
-let bot: Bot | null = null
+let bot: Bot | null = null
+let isInitializing = false

39-45: Improve error message for better debugging.

 export function useWasabiVistaBot(): Bot {
   if (!bot) {
-    throw new Error('Bot is not created')
+    throw new Error('Wasabi Vista bot is not initialized. Call useCreateWasabiVistaBot() first.')
   }
 
   return bot
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b18a043 and 4e1814d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • apps/web-app/.env.example (1 hunks)
  • apps/web-app/nuxt.config.ts (1 hunks)
  • apps/web-app/package.json (1 hunks)
  • apps/web-app/server/plugins/03.telegram.ts (1 hunks)
  • apps/web-app/server/services/telegram/wasabi-vista.ts (1 hunks)
  • pnpm-workspace.yaml (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: the latest version of pnpm on npm registry is 10.14.0 as of august 2025, so "npm install -g pnpm" in...
Learnt from: hmbanan666
PR: nextorders/roll-stack#40
File: package.json:5-6
Timestamp: 2025-08-01T10:34:55.317Z
Learning: The latest version of pnpm on npm registry is 10.14.0 as of August 2025, so "npm install -g pnpm" installs this version without needing explicit version specification.

Applied to files:

  • pnpm-workspace.yaml
🧬 Code Graph Analysis (1)
apps/web-app/server/plugins/03.telegram.ts (1)
apps/web-app/server/services/telegram/wasabi-vista.ts (1)
  • useCreateWasabiVistaBot (8-37)
🪛 dotenv-linter (3.3.0)
apps/web-app/.env.example

[warning] 25-25: [UnorderedKey] The NUXT_TELEGRAM_ADMIN_ID key should go before the NUXT_TELEGRAM_WASABI_VISTA_TOKEN key

⏰ 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
🔇 Additional comments (4)
pnpm-workspace.yaml (1)

46-46: Approve dependency addition

The grammy: ^1.37.0 entry is correct and up-to-date—1.37.0 is the latest stable grammY release as of July 5, 2025. No further changes needed.

apps/web-app/package.json (1)

26-26: LGTM!

The dependency addition correctly references the workspace catalog and maintains proper alphabetical ordering.

apps/web-app/nuxt.config.ts (1)

21-24: LGTM!

The telegram runtime configuration follows Nuxt best practices and maintains consistency with existing configuration structure.

apps/web-app/server/plugins/03.telegram.ts (1)

12-15: LGTM! Good error handling for missing configuration.

The early return prevents the bot from starting without proper configuration, which is the correct behavior.

Comment on lines +8 to +10
export function useCreateWasabiVistaBot() {
bot = new Bot(telegram.wasabiVistaToken)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add validation for the Telegram bot token.

The bot creation doesn't validate if telegram.wasabiVistaToken exists, which could cause runtime errors.

 export function useCreateWasabiVistaBot() {
+  if (!telegram.wasabiVistaToken) {
+    throw new Error('Telegram bot token is not configured')
+  }
+  
   bot = new Bot(telegram.wasabiVistaToken)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function useCreateWasabiVistaBot() {
bot = new Bot(telegram.wasabiVistaToken)
export function useCreateWasabiVistaBot() {
if (!telegram.wasabiVistaToken) {
throw new Error('Telegram bot token is not configured')
}
bot = new Bot(telegram.wasabiVistaToken)
🤖 Prompt for AI Agents
In apps/web-app/server/services/telegram/wasabi-vista.ts around lines 8 to 10,
the code creates a new Bot instance using telegram.wasabiVistaToken without
checking if the token exists. Add a validation step before creating the Bot to
verify that telegram.wasabiVistaToken is defined and not empty. If the token is
missing, throw an appropriate error or handle the case gracefully to prevent
runtime errors.

Comment on lines +11 to +34
bot.on('message:text', async (ctx) => {
// const locale = ctx.message.from.language_code

if (ctx.hasCommand('start')) {
// Welcome message with buttons
await ctx.reply(
'Привет!',
// {
// reply_markup: {
// inline_keyboard: [
// [{ text: dictionary(locale).bots.woodland.title, url: woodlandsBotUrl }],
// [{ text: dictionary(locale).bots.subscribeToChannel, url: gameChannelUrl }],
// [{ text: dictionary(locale).bots.chatgame.playingOnTwitch, url: twitchUrl }],
// ],
// },
// },
)

return
}

logger.log(ctx.message.from.id, ctx.message.text)
ctx.reply('Я пока не умею отвечать на сообщения.')
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

⚠️ Potential issue

Address hardcoded strings, privacy concerns, and error handling.

Several issues in the message handling logic:

  1. Hardcoded Russian strings - Consider using internationalization
  2. Privacy concern - Logging user IDs may violate privacy policies
  3. Missing error handling - Reply operations can fail
  4. Commented code - Should be removed or properly documented
   bot.on('message:text', async (ctx) => {
-    // const locale = ctx.message.from.language_code
+    const locale = ctx.message.from.language_code || 'ru'
 
     if (ctx.hasCommand('start')) {
-      // Welcome message with buttons
-      await ctx.reply(
-        'Привет!',
-        // {
-        //   reply_markup: {
-        //     inline_keyboard: [
-        //       [{ text: dictionary(locale).bots.woodland.title, url: woodlandsBotUrl }],
-        //       [{ text: dictionary(locale).bots.subscribeToChannel, url: gameChannelUrl }],
-        //       [{ text: dictionary(locale).bots.chatgame.playingOnTwitch, url: twitchUrl }],
-        //     ],
-        //   },
-        // },
-      )
+      try {
+        await ctx.reply(dictionary(locale).bots.wasabiVista.greeting)
+      } catch (error) {
+        logger.error('Failed to send welcome message:', error)
+      }
 
       return
     }
 
-    logger.log(ctx.message.from.id, ctx.message.text)
-    ctx.reply('Я пока не умею отвечать на сообщения.')
+    logger.log('Received message from user')
+    try {
+      await ctx.reply(dictionary(locale).bots.wasabiVista.defaultResponse)
+    } catch (error) {
+      logger.error('Failed to send default response:', error)
+    }
   })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
bot.on('message:text', async (ctx) => {
// const locale = ctx.message.from.language_code
if (ctx.hasCommand('start')) {
// Welcome message with buttons
await ctx.reply(
'Привет!',
// {
// reply_markup: {
// inline_keyboard: [
// [{ text: dictionary(locale).bots.woodland.title, url: woodlandsBotUrl }],
// [{ text: dictionary(locale).bots.subscribeToChannel, url: gameChannelUrl }],
// [{ text: dictionary(locale).bots.chatgame.playingOnTwitch, url: twitchUrl }],
// ],
// },
// },
)
return
}
logger.log(ctx.message.from.id, ctx.message.text)
ctx.reply('Я пока не умею отвечать на сообщения.')
})
bot.on('message:text', async (ctx) => {
const locale = ctx.message.from.language_code || 'ru'
if (ctx.hasCommand('start')) {
try {
await ctx.reply(dictionary(locale).bots.wasabiVista.greeting)
} catch (error) {
logger.error('Failed to send welcome message:', error)
}
return
}
logger.log('Received message from user')
try {
await ctx.reply(dictionary(locale).bots.wasabiVista.defaultResponse)
} catch (error) {
logger.error('Failed to send default response:', error)
}
})
🤖 Prompt for AI Agents
In apps/web-app/server/services/telegram/wasabi-vista.ts around lines 11 to 34,
replace hardcoded Russian reply strings with calls to an internationalization
function to support multiple languages, remove or properly document the
commented-out code for clarity, avoid logging user IDs directly to protect user
privacy, and add try-catch blocks around asynchronous reply calls to handle
potential errors gracefully.

Comment on lines +47 to +49
export async function notifyWasabiVistaAdmin(message: string) {
return useWasabiVistaBot().api.sendMessage(telegram.adminId, message)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add validation and error handling for admin notifications.

The function lacks validation for adminId and error handling for the API call.

 export async function notifyWasabiVistaAdmin(message: string) {
+  if (!telegram.adminId) {
+    throw new Error('Telegram admin ID is not configured')
+  }
+  
+  if (!message?.trim()) {
+    throw new Error('Message cannot be empty')
+  }
+  
+  try {
-    return useWasabiVistaBot().api.sendMessage(telegram.adminId, message)
+    return await useWasabiVistaBot().api.sendMessage(telegram.adminId, message)
+  } catch (error) {
+    logger.error('Failed to notify admin:', error)
+    throw error
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function notifyWasabiVistaAdmin(message: string) {
return useWasabiVistaBot().api.sendMessage(telegram.adminId, message)
}
export async function notifyWasabiVistaAdmin(message: string) {
if (!telegram.adminId) {
throw new Error('Telegram admin ID is not configured')
}
if (!message?.trim()) {
throw new Error('Message cannot be empty')
}
try {
return await useWasabiVistaBot().api.sendMessage(telegram.adminId, message)
} catch (error) {
logger.error('Failed to notify admin:', error)
throw error
}
}
🤖 Prompt for AI Agents
In apps/web-app/server/services/telegram/wasabi-vista.ts around lines 47 to 49,
the notifyWasabiVistaAdmin function does not validate the adminId or handle
errors from the sendMessage API call. Add a check to ensure telegram.adminId is
defined and valid before calling sendMessage. Wrap the API call in a try-catch
block to catch and handle any errors, logging or managing them appropriately to
prevent unhandled promise rejections.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Aug 5, 2025

@hmbanan666 hmbanan666 merged commit 6515f94 into main Aug 5, 2025
8 checks passed
@hmbanan666 hmbanan666 deleted the telegram branch August 5, 2025 12:37
@coderabbitai coderabbitai bot mentioned this pull request Aug 6, 2025
@coderabbitai coderabbitai bot mentioned this pull request Sep 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant