apps/bot: add feature add contact

This commit is contained in:
vchikalkin 2025-01-10 18:35:06 +03:00
parent f4377f160f
commit d723758704
6 changed files with 126 additions and 42 deletions

8
apps/bot/src/api.ts Normal file
View File

@ -0,0 +1,8 @@
import * as api from '@repo/graphql/api';
export async function getCustomer(telegramId: number) {
const response = await api.getCustomer({ telegramId });
const customer = response?.data?.customers?.at(0);
return customer;
}

View File

@ -1,61 +1,79 @@
/* eslint-disable consistent-return */
import { getCustomer } from './api';
import { env as environment } from './config/env';
import { createCustomer, getCustomer } from '@repo/graphql/api';
import { commandsList, KEYBOARD_REMOVE, KEYBOARD_SHARE_PHONE } from './message';
import { createClient, createCustomer } from '@repo/graphql/api';
import { Telegraf } from 'telegraf';
import { message } from 'telegraf/filters';
const bot = new Telegraf(environment.BOT_TOKEN);
bot.start(async (context) => {
const { id: telegramId } = context.from;
const customer = await getCustomer(context.from.id);
const response = await getCustomer({ telegramId });
const customer = response?.data?.customers?.at(0);
if (customer && !response.error) {
if (customer) {
return context.reply(
`Приветствуем снова, ${customer.name}. Чтобы воспользоваться сервисом, откройте приложение.`,
{
reply_markup: {
remove_keyboard: true,
},
},
`Приветствуем снова, ${customer.name} 👋.
Чтобы воспользоваться сервисом, откройте приложение.` + commandsList,
KEYBOARD_REMOVE,
);
}
return context.reply('Добро пожаловать! Пожалуйста, поделитесь своим номером телефона.', {
reply_markup: {
keyboard: [
[
{
request_contact: true,
text: 'Отправить номер телефона',
},
],
],
one_time_keyboard: true,
},
});
return context.reply(
'Добро пожаловать! Пожалуйста, поделитесь своим номером телефона.',
KEYBOARD_SHARE_PHONE,
);
});
bot.command('addcontact', async (context) => {
const customer = await getCustomer(context.from.id);
if (!customer) {
return context.reply(
'Чтобы добавить контакт, поделитесь своим номером телефона.',
KEYBOARD_SHARE_PHONE,
);
}
return context.reply('Отправьте контакт клиента, которого вы хотите добавить');
});
bot.on(message('contact'), async (context) => {
const response = await createCustomer({
name: context.from.first_name,
phone: context.message.contact.phone_number,
telegramId: context.from.id,
});
const customer = await getCustomer(context.from.id);
if (response.errors?.length) {
return context.reply('Произошла ошибка, попробуйте позже.');
const isRegistration = !customer;
if (isRegistration) {
const response = await createCustomer({
name: context.from.first_name,
phone: context.message.contact.phone_number,
telegramId: context.from.id,
}).catch((error) => {
context.reply('Произошла ошибка, попробуйте позже.' + error);
});
if (response) {
return context.reply(
`Спасибо! Мы сохранили ваш номер телефона. Теперь можете открыть приложение или воспользоваться командами бота.` +
commandsList,
KEYBOARD_REMOVE,
);
}
} else {
const { contact } = context.message;
const name = (contact.first_name || '') + ' ' + (contact.last_name || '').trim();
const phone = contact.phone_number;
const response = await createClient({ name, phone }).catch((error) => {
context.reply('Произошла ошибка, попробуйте позже.\n' + error);
});
if (response) {
return context.reply(
`Добавили контакт ${name}. Теперь вы можете добавить запись с ним в приложении.`,
);
}
}
return context.reply(
'Спасибо! Мы сохранили ваш номер телефона. Теперь можете открыть приложение.',
{
reply_markup: {
remove_keyboard: true,
},
},
);
});
bot.launch();

26
apps/bot/src/message.ts Normal file
View File

@ -0,0 +1,26 @@
import { type ReplyKeyboardRemove } from 'telegraf/types';
export const commandsList = `
\оступные команды:
/addcontact - Добавить контакт клиента
`;
export const KEYBOARD_SHARE_PHONE = {
reply_markup: {
keyboard: [
[
{
request_contact: true,
text: 'Отправить номер телефона',
},
],
],
one_time_keyboard: true,
},
};
export const KEYBOARD_REMOVE = {
reply_markup: {
remove_keyboard: true,
} as ReplyKeyboardRemove,
};

View File

@ -1,4 +1,4 @@
'use server';
'use server';;
import { getClientWithToken } from '../apollo/client';
import * as GQL from '../types';
@ -11,6 +11,23 @@ export async function createCustomer(variables: GQL.CreateCustomerMutationVariab
});
}
export async function createClient(variables: GQL.CreateClientMutationVariables) {
const { mutate } = await getClientWithToken();
const response = mutate({
mutation: GQL.CreateClientDocument,
variables,
}).catch((error) => {
const isContactAlreadyExists = JSON.stringify(error).includes('This attribute must be unique');
if (isContactAlreadyExists) throw new Error('Contact already exists');
throw error;
});
return response;
}
export async function getCustomer(variables: GQL.GetCustomerQueryVariables) {
const { query } = await getClientWithToken();

View File

@ -14,6 +14,12 @@ mutation CreateCustomer($name: String!, $telegramId: Long!, $phone: String!) {
}
}
mutation CreateClient($name: String!, $phone: String!) {
createCustomer(data: { name: $name, phone: $phone, role: client }) {
...CustomerProfile
}
}
query GetCustomer($telegramId: Long!) {
customers(filters: { telegramId: { eq: $telegramId } }) {
...CustomerProfile

View File

@ -578,6 +578,14 @@ export type CreateCustomerMutationVariables = Exact<{
export type CreateCustomerMutation = { __typename?: 'Mutation', createCustomer?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: any | null | undefined } | null | undefined };
export type CreateClientMutationVariables = Exact<{
name: Scalars['String']['input'];
phone: Scalars['String']['input'];
}>;
export type CreateClientMutation = { __typename?: 'Mutation', createCustomer?: { __typename?: 'Customer', active?: boolean | null | undefined, documentId: string, name: string, phone: string, photoUrl?: string | null | undefined, role: Enum_Customer_Role, telegramId?: any | null | undefined } | null | undefined };
export type GetCustomerQueryVariables = Exact<{
telegramId: Scalars['Long']['input'];
}>;
@ -597,5 +605,6 @@ export const CustomerProfileFragmentDoc = {"kind":"Document","definitions":[{"ki
export const RegisterDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"Register"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"identifier"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"password"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"email"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"register"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"username"},"value":{"kind":"Variable","name":{"kind":"Name","value":"identifier"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"password"},"value":{"kind":"Variable","name":{"kind":"Name","value":"password"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"email"},"value":{"kind":"Variable","name":{"kind":"Name","value":"email"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"jwt"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"username"}}]}}]}}]}}]} as unknown as DocumentNode<RegisterMutation, RegisterMutationVariables>;
export const LoginDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"Login"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"identifier"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"password"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"login"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"identifier"},"value":{"kind":"Variable","name":{"kind":"Name","value":"identifier"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"password"},"value":{"kind":"Variable","name":{"kind":"Name","value":"password"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"jwt"}}]}}]}}]} as unknown as DocumentNode<LoginMutation, LoginMutationVariables>;
export const CreateCustomerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateCustomer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Long"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"phone"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createCustomer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"telegramId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"phone"},"value":{"kind":"Variable","name":{"kind":"Name","value":"phone"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"role"},"value":{"kind":"EnumValue","value":"client"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerProfile"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerProfile"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode<CreateCustomerMutation, CreateCustomerMutationVariables>;
export const CreateClientDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateClient"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"phone"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createCustomer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"phone"},"value":{"kind":"Variable","name":{"kind":"Name","value":"phone"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"role"},"value":{"kind":"EnumValue","value":"client"}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerProfile"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerProfile"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode<CreateClientMutation, CreateClientMutationVariables>;
export const GetCustomerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetCustomer"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Long"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"customers"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filters"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"telegramId"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"eq"},"value":{"kind":"Variable","name":{"kind":"Name","value":"telegramId"}}}]}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerProfile"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerProfile"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode<GetCustomerQuery, GetCustomerQueryVariables>;
export const UpdateCustomerProfileDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateCustomerProfile"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CustomerInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateCustomer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"documentId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"documentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CustomerProfile"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CustomerProfile"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Customer"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"active"}},{"kind":"Field","name":{"kind":"Name","value":"documentId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"phone"}},{"kind":"Field","name":{"kind":"Name","value":"photoUrl"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"telegramId"}}]}}]} as unknown as DocumentNode<UpdateCustomerProfileMutation, UpdateCustomerProfileMutationVariables>;