mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 14:04:04 +00:00
feat: add chat topic binding for casual conversation
Add ability to bind a dedicated chat topic where normal conversation happens, separate from functional topics (purchases, payments, etc.) - Add 'chat' to HOUSEHOLD_TOPIC_ROLES - Add /bind_chat_topic command for admins - Update i18n strings for en/ru - Add command to admin scope in telegram-commands
This commit is contained in:
@@ -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<void> {
|
||||
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')
|
||||
})
|
||||
|
||||
@@ -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}).`,
|
||||
|
||||
@@ -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}).`,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user