Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: fixed receiving sessions for users #33

Merged
merged 9 commits into from
May 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
OPEN_AI_TOKEN=
TELEGRAM_TOKEN=
MONGODB_URI=
OPEN_AI_ORG=
OPEN_AI_TOKEN=
SUPER_ADMIN_USERNAME=
TELEGRAM_TOKEN=
8 changes: 6 additions & 2 deletions src/callbacks/admin/sessions.callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ export const getUserSessionMessagesCallback = async (username: string, ctx: BotC
} catch (error) {
await ctx.reply(ctx.t('error-common'));

logger.error(`callbacks::sessions::getUserSessionMessages::${(error as Error).message}`);
logger.error(
`callbacks::sessions::getUserSessionMessagesCallback::${(error as Error).message}`,
);
}
};

Expand All @@ -37,6 +39,8 @@ export const deleteUserSessionMessagesCallback = async (username: string, ctx: B
} catch (error) {
await ctx.reply(ctx.t('error-common'));

logger.error(`callbacks::sessions::deleteUserSessionMessages::${(error as Error).message}`);
logger.error(
`callbacks::sessions::deleteUserSessionMessagesCallback::${(error as Error).message}`,
);
}
};
59 changes: 59 additions & 0 deletions src/callbacks/admin/user-conversations.callback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { adminInlineGoToMainMenu } from '@bot/menu';
import { csv, logger, mongo } from '@bot/services';
import { BotContextType } from '@bot/types';
import { removeFile, uniqBy } from '@bot/utils';

export const getUserConversationMessagesCallback = async (
username: string,
ctx: BotContextType,
) => {
try {
const userSession = await mongo.getUserSession(username);
const userConversation = await mongo.getUserConversation(username);

const messages = uniqBy(
[...userConversation?.messages, ...userSession?.value?.messages],
'timestamp',
);

if (userSession) {
const { filePath, filePathForReply } =
(await csv.createSessionCsv({ key: userSession.key, value: { username, messages } })) ?? {};

if (filePath && filePathForReply) {
await ctx.deleteMessage();
await ctx.replyWithDocument(filePathForReply, {
reply_markup: adminInlineGoToMainMenu(ctx),
});

await removeFile(filePath);
}
}
} catch (error) {
await ctx.reply(ctx.t('error-common'));

logger.error(
`callbacks::sessions::getUserConversationMessagesCallback::${(error as Error).message}`,
);
}
};

export const deleteUserConversationMessagesCallback = async (
username: string,
ctx: BotContextType,
) => {
try {
await mongo.deleteUserConversation(username);

await ctx.deleteMessage();
await ctx.reply(ctx.t('admin-delete-conversation-successful', { username }), {
reply_markup: adminInlineGoToMainMenu(ctx),
});
} catch (error) {
await ctx.reply(ctx.t('error-common'));

logger.error(
`callbacks::sessions::deleteUserConversationMessagesCallback::${(error as Error).message}`,
);
}
};
1 change: 1 addition & 0 deletions src/callbacks/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './admin/logs.callback';
export * from './admin/sessions.callback';
export * from './admin/user-conversations.callback';
export * from './admin/users.callback';
17 changes: 3 additions & 14 deletions src/composers/menu.composer.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
import {
adminDynamicUsersForDeleteSessionsMenu,
adminDynamicUsersForSessionsMenu,
adminDynamicUsersMenu,
adminMainMenu,
adminSessionsMenu,
adminUsersMenu,
} from '@bot/menu';
import { adminMenu, adminSubMenu } 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(adminDynamicUsersMenu);
adminMainMenu.register(adminDynamicUsersForSessionsMenu);
adminMainMenu.register(adminDynamicUsersForDeleteSessionsMenu);
adminSubMenu.forEach((subMenu) => adminMenu.register(subMenu));

composer.use(adminMainMenu);
composer.use(adminMenu);

export const menuComposer = (): Middleware<BotContextType> => composer;
5 changes: 3 additions & 2 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ dotenv.config({
});

export const config = {
TELEGRAM_TOKEN: process.env.TELEGRAM_TOKEN ?? '',
OPEN_AI_TOKEN: process.env.OPEN_AI_TOKEN ?? '',
MONGODB_URI: process.env.MONGODB_URI ?? '',
OPEN_AI_ORG: process.env.OPEN_AI_ORG ?? '',
OPEN_AI_TOKEN: process.env.OPEN_AI_TOKEN ?? '',
SUPER_ADMIN_USERNAME: process.env.SUPER_ADMIN_USERNAME ?? '',
TELEGRAM_TOKEN: process.env.TELEGRAM_TOKEN ?? '',
};
27 changes: 25 additions & 2 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ export enum UserRoles {
export const ADD_USER_FORMAT = '<username>;<admin | user | moderator>';

// Regexp
export const REGEXP_USERNAME = /^[a-z0-9_-]{3,16}$/;
export const REGEXP_USERNAME = /^[a-z0-9_-]{3,32}$/;

// Normalize
export const MAX_SESSION_MESSAGES = 30;
export const MAX_SESSION_MESSAGES = 15;
export const CUT_NUMBER_OF_SESSION_MESSAGES_TAIL = 5;

// CSV files
export const CSV_READER_URL = 'https://www.convertcsv.com/csv-viewer-editor.htm';
Expand All @@ -70,3 +71,25 @@ export enum LoggerInfoCsvIds {
MESSAGE = 'message',
TIMESTAMP = 'timestamp',
}

// Winston logger
export const winstonConfig = {
levels: {
error: 0,
debug: 1,
warn: 2,
data: 3,
info: 4,
verbose: 5,
silly: 6,
},
colors: {
error: 'red',
debug: 'blue',
warn: 'yellow',
data: 'magenta',
info: 'green',
verbose: 'cyan',
silly: 'grey',
},
};
6 changes: 3 additions & 3 deletions src/controllers/admin/admin.controller.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { BotCommands } from '@bot/constants';
import { adminMainMenu } from '@bot/menu';
import { adminMenu } from '@bot/menu';
import { BotType } from '@bot/types';

export const adminController = async (bot: BotType) => {
bot.callbackQuery('admin-go-to-main-action', async (ctx) => {
await ctx.deleteMessage();
await ctx.conversation.exit('addUserConversation');
await ctx.reply(ctx.t('admin-initial'), { reply_markup: adminMainMenu });
await ctx.reply(ctx.t('admin-initial'), { reply_markup: adminMenu });
});

bot.callbackQuery('admin-add-new-user-action', async (ctx) => {
Expand All @@ -15,6 +15,6 @@ export const adminController = async (bot: BotType) => {
});

return bot.command(BotCommands.ADMIN, async (ctx) => {
await ctx.reply(ctx.t('admin-initial'), { reply_markup: adminMainMenu });
await ctx.reply(ctx.t('admin-initial'), { reply_markup: adminMenu });
});
};
5 changes: 5 additions & 0 deletions src/locales/en.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,8 @@ admin-block-unblock-user-refresh = 🔄 Refresh
admin-enter-user = Enter user following next format: { $inputFormat }.
admin-logs = Logs
admin-csv-reader = CSV Reader
admin-conversations = Conversations
admin-get-conversations = Get conversation
admin-delete-conversations = Delete conversation
admin-delete-conversation-successful = Conversation for { $username } has been deleted.

5 changes: 5 additions & 0 deletions src/locales/ru.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,8 @@ admin-block-unblock-user-refresh = 🔄 Обновить
admin-enter-user = Введите пользовтеля в следующем формате: { $inputFormat }.
admin-logs = Логи
admin-csv-reader = CSV Считыватель
admin-conversations = Беседы
admin-get-conversations = Получить беседу
admin-delete-conversations = Удалить беседу
admin-delete-conversation-successful = Беседа для { $username } была удалена.

120 changes: 69 additions & 51 deletions src/menu/admin/admin.menu.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {
addUserInitialCallback,
blockUnblockUserCallback,
deleteUserConversationMessagesCallback,
deleteUserSessionMessagesCallback,
downloadLogsCallback,
getAllUsersCallback,
getUserConversationMessagesCallback,
getUserSessionMessagesCallback,
} from '@bot/callbacks';
import { CSV_READER_URL } from '@bot/constants';
Expand All @@ -13,12 +15,18 @@ import { isDocumentsTheSame } from '@bot/utils';
import { Menu, MenuRange } from '@grammyjs/menu';
import { InlineKeyboard } from 'grammy';

export const adminInlineGoToMainMenu = (ctx: BotContextType) =>
new InlineKeyboard().text(ctx.t('admin-go-to-main'), 'admin-go-to-main-action');

export const adminInlineAddNewUser = (ctx: BotContextType) =>
new InlineKeyboard().text(ctx.t('error-common-try-again'), 'admin-add-new-user-action');

export const dynamicUsersMenuRange = async (
ctx: BotContextType,
callback: (username: string, ctx: BotContextType) => void,
) => {
const range = new MenuRange<BotContextType>();
const currentUsername = ctx?.update?.callback_query?.from?.username ?? '';
const currentUsername = ctx?.from?.username ?? '';

let users: UserModelType[] = await mongo.getUsers();

Expand Down Expand Up @@ -52,7 +60,7 @@ export const dynamicUsersWithSessionMenuRange = async (
showCurrentUsername = true,
) => {
const range = new MenuRange<BotContextType>();
const currentUsername = ctx?.update?.callback_query?.from?.username ?? '';
const currentUsername = ctx?.from?.username ?? '';

const allUserSessions: SessionModelType[] = await mongo.getAllUserSessions();

Expand All @@ -67,16 +75,17 @@ export const dynamicUsersWithSessionMenuRange = async (
return range;
};

export const adminMainMenu = new Menu<BotContextType>('admin-main-menu')
export const adminMenu = new Menu<BotContextType>('admin-main-menu')
.submenu((ctx) => ctx.t('admin-sessions'), 'admin-sessions-menu')
.submenu((ctx) => ctx.t('admin-users'), 'admin-users-menu')
.submenu((ctx) => ctx.t('admin-conversations'), 'admin-conversations-menu')
.row()
.submenu((ctx) => ctx.t('admin-users'), 'admin-users-menu')
.text(
(ctx) => ctx.t('admin-logs'),
(ctx) => downloadLogsCallback(ctx),
)
.url((ctx) => ctx.t('admin-csv-reader'), CSV_READER_URL)
.row()
.url((ctx) => ctx.t('admin-csv-reader'), CSV_READER_URL)
.text(
(ctx) => ctx.t('admin-go-to-bot'),
async (ctx) => {
Expand All @@ -85,49 +94,58 @@ export const adminMainMenu = new Menu<BotContextType>('admin-main-menu')
},
);

export const adminSessionsMenu = new Menu<BotContextType>('admin-sessions-menu')
.submenu((ctx) => ctx.t('admin-get-session'), 'admin-dynamic-users-for-sessions-menu')
.submenu((ctx) => ctx.t('admin-delete-session'), 'admin-dynamic-users-for-delete-sessions-menu')
.row()
.back((ctx) => ctx.t('admin-go-back'));

export const adminUsersMenu = new Menu<BotContextType>('admin-users-menu')
.text(
(ctx) => ctx.t('admin-get-all-users'),
(ctx) => getAllUsersCallback(ctx),
)
.row()
.text(
(ctx) => ctx.t('admin-add-user'),
(ctx) => addUserInitialCallback(ctx),
)
.row()
.submenu((ctx) => ctx.t('admin-block-unblock-user'), 'admin-dynamic-users-menu')
.row()
.back((ctx) => ctx.t('admin-go-back'));

export const adminDynamicUsersMenu = new Menu<BotContextType>('admin-dynamic-users-menu', {
onMenuOutdated: false,
})
.dynamic(async (ctx) => dynamicUsersMenuRange(ctx, blockUnblockUserCallback))
.back((ctx) => ctx.t('admin-cancel'));

export const adminDynamicUsersForSessionsMenu = new Menu<BotContextType>(
'admin-dynamic-users-for-sessions-menu',
)
.dynamic(async (ctx) => dynamicUsersWithSessionMenuRange(ctx, getUserSessionMessagesCallback))
.back((ctx) => ctx.t('admin-cancel'));

export const adminDynamicUsersForDeleteSessionsMenu = new Menu<BotContextType>(
'admin-dynamic-users-for-delete-sessions-menu',
)
.dynamic(async (ctx) =>
dynamicUsersWithSessionMenuRange(ctx, deleteUserSessionMessagesCallback, false),
)
.back((ctx) => ctx.t('admin-cancel'));

export const adminInlineGoToMainMenu = (ctx: BotContextType) =>
new InlineKeyboard().text(ctx.t('admin-go-to-main'), 'admin-go-to-main-action');

export const adminInlineAddNewUser = (ctx: BotContextType) =>
new InlineKeyboard().text(ctx.t('error-common-try-again'), 'admin-add-new-user-action');
export const adminSubMenu = [
new Menu<BotContextType>('admin-sessions-menu')
.submenu((ctx) => ctx.t('admin-get-session'), 'admin-dynamic-users-for-sessions-menu')
.submenu((ctx) => ctx.t('admin-delete-session'), 'admin-dynamic-users-for-delete-sessions-menu')
.row()
.back((ctx) => ctx.t('admin-go-back')),
new Menu<BotContextType>('admin-users-menu')
.text(
(ctx) => ctx.t('admin-get-all-users'),
(ctx) => getAllUsersCallback(ctx),
)
.row()
.text(
(ctx) => ctx.t('admin-add-user'),
(ctx) => addUserInitialCallback(ctx),
)
.row()
.submenu((ctx) => ctx.t('admin-block-unblock-user'), 'admin-dynamic-users-menu')
.row()
.back((ctx) => ctx.t('admin-go-back')),
new Menu<BotContextType>('admin-conversations-menu')
.submenu(
(ctx) => ctx.t('admin-get-conversations'),
'admin-dynamic-users-for-conversations-menu',
)
.submenu(
(ctx) => ctx.t('admin-delete-conversations'),
'admin-dynamic-users-for-delete-conversations-menu',
)
.row()
.back((ctx) => ctx.t('admin-go-back')),
new Menu<BotContextType>('admin-dynamic-users-menu', {
onMenuOutdated: false,
})
.dynamic(async (ctx) => dynamicUsersMenuRange(ctx, blockUnblockUserCallback))
.back((ctx) => ctx.t('admin-cancel')),
new Menu<BotContextType>('admin-dynamic-users-for-sessions-menu')
.dynamic(async (ctx) => dynamicUsersWithSessionMenuRange(ctx, getUserSessionMessagesCallback))
.back((ctx) => ctx.t('admin-cancel')),
new Menu<BotContextType>('admin-dynamic-users-for-delete-sessions-menu')
.dynamic(async (ctx) =>
dynamicUsersWithSessionMenuRange(ctx, deleteUserSessionMessagesCallback, false),
)
.back((ctx) => ctx.t('admin-cancel')),
new Menu<BotContextType>('admin-dynamic-users-for-conversations-menu')
.dynamic(async (ctx) =>
dynamicUsersWithSessionMenuRange(ctx, getUserConversationMessagesCallback),
)
.back((ctx) => ctx.t('admin-cancel')),
new Menu<BotContextType>('admin-dynamic-users-for-delete-conversations-menu')
.dynamic(async (ctx) =>
dynamicUsersWithSessionMenuRange(ctx, deleteUserConversationMessagesCallback, false),
)
.back((ctx) => ctx.t('admin-cancel')),
];
Loading