refactor(bot): update conversation handling and middleware integration
- Replaced the previous conversations middleware with the Grammy framework's implementation. - Introduced a loop to register custom conversations, enhancing the bot's conversation management capabilities. - Removed the addContact feature implementation from the add-contact file, streamlining the codebase.
This commit is contained in:
parent
a2bbcbb107
commit
5671ad5b02
87
apps/bot/src/bot/conversations/add-contact.ts
Normal file
87
apps/bot/src/bot/conversations/add-contact.ts
Normal file
@ -0,0 +1,87 @@
|
||||
/* eslint-disable id-length */
|
||||
import { type Context } from '@/bot/context';
|
||||
import { KEYBOARD_REMOVE, KEYBOARD_SHARE_BOT, KEYBOARD_SHARE_PHONE } from '@/config/keyboards';
|
||||
import { isCustomerMaster } from '@/utils/customer';
|
||||
import { isValidPhoneNumber, normalizePhoneNumber } from '@/utils/phone';
|
||||
import { type Conversation } from '@grammyjs/conversations';
|
||||
import { CustomersService } from '@repo/graphql/api/customers';
|
||||
import { RegistrationService } from '@repo/graphql/api/registration';
|
||||
|
||||
export async function addContact(conversation: Conversation<Context, Context>, ctx: Context) {
|
||||
// Проверяем, что пользователь является мастером
|
||||
const telegramId = ctx.from?.id;
|
||||
if (!telegramId) {
|
||||
return ctx.reply(await conversation.external(({ t }) => t('err-generic')));
|
||||
}
|
||||
|
||||
const customerService = new CustomersService({ telegramId });
|
||||
const { customer } = await customerService.getCustomer({ telegramId });
|
||||
|
||||
if (!customer) {
|
||||
return ctx.reply(
|
||||
await conversation.external(({ t }) => t('msg-need-phone')),
|
||||
KEYBOARD_SHARE_PHONE,
|
||||
);
|
||||
}
|
||||
|
||||
if (!isCustomerMaster(customer)) {
|
||||
return ctx.reply(await conversation.external(({ t }) => t('msg-not-master')));
|
||||
}
|
||||
|
||||
// Просим отправить контакт клиента
|
||||
await ctx.reply(await conversation.external(({ t }) => t('msg-send-client-contact')));
|
||||
|
||||
// Ждем любое сообщение от пользователя
|
||||
const waitCtx = await conversation.wait();
|
||||
|
||||
// Проверяем команду отмены
|
||||
if (waitCtx.message?.text === '/cancel') {
|
||||
return ctx.reply(await conversation.external(({ t }) => t('msg-cancel')));
|
||||
}
|
||||
|
||||
// Проверяем, что отправлен контакт
|
||||
if (!waitCtx.message?.contact) {
|
||||
return ctx.reply(await conversation.external(({ t }) => t('msg-send-contact')));
|
||||
}
|
||||
|
||||
const { contact } = waitCtx.message;
|
||||
const name = `${contact.first_name || ''} ${contact.last_name || ''}`.trim();
|
||||
const phone = normalizePhoneNumber(contact.phone_number);
|
||||
|
||||
// Проверяем валидность номера телефона
|
||||
if (!isValidPhoneNumber(phone)) {
|
||||
return ctx.reply(await conversation.external(({ t }) => t('msg-invalid-phone')));
|
||||
}
|
||||
|
||||
try {
|
||||
// Проверяем, есть ли клиент с таким номером
|
||||
const { customer: existingCustomer } = await customerService.getCustomer({ phone });
|
||||
let documentId = existingCustomer?.documentId;
|
||||
|
||||
// Если клиента нет, создаём нового
|
||||
if (!documentId) {
|
||||
const registrationService = new RegistrationService();
|
||||
const createCustomerResult = await registrationService.createCustomer({ name, phone });
|
||||
|
||||
documentId = createCustomerResult?.createCustomer?.documentId;
|
||||
if (!documentId) throw new Error('Клиент не создан');
|
||||
}
|
||||
|
||||
// Добавляем текущего мастера к клиенту
|
||||
const masters = [customer.documentId];
|
||||
await customerService.addMasters({ data: { masters }, documentId });
|
||||
|
||||
// Отправляем подтверждения и инструкции
|
||||
await ctx.reply(await conversation.external(({ t }) => t('msg-contact-added', { name })));
|
||||
await ctx.reply(await conversation.external(({ t }) => t('msg-contact-forward')));
|
||||
await ctx.reply(await conversation.external(({ t }) => t('msg-share-bot')), KEYBOARD_SHARE_BOT);
|
||||
} catch (error) {
|
||||
await ctx.reply(
|
||||
await conversation.external(({ t }) => t('err-with-details', { error: String(error) })),
|
||||
);
|
||||
} finally {
|
||||
await ctx.reply(await conversation.external(({ t }) => t('commands-list')), KEYBOARD_REMOVE);
|
||||
}
|
||||
|
||||
return ctx.reply(await conversation.external(({ t }) => t('err-generic')), KEYBOARD_REMOVE);
|
||||
}
|
||||
1
apps/bot/src/bot/conversations/index.ts
Normal file
1
apps/bot/src/bot/conversations/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './add-contact';
|
||||
@ -1,99 +1,11 @@
|
||||
/* eslint-disable id-length */
|
||||
import { type Context } from '@/bot/context';
|
||||
import { logHandle } from '@/bot/helpers/logging';
|
||||
import { KEYBOARD_REMOVE, KEYBOARD_SHARE_BOT, KEYBOARD_SHARE_PHONE } from '@/config/keyboards';
|
||||
import { isCustomerMaster } from '@/utils/customer';
|
||||
import { isValidPhoneNumber, normalizePhoneNumber } from '@/utils/phone';
|
||||
import { type Conversation, createConversation } from '@grammyjs/conversations';
|
||||
import { CustomersService } from '@repo/graphql/api/customers';
|
||||
import { RegistrationService } from '@repo/graphql/api/registration';
|
||||
import { Composer } from 'grammy';
|
||||
|
||||
const composer = new Composer<Context>();
|
||||
|
||||
const feature = composer.chatType('private');
|
||||
|
||||
async function addContact(conversation: Conversation<Context, Context>, ctx: Context) {
|
||||
// Проверяем, что пользователь является мастером
|
||||
const telegramId = ctx.from?.id;
|
||||
if (!telegramId) {
|
||||
return ctx.reply(await conversation.external(({ t }) => t('err-generic')));
|
||||
}
|
||||
|
||||
const customerService = new CustomersService({ telegramId });
|
||||
const { customer } = await customerService.getCustomer({ telegramId });
|
||||
|
||||
if (!customer) {
|
||||
return ctx.reply(
|
||||
await conversation.external(({ t }) => t('msg-need-phone')),
|
||||
KEYBOARD_SHARE_PHONE,
|
||||
);
|
||||
}
|
||||
|
||||
if (!isCustomerMaster(customer)) {
|
||||
return ctx.reply(await conversation.external(({ t }) => t('msg-not-master')));
|
||||
}
|
||||
|
||||
// Просим отправить контакт клиента
|
||||
await ctx.reply(await conversation.external(({ t }) => t('msg-send-client-contact')));
|
||||
|
||||
// Ждем любое сообщение от пользователя
|
||||
const waitCtx = await conversation.wait();
|
||||
|
||||
// Проверяем команду отмены
|
||||
if (waitCtx.message?.text === '/cancel') {
|
||||
return ctx.reply(await conversation.external(({ t }) => t('msg-cancel')));
|
||||
}
|
||||
|
||||
// Проверяем, что отправлен контакт
|
||||
if (!waitCtx.message?.contact) {
|
||||
return ctx.reply(await conversation.external(({ t }) => t('msg-send-contact')));
|
||||
}
|
||||
|
||||
const { contact } = waitCtx.message;
|
||||
const name = `${contact.first_name || ''} ${contact.last_name || ''}`.trim();
|
||||
const phone = normalizePhoneNumber(contact.phone_number);
|
||||
|
||||
// Проверяем валидность номера телефона
|
||||
if (!isValidPhoneNumber(phone)) {
|
||||
return ctx.reply(await conversation.external(({ t }) => t('msg-invalid-phone')));
|
||||
}
|
||||
|
||||
try {
|
||||
// Проверяем, есть ли клиент с таким номером
|
||||
const { customer: existingCustomer } = await customerService.getCustomer({ phone });
|
||||
let documentId = existingCustomer?.documentId;
|
||||
|
||||
// Если клиента нет, создаём нового
|
||||
if (!documentId) {
|
||||
const registrationService = new RegistrationService();
|
||||
const createCustomerResult = await registrationService.createCustomer({ name, phone });
|
||||
|
||||
documentId = createCustomerResult?.createCustomer?.documentId;
|
||||
if (!documentId) throw new Error('Клиент не создан');
|
||||
}
|
||||
|
||||
// Добавляем текущего мастера к клиенту
|
||||
const masters = [customer.documentId];
|
||||
await customerService.addMasters({ data: { masters }, documentId });
|
||||
|
||||
// Отправляем подтверждения и инструкции
|
||||
await ctx.reply(await conversation.external(({ t }) => t('msg-contact-added', { name })));
|
||||
await ctx.reply(await conversation.external(({ t }) => t('msg-contact-forward')));
|
||||
await ctx.reply(await conversation.external(({ t }) => t('msg-share-bot')), KEYBOARD_SHARE_BOT);
|
||||
} catch (error) {
|
||||
await ctx.reply(
|
||||
await conversation.external(({ t }) => t('err-with-details', { error: String(error) })),
|
||||
);
|
||||
} finally {
|
||||
await ctx.reply(await conversation.external(({ t }) => t('commands-list')), KEYBOARD_REMOVE);
|
||||
}
|
||||
|
||||
return ctx.reply(await conversation.external(({ t }) => t('err-generic')), KEYBOARD_REMOVE);
|
||||
}
|
||||
|
||||
feature.use(createConversation(addContact));
|
||||
|
||||
feature.command('addcontact', logHandle('command-add-contact'), async (ctx) => {
|
||||
await ctx.conversation.enter('addContact');
|
||||
});
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { type Context } from './context';
|
||||
import * as conversations from './conversations';
|
||||
import * as features from './features';
|
||||
import { unhandledFeature } from './features/unhandled';
|
||||
import { errorHandler } from './handlers/errors';
|
||||
@ -9,7 +10,7 @@ import { setInfo } from './settings/info';
|
||||
import { env } from '@/config/env';
|
||||
import { getRedisInstance } from '@/utils/redis';
|
||||
import { autoChatAction } from '@grammyjs/auto-chat-action';
|
||||
import { conversations } from '@grammyjs/conversations';
|
||||
import { createConversation, conversations as grammyConversations } from '@grammyjs/conversations';
|
||||
import { hydrate } from '@grammyjs/hydrate';
|
||||
import { limit } from '@grammyjs/ratelimiter';
|
||||
import { Bot } from 'grammy';
|
||||
@ -37,7 +38,11 @@ export function createBot({ token }: Parameters_) {
|
||||
}),
|
||||
);
|
||||
|
||||
bot.use(conversations());
|
||||
bot.use(grammyConversations());
|
||||
|
||||
for (const conversation of Object.values(conversations)) {
|
||||
bot.use(createConversation(conversation));
|
||||
}
|
||||
|
||||
setInfo(bot);
|
||||
setCommands(bot);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user