feat(bot): add safe group unsetup flow

This commit is contained in:
2026-03-11 06:08:34 +04:00
parent 1b8c6e87f6
commit b6b6f9e1b8
25 changed files with 495 additions and 0 deletions

View File

@@ -72,6 +72,19 @@ function setupRejectionMessage(
}
}
function unsetupRejectionMessage(
locale: BotLocale,
reason: 'not_admin' | 'invalid_chat_type'
): string {
const t = getBotTranslations(locale).setup
switch (reason) {
case 'not_admin':
return t.onlyTelegramAdminsUnsetup
case 'invalid_chat_type':
return t.useUnsetupInGroup
}
}
function bindRejectionMessage(
locale: BotLocale,
reason: 'not_admin' | 'household_not_found' | 'not_topic_message'
@@ -668,6 +681,57 @@ export function registerHouseholdSetupCommands(options: {
await ctx.reply(reply.text, 'reply_markup' in reply ? { reply_markup: reply.reply_markup } : {})
})
options.bot.command('unsetup', async (ctx) => {
const locale = await resolveReplyLocale({
ctx,
repository: options.householdConfigurationRepository
})
const t = getBotTranslations(locale)
if (!isGroupChat(ctx)) {
await ctx.reply(t.setup.useUnsetupInGroup)
return
}
const telegramChatId = ctx.chat.id.toString()
const result = await options.householdSetupService.unsetupGroupChat({
actorIsAdmin: await isGroupAdmin(ctx),
telegramChatId,
telegramChatType: ctx.chat.type
})
if (result.status === 'rejected') {
await ctx.reply(unsetupRejectionMessage(locale, result.reason))
return
}
if (result.status === 'noop') {
await options.promptRepository?.clearPendingActionsForChat(
telegramChatId,
SETUP_BIND_TOPIC_ACTION
)
await ctx.reply(t.setup.unsetupNoop)
return
}
await options.promptRepository?.clearPendingActionsForChat(
telegramChatId,
SETUP_BIND_TOPIC_ACTION
)
options.logger?.info(
{
event: 'household_setup.chat_reset',
telegramChatId,
householdId: result.household.householdId,
actorTelegramUserId: ctx.from?.id?.toString()
},
'Household setup state reset'
)
await ctx.reply(t.setup.unsetupComplete(result.household.householdName))
})
options.bot.command('bind_purchase_topic', async (ctx) => {
await handleBindTopicCommand(ctx, 'purchase')
})