From fcdd0f2aaf1da4473cf59f1652b131326328ec57 Mon Sep 17 00:00:00 2001 From: whekin Date: Tue, 17 Mar 2026 02:17:11 +0400 Subject: [PATCH] feat(bot): add /dashboard command and MINI_APP_URL config - Add /dashboard command to BotFather registration alongside /app - Add new MINI_APP_URL env var for dashboard URL (separate from CORS origins) - Pass MINI_APP_URL and BOT_API_URL in CD workflow - Update Terraform with new variable for future infrastructure deployments --- .env.example | 3 +++ .github/workflows/cd.yml | 6 +++++- apps/bot/src/config.ts | 5 +++++ apps/bot/src/i18n/locales/en.ts | 1 + apps/bot/src/i18n/locales/ru.ts | 1 + apps/bot/src/i18n/types.ts | 2 ++ apps/bot/src/index.ts | 16 +++++++++++----- apps/bot/src/telegram-commands.ts | 4 +++- infra/terraform/main.tf | 3 +++ infra/terraform/terraform.tfvars.example | 1 + infra/terraform/variables.tf | 7 +++++++ 11 files changed, 42 insertions(+), 7 deletions(-) diff --git a/.env.example b/.env.example index e4311d0..8a3b5e8 100644 --- a/.env.example +++ b/.env.example @@ -13,6 +13,9 @@ TELEGRAM_WEBHOOK_SECRET=your-webhook-secret TELEGRAM_WEBHOOK_PATH=/webhook/telegram # Mini app +# URL for /app and /dashboard commands (e.g., https://your-app.cloud.run) +MINI_APP_URL=https://your-miniapp-domain.com +# CORS origins for mini app API (comma-separated) MINI_APP_ALLOWED_ORIGINS=http://localhost:5173 # Parsing / AI diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index df8ac08..3d0ffac 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -234,15 +234,18 @@ jobs: } >> "$GITHUB_OUTPUT" - name: Deploy bot service + id: bot-api run: | gcloud run deploy "household-${SERVICE_SUFFIX}-bot-api" \ --image "${{ steps.images.outputs.bot_image }}" \ --region "${GCP_REGION}" \ --project "${{ vars.GCP_PROJECT_ID }}" \ - --set-env-vars "DB_SCHEMA=${DB_SCHEMA}" \ + --set-env-vars "DB_SCHEMA=${DB_SCHEMA},MINI_APP_URL=${{ vars.MINI_APP_URL }}" \ --allow-unauthenticated \ --quiet + echo "url=$(gcloud run services describe "household-${SERVICE_SUFFIX}-bot-api" --region "${GCP_REGION}" --project "${{ vars.GCP_PROJECT_ID }}" --format 'value(status.url)')" >> "$GITHUB_OUTPUT" + - name: Route traffic to latest bot revision run: | gcloud run services update-traffic "household-${SERVICE_SUFFIX}-bot-api" \ @@ -257,6 +260,7 @@ jobs: --image "${{ steps.images.outputs.mini_image }}" \ --region "${GCP_REGION}" \ --project "${{ vars.GCP_PROJECT_ID }}" \ + --set-env-vars "BOT_API_URL=${{ steps.bot-api.outputs.url }}" \ --allow-unauthenticated \ --quiet diff --git a/apps/bot/src/config.ts b/apps/bot/src/config.ts index 52f00a7..dedd885 100644 --- a/apps/bot/src/config.ts +++ b/apps/bot/src/config.ts @@ -25,6 +25,7 @@ export interface BotRuntimeConfig { assistantRateLimitBurstWindowMs: number assistantRateLimitRolling: number assistantRateLimitRollingWindowMs: number + miniAppUrl?: string } function parsePort(raw: string | undefined): number { @@ -103,6 +104,7 @@ export function getBotRuntimeConfig(env: NodeJS.ProcessEnv = process.env): BotRu const schedulerSharedSecret = parseOptionalValue(env.SCHEDULER_SHARED_SECRET) const schedulerOidcAllowedEmails = parseOptionalCsv(env.SCHEDULER_OIDC_ALLOWED_EMAILS) const miniAppAllowedOrigins = parseOptionalCsv(env.MINI_APP_ALLOWED_ORIGINS) + const miniAppUrl = parseOptionalValue(env.MINI_APP_URL) const purchaseTopicIngestionEnabled = databaseUrl !== undefined @@ -174,6 +176,9 @@ export function getBotRuntimeConfig(env: NodeJS.ProcessEnv = process.env): BotRu if (schedulerSharedSecret !== undefined) { runtime.schedulerSharedSecret = schedulerSharedSecret } + if (miniAppUrl !== undefined) { + runtime.miniAppUrl = miniAppUrl + } const openaiApiKey = parseOptionalValue(env.OPENAI_API_KEY) if (openaiApiKey !== undefined) { runtime.openaiApiKey = openaiApiKey diff --git a/apps/bot/src/i18n/locales/en.ts b/apps/bot/src/i18n/locales/en.ts index 495d0b2..c1af013 100644 --- a/apps/bot/src/i18n/locales/en.ts +++ b/apps/bot/src/i18n/locales/en.ts @@ -15,6 +15,7 @@ export const enBotTranslations: BotTranslationCatalog = { pending_members: 'List pending household join requests', approve_member: 'Approve a pending household member', app: 'Open the Kojori mini app', + dashboard: 'Open the household dashboard', keyboard: 'Toggle persistent dashboard button' }, help: { diff --git a/apps/bot/src/i18n/locales/ru.ts b/apps/bot/src/i18n/locales/ru.ts index 30114a1..b626f3f 100644 --- a/apps/bot/src/i18n/locales/ru.ts +++ b/apps/bot/src/i18n/locales/ru.ts @@ -15,6 +15,7 @@ export const ruBotTranslations: BotTranslationCatalog = { pending_members: 'Показать ожидающие заявки на вступление', approve_member: 'Подтвердить участника дома', app: 'Открыть мини-приложение Kojori', + dashboard: 'Открыть дашборд дома', keyboard: 'Вкл/выкл кнопку дашборда' }, help: { diff --git a/apps/bot/src/i18n/types.ts b/apps/bot/src/i18n/types.ts index 9223f42..febf58d 100644 --- a/apps/bot/src/i18n/types.ts +++ b/apps/bot/src/i18n/types.ts @@ -13,6 +13,7 @@ export type TelegramCommandName = | 'pending_members' | 'approve_member' | 'app' + | 'dashboard' | 'keyboard' export interface BotCommandDescriptions { @@ -28,6 +29,7 @@ export interface BotCommandDescriptions { pending_members: string approve_member: string app: string + dashboard: string keyboard: string } diff --git a/apps/bot/src/index.ts b/apps/bot/src/index.ts index 5ae1326..fcaa8b6 100644 --- a/apps/bot/src/index.ts +++ b/apps/bot/src/index.ts @@ -313,7 +313,13 @@ if (purchaseRepositoryClient && householdConfigurationRepositoryClient) { if (runtime.financeCommandsEnabled) { const financeCommands = createFinanceCommandsService({ householdConfigurationRepository: householdConfigurationRepositoryClient!.repository, - financeServiceForHousehold + financeServiceForHousehold, + ...(runtime.miniAppUrl + ? { + miniAppUrl: runtime.miniAppUrl, + botUsername: bot.botInfo?.username + } + : {}) }) financeCommands.register(bot) @@ -343,9 +349,9 @@ if (householdConfigurationRepositoryClient) { promptRepository: telegramPendingActionRepositoryClient.repository } : {}), - ...(runtime.miniAppAllowedOrigins[0] + ...(runtime.miniAppUrl ? { - miniAppUrl: runtime.miniAppAllowedOrigins[0] + miniAppUrl: runtime.miniAppUrl } : {}), logger: getLogger('household-setup') @@ -399,9 +405,9 @@ const reminderJobs = runtime.reminderJobsEnabled }) }, reminderService, - ...(runtime.miniAppAllowedOrigins[0] + ...(runtime.miniAppUrl ? { - miniAppUrl: runtime.miniAppAllowedOrigins[0] + miniAppUrl: runtime.miniAppUrl } : {}), ...(bot.botInfo?.username diff --git a/apps/bot/src/telegram-commands.ts b/apps/bot/src/telegram-commands.ts index f686a7a..5c55012 100644 --- a/apps/bot/src/telegram-commands.ts +++ b/apps/bot/src/telegram-commands.ts @@ -24,7 +24,9 @@ const DEFAULT_COMMAND_NAMES = [ const PRIVATE_CHAT_COMMAND_NAMES = [ ...DEFAULT_COMMAND_NAMES, 'anon', - 'cancel' + 'cancel', + 'app', + 'dashboard' ] as const satisfies readonly TelegramCommandName[] const GROUP_CHAT_COMMAND_NAMES = DEFAULT_COMMAND_NAMES const GROUP_MEMBER_COMMAND_NAMES = [ diff --git a/infra/terraform/main.tf b/infra/terraform/main.tf index 3b7f557..96cd4f2 100644 --- a/infra/terraform/main.tf +++ b/infra/terraform/main.tf @@ -166,6 +166,9 @@ module "bot_api_service" { length(var.bot_mini_app_allowed_origins) == 0 ? {} : { MINI_APP_ALLOWED_ORIGINS = join(",", var.bot_mini_app_allowed_origins) }, + var.bot_mini_app_url == null ? {} : { + MINI_APP_URL = var.bot_mini_app_url + }, { SCHEDULER_OIDC_ALLOWED_EMAILS = google_service_account.scheduler_invoker.email } diff --git a/infra/terraform/terraform.tfvars.example b/infra/terraform/terraform.tfvars.example index 5f3c5fd..925d8d2 100644 --- a/infra/terraform/terraform.tfvars.example +++ b/infra/terraform/terraform.tfvars.example @@ -20,6 +20,7 @@ bot_assistant_rate_limit_burst = 5 bot_assistant_rate_limit_burst_window_ms = 60000 bot_assistant_rate_limit_rolling = 50 bot_assistant_rate_limit_rolling_window_ms = 86400000 +bot_mini_app_url = "https://household-dev-mini-app-abc123-ew.a.run.app" bot_mini_app_allowed_origins = [ "https://household-dev-mini-app-abc123-ew.a.run.app" ] diff --git a/infra/terraform/variables.tf b/infra/terraform/variables.tf index d9222a3..bf685a5 100644 --- a/infra/terraform/variables.tf +++ b/infra/terraform/variables.tf @@ -139,6 +139,13 @@ variable "bot_assistant_rate_limit_rolling_window_ms" { nullable = true } +variable "bot_mini_app_url" { + description = "Optional URL for /app and /dashboard bot commands" + type = string + default = null + nullable = true +} + variable "bot_mini_app_allowed_origins" { description = "Optional allow-list of mini app origins for bot CORS handling" type = list(string)