Conversation
WalkthroughA Telegram bot integration was introduced into the web application. This involved adding new environment variables, updating the Nuxt runtime configuration, installing the Changes
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)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~15 minutes Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
⏰ 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)
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
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
botvariable 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
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis 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 additionThe
grammy: ^1.37.0entry 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.
| export function useCreateWasabiVistaBot() { | ||
| bot = new Bot(telegram.wasabiVistaToken) | ||
|
|
There was a problem hiding this comment.
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.
| 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.
| 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('Я пока не умею отвечать на сообщения.') | ||
| }) |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Address hardcoded strings, privacy concerns, and error handling.
Several issues in the message handling logic:
- Hardcoded Russian strings - Consider using internationalization
- Privacy concern - Logging user IDs may violate privacy policies
- Missing error handling - Reply operations can fail
- 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.
| 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.
| export async function notifyWasabiVistaAdmin(message: string) { | ||
| return useWasabiVistaBot().api.sendMessage(telegram.adminId, message) | ||
| } |
There was a problem hiding this comment.
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.
| 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.
|



Summary by CodeRabbit