diff --git a/apps/bot/locales/en.ftl b/apps/bot/locales/en.ftl index aac2f14..c1b9e18 100644 --- a/apps/bot/locales/en.ftl +++ b/apps/bot/locales/en.ftl @@ -1,3 +1,7 @@ +start = + .description = Start the bot + + err-invalid-url = ❌ Invalid URL! Please send a valid TikTok link (e.g., https://vt.tiktok.com/...) err-invalid-download-urls = 🔍 Download links not found. The video might be deleted or unavailable err-generic = ⚠️ Something went wrong. Please try again in a few seconds diff --git a/apps/bot/locales/ru.ftl b/apps/bot/locales/ru.ftl index 21cd977..40ba25d 100644 --- a/apps/bot/locales/ru.ftl +++ b/apps/bot/locales/ru.ftl @@ -1,3 +1,7 @@ +start = + .description = Запуск бота + + err-invalid-url = ❌ Неверная ссылка! Отправьте корректную ссылку TikTok (например: https://vt.tiktok.com/...) err-invalid-download-urls = 🔍 Не удалось найти ссылки для скачивания. Возможно, видео удалено или недоступно err-generic = ⚠️ Что-то пошло не так. Попробуйте еще раз через несколько секунд diff --git a/apps/bot/package.json b/apps/bot/package.json index 2cece67..a5693b1 100644 --- a/apps/bot/package.json +++ b/apps/bot/package.json @@ -19,6 +19,7 @@ ], "dependencies": { "@grammyjs/auto-chat-action": "^0.1.1", + "@grammyjs/commands": "^1.1.0", "@grammyjs/hydrate": "^1.4.1", "@grammyjs/i18n": "^1.1.2", "@grammyjs/parse-mode": "^2.2.0", diff --git a/apps/bot/src/bot/commands/index.ts b/apps/bot/src/bot/commands/index.ts new file mode 100644 index 0000000..afaf8ca --- /dev/null +++ b/apps/bot/src/bot/commands/index.ts @@ -0,0 +1,38 @@ +import { type Context } from '@/bot/context'; +import { i18n } from '@/bot/i18n'; +import { Command, CommandGroup } from '@grammyjs/commands'; +import { type LanguageCode } from '@grammyjs/types'; +import { type NextFunction } from 'grammy'; + +export async function setCommands(ctx: Context, next: NextFunction) { + const start = createCommand('start'); + + const commands = [start]; + + for (const command of commands) { + addLocalizations(command); + } + + const commandsGroup = new CommandGroup().add([start]); + + await commandsGroup.setCommands(ctx); + return next(); +} + +function addLocalizations(command: Command) { + for (const locale of i18n.locales) { + command.localize( + locale as LanguageCode, + command.name, + i18n.t(locale, `${command.name}.description`), + ); + } + + return command; +} + +function createCommand(name: string) { + return new Command(name, i18n.t('en', `${name}.description`)).addToScope({ + type: 'all_private_chats', + }); +} diff --git a/apps/bot/src/bot/context.ts b/apps/bot/src/bot/context.ts index a08099a..0b0d24c 100644 --- a/apps/bot/src/bot/context.ts +++ b/apps/bot/src/bot/context.ts @@ -1,11 +1,13 @@ import { type logger } from '@/utils/logger'; import { type AutoChatActionFlavor } from '@grammyjs/auto-chat-action'; +import { type CommandsFlavor } from '@grammyjs/commands'; import { type HydrateFlavor } from '@grammyjs/hydrate'; import { type I18nFlavor } from '@grammyjs/i18n'; import { type Context as DefaultContext } from 'grammy'; export type Context = HydrateFlavor< AutoChatActionFlavor & + CommandsFlavor & DefaultContext & I18nFlavor & { logger: typeof logger; diff --git a/apps/bot/src/bot/index.ts b/apps/bot/src/bot/index.ts index eb2d4dd..ffdb419 100644 --- a/apps/bot/src/bot/index.ts +++ b/apps/bot/src/bot/index.ts @@ -1,4 +1,5 @@ /* eslint-disable n/callback-return */ +import { setCommands } from './commands'; import { type Context } from './context'; import * as features from './features'; import { errorHandler } from './handlers/errors'; @@ -51,6 +52,7 @@ export function createBot({ apiRoot, token }: Parameters_) { const protectedBot = bot.errorBoundary(errorHandler); + protectedBot.use(setCommands); protectedBot.use(autoChatAction(bot.api)); protectedBot.use(hydrate()); protectedBot.use(features.welcome); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d284320..e0412a4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -57,6 +57,9 @@ importers: '@grammyjs/auto-chat-action': specifier: ^0.1.1 version: 0.1.1(grammy@1.37.1) + '@grammyjs/commands': + specifier: ^1.1.0 + version: 1.1.0(grammy@1.37.1) '@grammyjs/hydrate': specifier: ^1.4.1 version: 1.5.0(grammy@1.37.1) @@ -501,6 +504,11 @@ packages: peerDependencies: grammy: ^1.0.0 + '@grammyjs/commands@1.1.0': + resolution: {integrity: sha512-yU95GZLOfZabXGmbb5ImJ5cmVVxLk81iypvriiVpr2NGJ2DIAH3dzSJQNOgFbfX6li3rGm7l2h0JR1mvLkfF/w==} + peerDependencies: + grammy: ^1.17.1 + '@grammyjs/hydrate@1.5.0': resolution: {integrity: sha512-5OtGidRbqD3TGxQ9HXrVxCWhjzR0uJQ32SFNeJO/I+g2iMQ7pkBkhp7QK11x/K2nWfyu+EcPQE3fubLNb75xQw==} engines: {node: ^12.20.0 || >=14.13.1} @@ -4280,6 +4288,10 @@ snapshots: dependencies: grammy: 1.37.1 + '@grammyjs/commands@1.1.0(grammy@1.37.1)': + dependencies: + grammy: 1.37.1 + '@grammyjs/hydrate@1.5.0(grammy@1.37.1)': dependencies: abort-controller: 3.0.0