Skip to content

Commit

Permalink
chore: added composers (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikita-kandratsyeu authored May 15, 2023
1 parent b6319c9 commit 68825f3
Show file tree
Hide file tree
Showing 27 changed files with 146 additions and 95 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
OPEN_AI_TOKEN=
TELEGRAM_TOKEN=
MONGODB_URI=
MONGODB_URI=
SUPER_ADMIN_USERNAME=
88 changes: 10 additions & 78 deletions src/bot.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { conversationComposer, menuComposer, sessionComposer } from '@bot/composers';
import { config } from '@bot/config';
import { gptModel, supportLanguageCodes } from '@bot/constants';
import {
aboutController,
adminController,
Expand All @@ -9,94 +9,26 @@ import {
textController,
voiceController,
} from '@bot/controllers';
import { addUserConversation } from '@bot/conversations';
import { createInitialSessionData, mapBotCommands, mapBotDescription } from '@bot/helpers';
import {
adminDynamicUsersForDeleteSessionsMenu,
adminDynamicUsersForSessionsMenu,
adminDynamicUsersMenu,
adminLogsMenu,
adminMainMenu,
adminSessionsMenu,
adminUsersMenu,
} from '@bot/menu';
import { handleBotError } from '@bot/helpers';
import { auth, normalize } from '@bot/middlewares';
import { logger, mongo } from '@bot/services';
import { BotContextType } from '@bot/types';
import { conversations, createConversation } from '@grammyjs/conversations';
import { I18n } from '@grammyjs/i18n';
import { Bot, BotError, GrammyError, HttpError, session } from 'grammy';
import path from 'path';

const handleBotError = (error: BotError) => {
const ctx = error.ctx;
const err = error.error;

logger.error(`botInitialize::error while handling update::${ctx.update.update_id}:`);
import { i18nComposer } from 'composers/i18n.composer';
import { Bot } from 'grammy';

if (err instanceof GrammyError) {
logger.error(`botInitialize::error in request::${err.description}`);
} else if (err instanceof HttpError) {
logger.error(`botInitialize::could not contact Telegram::${err.message}`);
} else {
logger.error(`botInitialize::unknown error::${(err as Error).message}`);
}
};

export const createBot = async () => {
export const createBot = () => {
const bot = new Bot<BotContextType>(config.TELEGRAM_TOKEN);

const i18n = new I18n<BotContextType>({
defaultLocale: 'en',
globalTranslationContext: (ctx) => ({
botName: ctx?.me?.first_name ?? '',
firstName: ctx?.from?.first_name ?? '',
model: gptModel,
username: ctx?.from?.username ?? '',
}),
directory: path.join(__dirname, './locales'),
useSession: true,
});

supportLanguageCodes.forEach(async (languageCode) => {
await bot.api.setMyDescription(mapBotDescription(i18n, languageCode), {
language_code: languageCode,
});
bot.use(i18nComposer());

await bot.api.setMyCommands(mapBotCommands(i18n, languageCode), {
language_code: languageCode,
});
});
bot.use(sessionComposer());

adminMainMenu.register(adminSessionsMenu);
adminMainMenu.register(adminUsersMenu);
adminMainMenu.register(adminLogsMenu);
adminMainMenu.register(adminDynamicUsersMenu);
adminMainMenu.register(adminDynamicUsersForSessionsMenu);
adminMainMenu.register(adminDynamicUsersForDeleteSessionsMenu);
bot.use(conversationComposer());

bot.use(i18n);

bot.use(
session({
type: 'multi',
custom: {
storage: mongo.sessionAdapter,
initial: createInitialSessionData,
},
conversation: {},
}),
);

bot.use(auth());
bot.use(menuComposer());

bot.use(normalize());

bot.use(conversations());

bot.use(createConversation(addUserConversation));

bot.use(adminMainMenu);
bot.use(auth());

[
aboutController,
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions src/callbacks/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './admin/logs.callbacks';
export * from './admin/sessions.callbacks';
export * from './admin/users.callbacks';
export * from './admin/logs.callback';
export * from './admin/sessions.callback';
export * from './admin/users.callback';
12 changes: 12 additions & 0 deletions src/composers/conversation.composer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { addUserConversation } from '@bot/conversations';
import { BotContextType } from '@bot/types';
import { conversations, createConversation } from '@grammyjs/conversations';
import { Composer, Middleware } from 'grammy';

const composer = new Composer<BotContextType>();

composer.use(conversations());

composer.use(createConversation(addUserConversation));

export const conversationComposer = (): Middleware<BotContextType> => composer;
37 changes: 37 additions & 0 deletions src/composers/i18n.composer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { config } from '@bot/config';
import { gptModel, supportLanguageCodes } from '@bot/constants';
import { mapBotCommands, mapBotDescription } from '@bot/helpers';
import { BotContextType } from '@bot/types';
import { I18n } from '@grammyjs/i18n';
import { Api, Composer, Middleware } from 'grammy';
import path from 'path';

const api = new Api(config.TELEGRAM_TOKEN);

const composer = new Composer<BotContextType>();

const i18n = new I18n<BotContextType>({
defaultLocale: 'en',
globalTranslationContext: (ctx) => ({
botName: ctx?.me?.first_name ?? '',
firstName: ctx?.from?.first_name ?? '',
model: gptModel,
username: ctx?.from?.username ?? '',
}),
directory: path.join(__dirname, '../locales'),
useSession: true,
});

supportLanguageCodes.forEach(async (languageCode) => {
await api.setMyDescription(mapBotDescription(i18n, languageCode), {
language_code: languageCode,
});

await api.setMyCommands(mapBotCommands(i18n, languageCode), {
language_code: languageCode,
});
});

composer.use(i18n);

export const i18nComposer = (): Middleware<BotContextType> => composer;
3 changes: 3 additions & 0 deletions src/composers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './conversation.composer';
export * from './menu.composer';
export * from './session.composer';
24 changes: 24 additions & 0 deletions src/composers/menu.composer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {
adminDynamicUsersForDeleteSessionsMenu,
adminDynamicUsersForSessionsMenu,
adminDynamicUsersMenu,
adminLogsMenu,
adminMainMenu,
adminSessionsMenu,
adminUsersMenu,
} from '@bot/menu';
import { BotContextType } from '@bot/types';
import { Composer, Middleware } from 'grammy';

const composer = new Composer<BotContextType>();

adminMainMenu.register(adminSessionsMenu);
adminMainMenu.register(adminUsersMenu);
adminMainMenu.register(adminLogsMenu);
adminMainMenu.register(adminDynamicUsersMenu);
adminMainMenu.register(adminDynamicUsersForSessionsMenu);
adminMainMenu.register(adminDynamicUsersForDeleteSessionsMenu);

composer.use(adminMainMenu);

export const menuComposer = (): Middleware<BotContextType> => composer;
19 changes: 19 additions & 0 deletions src/composers/session.composer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createInitialSessionData } from '@bot/helpers';
import { mongo } from '@bot/services';
import { BotContextType } from '@bot/types';
import { Composer, Middleware, session } from 'grammy';

const composer = new Composer<BotContextType>();

composer.use(
session({
type: 'multi',
custom: {
storage: mongo.sessionAdapter,
initial: createInitialSessionData,
},
conversation: {},
}),
);

export const sessionComposer = (): Middleware<BotContextType> => composer;
1 change: 1 addition & 0 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export const config = {
TELEGRAM_TOKEN: process.env.TELEGRAM_TOKEN ?? '',
OPEN_AI_TOKEN: process.env.OPEN_AI_TOKEN ?? '',
MONGODB_URI: process.env.MONGODB_URI ?? '',
SUPER_ADMIN_USERNAME: process.env.SUPER_ADMIN_USERNAME ?? '',
};
2 changes: 1 addition & 1 deletion src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export enum MessageRoles {
// Telegram API
export const telegramApi = 'https://api.telegram.org';

// Bot
// Bot config
export const supportLanguageCodes = ['en', 'ru'];

export enum BotCommands {
Expand Down
File renamed without changes.
File renamed without changes.
11 changes: 6 additions & 5 deletions src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './api.helpers';
export * from './gpt.helpers';
export * from './lang.helpers';
export * from './session.helpers';
export * from './user.helpers';
export * from './api.helper';
export * from './gpt.helper';
export * from './lang.helper';
export * from './logger.helper';
export * from './session.helper';
export * from './user.helper';
File renamed without changes.
17 changes: 17 additions & 0 deletions src/helpers/logger.helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { logger } from '@bot/services';
import { BotError, GrammyError, HttpError } from 'grammy';

export const handleBotError = (error: BotError) => {
const ctx = error.ctx;
const err = error.error;

logger.error(`botInitialize::error while handling update::${ctx.update.update_id}:`);

if (err instanceof GrammyError) {
logger.error(`botInitialize::error in request::${err.description}`);
} else if (err instanceof HttpError) {
logger.error(`botInitialize::could not contact Telegram::${err.message}`);
} else {
logger.error(`botInitialize::unknown error::${(err as Error).message}`);
}
};
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import mongoose from 'mongoose';
const botInitialize = async () => {
await mongoose.connect(config.MONGODB_URI);

const bot = await createBot();
const bot = createBot();

run(bot);

Expand Down
8 changes: 6 additions & 2 deletions src/middlewares/auth.middleware.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { config } from '@bot/config';
import { UserRoles } from '@bot/constants';
import { mongo } from '@bot/services';
import { BotContextType, GrammyMiddlewareFn } from '@bot/types';

export const auth = (): GrammyMiddlewareFn<BotContextType> => async (ctx, next) => {
const username =
ctx?.update?.message?.from?.username ?? ctx?.update?.callback_query?.from?.username ?? '';
const username = ctx?.from?.username ?? '';
const action = ctx?.update?.message?.text ?? '';

if (username === config.SUPER_ADMIN_USERNAME) {
return next();
}

const user = await mongo.getUser(username);

if (user?.enabled) {
Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from './bot.types';
export * from './middleware.types';
export * from './model.types';
export * from './service.types';
export * from './bot.type';
export * from './middleware.type';
export * from './model.type';
export * from './service.type';
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 68825f3

Please sign in to comment.