mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 14:04:04 +00:00
fix(bot): improve utilities reminder template flow
This commit is contained in:
@@ -270,7 +270,8 @@ export const enBotTranslations: BotTranslationCatalog = {
|
|||||||
`I could not read that amount for ${categoryName}. Reply with a number in ${currency}, or send 0 / "skip".`,
|
`I could not read that amount for ${categoryName}. Reply with a number in ${currency}, or send 0 / "skip".`,
|
||||||
templateIntro: (currency) =>
|
templateIntro: (currency) =>
|
||||||
`Fill in the utility amounts below in ${currency}, then send the completed message back in this topic.`,
|
`Fill in the utility amounts below in ${currency}, then send the completed message back in this topic.`,
|
||||||
templateInstruction: 'Use 0 or skip for any category you want to leave empty.',
|
templateInstruction:
|
||||||
|
'For any category you do not want to add, leave it blank, remove the line entirely, or send 0 / "skip".',
|
||||||
templateInvalid:
|
templateInvalid:
|
||||||
'I could not read any utility amounts from that template. Send the filled template back with at least one amount.',
|
'I could not read any utility amounts from that template. Send the filled template back with at least one amount.',
|
||||||
summaryTitle: (period) => `Utility charges for ${period}`,
|
summaryTitle: (period) => `Utility charges for ${period}`,
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ export const ruBotTranslations: BotTranslationCatalog = {
|
|||||||
templateIntro: (currency) =>
|
templateIntro: (currency) =>
|
||||||
`Заполните суммы по коммуналке ниже в ${currency}, затем отправьте заполненное сообщение обратно в этот топик.`,
|
`Заполните суммы по коммуналке ниже в ${currency}, затем отправьте заполненное сообщение обратно в этот топик.`,
|
||||||
templateInstruction:
|
templateInstruction:
|
||||||
'Для любой категории, которую не нужно добавлять, укажите 0 или слово «пропуск».',
|
'Для любой категории, которую не нужно добавлять, оставьте поле пустым, удалите строку целиком или укажите 0 / «пропуск».',
|
||||||
templateInvalid:
|
templateInvalid:
|
||||||
'Не удалось распознать ни одной суммы в этом шаблоне. Отправьте заполненный шаблон хотя бы с одной суммой.',
|
'Не удалось распознать ни одной суммы в этом шаблоне. Отправьте заполненный шаблон хотя бы с одной суммой.',
|
||||||
summaryTitle: (period) => `Коммунальные начисления за ${period}`,
|
summaryTitle: (period) => `Коммунальные начисления за ${period}`,
|
||||||
|
|||||||
@@ -375,7 +375,8 @@ describe('registerReminderTopicUtilities', () => {
|
|||||||
expect(calls[1]).toMatchObject({
|
expect(calls[1]).toMatchObject({
|
||||||
method: 'sendMessage',
|
method: 'sendMessage',
|
||||||
payload: {
|
payload: {
|
||||||
text: expect.stringContaining('Electricity:'),
|
text: expect.stringContaining('<pre>Electricity: \nWater: </pre>'),
|
||||||
|
parse_mode: 'HTML',
|
||||||
message_thread_id: 555
|
message_thread_id: 555
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -391,6 +392,34 @@ describe('registerReminderTopicUtilities', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('treats blank or removed template lines as skipped categories', async () => {
|
||||||
|
const { bot, calls } = setupBot()
|
||||||
|
|
||||||
|
await bot.handleUpdate(reminderCallbackUpdate(REMINDER_UTILITY_TEMPLATE_CALLBACK) as never)
|
||||||
|
|
||||||
|
calls.length = 0
|
||||||
|
await bot.handleUpdate(reminderMessageUpdate('Electricity: 22\nWater: ') as never)
|
||||||
|
|
||||||
|
expect(calls[0]).toMatchObject({
|
||||||
|
method: 'sendMessage',
|
||||||
|
payload: {
|
||||||
|
text: expect.stringContaining('- Electricity: 22.00 GEL')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
calls.length = 0
|
||||||
|
await bot.handleUpdate(reminderCallbackUpdate(REMINDER_UTILITY_TEMPLATE_CALLBACK) as never)
|
||||||
|
calls.length = 0
|
||||||
|
await bot.handleUpdate(reminderMessageUpdate('Electricity: 22') as never)
|
||||||
|
|
||||||
|
expect(calls[0]).toMatchObject({
|
||||||
|
method: 'sendMessage',
|
||||||
|
payload: {
|
||||||
|
text: expect.stringContaining('- Electricity: 22.00 GEL')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
test('treats expired pending reminder submissions as unavailable', async () => {
|
test('treats expired pending reminder submissions as unavailable', async () => {
|
||||||
const { bot, calls, promptRepository } = setupBot()
|
const { bot, calls, promptRepository } = setupBot()
|
||||||
|
|
||||||
|
|||||||
@@ -182,20 +182,32 @@ function parseTemplateEntries(
|
|||||||
return entries.length > 0 ? entries : null
|
return entries.length > 0 ? entries : null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function escapeHtml(raw: string): string {
|
||||||
|
return raw.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>')
|
||||||
|
}
|
||||||
|
|
||||||
function buildTemplateText(
|
function buildTemplateText(
|
||||||
locale: BotLocale,
|
locale: BotLocale,
|
||||||
currency: 'GEL' | 'USD',
|
currency: 'GEL' | 'USD',
|
||||||
categories: readonly string[]
|
categories: readonly string[]
|
||||||
): string {
|
): {
|
||||||
|
text: string
|
||||||
|
parseMode: 'HTML'
|
||||||
|
} {
|
||||||
const t = getBotTranslations(locale).reminders
|
const t = getBotTranslations(locale).reminders
|
||||||
|
|
||||||
return [
|
const templateLines = categories.map((category) => `${category}: `).join('\n')
|
||||||
t.templateIntro(currency),
|
|
||||||
|
return {
|
||||||
|
text: [
|
||||||
|
escapeHtml(t.templateIntro(currency)),
|
||||||
'',
|
'',
|
||||||
...categories.map((category) => `${category}: `),
|
`<pre>${escapeHtml(templateLines)}</pre>`,
|
||||||
'',
|
'',
|
||||||
t.templateInstruction
|
escapeHtml(t.templateInstruction)
|
||||||
].join('\n')
|
].join('\n'),
|
||||||
|
parseMode: 'HTML'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function reminderUtilitySummaryText(
|
function reminderUtilitySummaryText(
|
||||||
@@ -261,7 +273,10 @@ function buildReminderConfirmationPayload(input: {
|
|||||||
async function replyInTopic(
|
async function replyInTopic(
|
||||||
ctx: Context,
|
ctx: Context,
|
||||||
text: string,
|
text: string,
|
||||||
replyMarkup?: InlineKeyboardMarkup
|
replyMarkup?: InlineKeyboardMarkup,
|
||||||
|
options?: {
|
||||||
|
parseMode?: 'HTML'
|
||||||
|
}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const message = ctx.msg
|
const message = ctx.msg
|
||||||
if (!ctx.chat || !message) {
|
if (!ctx.chat || !message) {
|
||||||
@@ -286,6 +301,11 @@ async function replyInTopic(
|
|||||||
? {
|
? {
|
||||||
reply_markup: replyMarkup as InlineKeyboardMarkup
|
reply_markup: replyMarkup as InlineKeyboardMarkup
|
||||||
}
|
}
|
||||||
|
: {}),
|
||||||
|
...(options?.parseMode
|
||||||
|
? {
|
||||||
|
parse_mode: options.parseMode
|
||||||
|
}
|
||||||
: {})
|
: {})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -481,14 +501,14 @@ export function registerReminderTopicUtilities(options: {
|
|||||||
await ctx.answerCallbackQuery({
|
await ctx.answerCallbackQuery({
|
||||||
text: t.templateToast
|
text: t.templateToast
|
||||||
})
|
})
|
||||||
await replyInTopic(
|
const template = buildTemplateText(
|
||||||
ctx,
|
|
||||||
buildTemplateText(
|
|
||||||
reminderContext.locale,
|
reminderContext.locale,
|
||||||
reminderContext.currency,
|
reminderContext.currency,
|
||||||
reminderContext.categories
|
reminderContext.categories
|
||||||
)
|
)
|
||||||
)
|
await replyInTopic(ctx, template.text, undefined, {
|
||||||
|
parseMode: template.parseMode
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
options.bot.callbackQuery(REMINDER_UTILITY_GUIDED_CALLBACK, async (ctx) => {
|
options.bot.callbackQuery(REMINDER_UTILITY_GUIDED_CALLBACK, async (ctx) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user