diff --git a/apps/bot/src/household-setup.ts b/apps/bot/src/household-setup.ts index d37c9e0..411a28b 100644 --- a/apps/bot/src/household-setup.ts +++ b/apps/bot/src/household-setup.ts @@ -28,6 +28,7 @@ const GROUP_INVITE_TTL_MS = 3 * 24 * 60 * 60 * 1000 const SETUP_BIND_TOPIC_ACTION = 'setup_topic_binding' as const const SETUP_BIND_TOPIC_TTL_MS = 10 * 60 * 1000 const HOUSEHOLD_TOPIC_ROLE_ORDER: readonly HouseholdTopicRole[] = [ + 'chat', 'purchase', 'feedback', 'reminders', @@ -106,11 +107,13 @@ function bindRejectionMessage( function bindTopicUsageMessage( locale: BotLocale, - role: 'purchase' | 'feedback' | 'reminders' | 'payments' + role: 'chat' | 'purchase' | 'feedback' | 'reminders' | 'payments' ): string { const t = getBotTranslations(locale).setup switch (role) { + case 'chat': + return t.useBindChatTopicInGroup case 'purchase': return t.useBindPurchaseTopicInGroup case 'feedback': @@ -124,13 +127,15 @@ function bindTopicUsageMessage( function bindTopicSuccessMessage( locale: BotLocale, - role: 'purchase' | 'feedback' | 'reminders' | 'payments', + role: 'chat' | 'purchase' | 'feedback' | 'reminders' | 'payments', householdName: string, threadId: string ): string { const t = getBotTranslations(locale).setup switch (role) { + case 'chat': + return t.chatTopicSaved(householdName, threadId) case 'purchase': return t.purchaseTopicSaved(householdName, threadId) case 'feedback': @@ -358,7 +363,11 @@ function setupReply(input: { function isHouseholdTopicRole(value: string): value is HouseholdTopicRole { return ( - value === 'purchase' || value === 'feedback' || value === 'reminders' || value === 'payments' + value === 'chat' || + value === 'purchase' || + value === 'feedback' || + value === 'reminders' || + value === 'payments' ) } @@ -647,7 +656,7 @@ export function registerHouseholdSetupCommands(options: { async function handleBindTopicCommand( ctx: Context, - role: 'purchase' | 'feedback' | 'reminders' | 'payments' + role: 'chat' | 'purchase' | 'feedback' | 'reminders' | 'payments' ): Promise { const locale = await resolveReplyLocale({ ctx, @@ -1129,6 +1138,10 @@ export function registerHouseholdSetupCommands(options: { await ctx.reply(t.setup.unsetupComplete(result.household.householdName)) }) + options.bot.command('bind_chat_topic', async (ctx) => { + await handleBindTopicCommand(ctx, 'chat') + }) + options.bot.command('bind_purchase_topic', async (ctx) => { await handleBindTopicCommand(ctx, 'purchase') }) diff --git a/apps/bot/src/i18n/locales/en.ts b/apps/bot/src/i18n/locales/en.ts index 86400fb..0cd20a0 100644 --- a/apps/bot/src/i18n/locales/en.ts +++ b/apps/bot/src/i18n/locales/en.ts @@ -9,6 +9,7 @@ export const enBotTranslations: BotTranslationCatalog = { cancel: 'Cancel the current prompt', setup: 'Register this group as a household', unsetup: 'Reset topic setup for this group', + bind_chat_topic: 'Bind the current topic for casual conversation', bind_purchase_topic: 'Bind the current topic as purchases', bind_feedback_topic: 'Bind the current topic as feedback', bind_reminders_topic: 'Bind the current topic as reminders', @@ -76,6 +77,8 @@ export const enBotTranslations: BotTranslationCatalog = { setupTopicBindNotAvailable: 'That topic-binding action is no longer available.', setupTopicBindRoleName: (role) => { switch (role) { + case 'chat': + return 'chat' case 'purchase': return 'purchases' case 'feedback': @@ -88,6 +91,8 @@ export const enBotTranslations: BotTranslationCatalog = { }, setupTopicSuggestedName: (role) => { switch (role) { + case 'chat': + return 'Chat' case 'purchase': return 'Shared purchases' case 'feedback': @@ -103,6 +108,9 @@ export const enBotTranslations: BotTranslationCatalog = { unsetupComplete: (householdName) => `Setup state reset for ${householdName}. Run /setup again to bind topics from scratch.`, unsetupNoop: 'Nothing to reset for this group yet. Run /setup when you are ready.', + useBindChatTopicInGroup: 'Use /bind_chat_topic inside the household group topic.', + chatTopicSaved: (householdName, threadId) => + `Chat topic saved for ${householdName} (thread ${threadId}).`, useBindPurchaseTopicInGroup: 'Use /bind_purchase_topic inside the household group topic.', purchaseTopicSaved: (householdName, threadId) => `Purchase topic saved for ${householdName} (thread ${threadId}).`, diff --git a/apps/bot/src/i18n/locales/ru.ts b/apps/bot/src/i18n/locales/ru.ts index a97c166..3ee553b 100644 --- a/apps/bot/src/i18n/locales/ru.ts +++ b/apps/bot/src/i18n/locales/ru.ts @@ -9,6 +9,7 @@ export const ruBotTranslations: BotTranslationCatalog = { cancel: 'Отменить текущий ввод', setup: 'Подключить эту группу как дом', unsetup: 'Сбросить настройку топиков для этой группы', + bind_chat_topic: 'Назначить текущий топик для разговоров', bind_purchase_topic: 'Назначить текущий топик для покупок', bind_feedback_topic: 'Назначить текущий топик для анонимных сообщений', bind_reminders_topic: 'Назначить текущий топик для напоминаний', @@ -78,6 +79,8 @@ export const ruBotTranslations: BotTranslationCatalog = { setupTopicBindNotAvailable: 'Это действие привязки топика уже недоступно.', setupTopicBindRoleName: (role) => { switch (role) { + case 'chat': + return 'разговоров' case 'purchase': return 'покупки' case 'feedback': @@ -90,6 +93,8 @@ export const ruBotTranslations: BotTranslationCatalog = { }, setupTopicSuggestedName: (role) => { switch (role) { + case 'chat': + return 'Разговоры' case 'purchase': return 'Общие покупки' case 'feedback': @@ -105,6 +110,9 @@ export const ruBotTranslations: BotTranslationCatalog = { unsetupComplete: (householdName) => `Состояние настройки для ${householdName} сброшено. Запустите /setup ещё раз, чтобы заново привязать топики.`, unsetupNoop: 'Для этой группы пока нечего сбрасывать. Когда будете готовы, запустите /setup.', + useBindChatTopicInGroup: 'Используйте /bind_chat_topic внутри топика группы дома.', + chatTopicSaved: (householdName, threadId) => + `Топик для разговоров сохранён для ${householdName} (тред ${threadId}).`, useBindPurchaseTopicInGroup: 'Используйте /bind_purchase_topic внутри топика группы дома.', purchaseTopicSaved: (householdName, threadId) => `Топик покупок сохранён для ${householdName} (тред ${threadId}).`, diff --git a/apps/bot/src/i18n/types.ts b/apps/bot/src/i18n/types.ts index 314830b..e74ca84 100644 --- a/apps/bot/src/i18n/types.ts +++ b/apps/bot/src/i18n/types.ts @@ -7,6 +7,7 @@ export type TelegramCommandName = | 'cancel' | 'setup' | 'unsetup' + | 'bind_chat_topic' | 'bind_purchase_topic' | 'bind_feedback_topic' | 'bind_reminders_topic' @@ -23,6 +24,7 @@ export interface BotCommandDescriptions { cancel: string setup: string unsetup: string + bind_chat_topic: string bind_purchase_topic: string bind_feedback_topic: string bind_reminders_topic: string @@ -90,12 +92,18 @@ export interface BotTranslationCatalog { setupTopicBindPending: (role: string) => string setupTopicBindCancelled: string setupTopicBindNotAvailable: string - setupTopicBindRoleName: (role: 'purchase' | 'feedback' | 'reminders' | 'payments') => string - setupTopicSuggestedName: (role: 'purchase' | 'feedback' | 'reminders' | 'payments') => string + setupTopicBindRoleName: ( + role: 'chat' | 'purchase' | 'feedback' | 'reminders' | 'payments' + ) => string + setupTopicSuggestedName: ( + role: 'chat' | 'purchase' | 'feedback' | 'reminders' | 'payments' + ) => string onlyTelegramAdminsUnsetup: string useUnsetupInGroup: string unsetupComplete: (householdName: string) => string unsetupNoop: string + useBindChatTopicInGroup: string + chatTopicSaved: (householdName: string, threadId: string) => string useBindPurchaseTopicInGroup: string purchaseTopicSaved: (householdName: string, threadId: string) => string useBindFeedbackTopicInGroup: string diff --git a/apps/bot/src/telegram-commands.ts b/apps/bot/src/telegram-commands.ts index 99e15f5..9bea27f 100644 --- a/apps/bot/src/telegram-commands.ts +++ b/apps/bot/src/telegram-commands.ts @@ -35,6 +35,7 @@ const GROUP_ADMIN_COMMAND_NAMES = [ ...GROUP_MEMBER_COMMAND_NAMES, 'setup', 'unsetup', + 'bind_chat_topic', 'bind_purchase_topic', 'bind_feedback_topic', 'bind_reminders_topic', diff --git a/packages/ports/src/household-config.ts b/packages/ports/src/household-config.ts index e14ac23..9ba0e0a 100644 --- a/packages/ports/src/household-config.ts +++ b/packages/ports/src/household-config.ts @@ -1,7 +1,13 @@ import type { CurrencyCode, SupportedLocale } from '@household/domain' import type { ReminderTarget } from './reminders' -export const HOUSEHOLD_TOPIC_ROLES = ['purchase', 'feedback', 'reminders', 'payments'] as const +export const HOUSEHOLD_TOPIC_ROLES = [ + 'chat', + 'purchase', + 'feedback', + 'reminders', + 'payments' +] as const export const HOUSEHOLD_MEMBER_LIFECYCLE_STATUSES = ['active', 'away', 'left'] as const export const HOUSEHOLD_MEMBER_ABSENCE_POLICIES = [ 'resident',