From 95e06bc54a61153fa51dd2f4ede750117e445467 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Sat, 31 Jan 2026 00:51:52 +0530 Subject: [PATCH] Refactor Telegram MCP integration and add new API functionalities - Updated import paths for Telegram types and API functions to improve module organization. - Introduced new helper functions for reading typed values from MCP tool arguments. - Added comprehensive API functions for managing Telegram contacts, chats, and messages, including creating groups, channels, and polls. - Implemented a tool action parser to convert tool inputs into human-readable descriptions. - Added tests for new functionalities to ensure reliability and correctness. This update enhances the Telegram MCP server's capabilities and improves code maintainability. --- package-lock.json | 19 +++ package.json | 2 + src/__tests__/fixtures/mcpContext.ts | 6 +- src/lib/mcp/skills/bulk.ts | 19 +-- .../telegram/api/__tests__/getChats.test.ts | 41 ++++--- .../api/__tests__/getCurrentUser.test.ts | 24 ++-- .../api/__tests__/getMessages.test.ts | 32 +++-- .../telegram/api/__tests__/helpers.test.ts | 2 +- .../api/__tests__/sendMessage.test.ts | 20 ++-- src/lib/{mcp => }/telegram/api/addContact.ts | 6 +- .../{mcp => }/telegram/api/apiCastHelpers.ts | 0 .../{mcp => }/telegram/api/apiResultTypes.ts | 0 src/lib/{mcp => }/telegram/api/archiveChat.ts | 6 +- src/lib/{mcp => }/telegram/api/banUser.ts | 6 +- src/lib/{mcp => }/telegram/api/blockUser.ts | 6 +- src/lib/{mcp => }/telegram/api/clearDraft.ts | 10 +- .../{mcp => }/telegram/api/createChannel.ts | 6 +- src/lib/{mcp => }/telegram/api/createGroup.ts | 4 +- src/lib/{mcp => }/telegram/api/createPoll.ts | 12 +- .../{mcp => }/telegram/api/deleteChatPhoto.ts | 8 +- .../{mcp => }/telegram/api/deleteContact.ts | 8 +- .../{mcp => }/telegram/api/deleteMessage.ts | 8 +- .../telegram/api/deleteProfilePhoto.ts | 6 +- src/lib/{mcp => }/telegram/api/demoteAdmin.ts | 8 +- .../{mcp => }/telegram/api/editChatPhoto.ts | 0 .../{mcp => }/telegram/api/editChatTitle.ts | 8 +- src/lib/{mcp => }/telegram/api/editMessage.ts | 8 +- .../telegram/api/exportChatInvite.ts | 6 +- .../{mcp => }/telegram/api/exportContacts.ts | 6 +- .../{mcp => }/telegram/api/forwardMessage.ts | 4 +- src/lib/{mcp => }/telegram/api/getAdmins.ts | 10 +- .../{mcp => }/telegram/api/getBannedUsers.ts | 8 +- .../{mcp => }/telegram/api/getBlockedUsers.ts | 4 +- src/lib/{mcp => }/telegram/api/getBotInfo.ts | 6 +- src/lib/{mcp => }/telegram/api/getChat.ts | 16 +-- src/lib/{mcp => }/telegram/api/getChats.ts | 12 +- .../{mcp => }/telegram/api/getContactChats.ts | 4 +- .../{mcp => }/telegram/api/getContactIds.ts | 4 +- .../{mcp => }/telegram/api/getCurrentUser.ts | 6 +- .../telegram/api/getDirectChatByContact.ts | 8 +- src/lib/{mcp => }/telegram/api/getDrafts.ts | 2 +- .../{mcp => }/telegram/api/getGifSearch.ts | 6 +- .../{mcp => }/telegram/api/getInviteLink.ts | 6 +- .../telegram/api/getLastInteraction.ts | 0 .../{mcp => }/telegram/api/getMediaInfo.ts | 0 .../telegram/api/getMessageReactions.ts | 12 +- src/lib/{mcp => }/telegram/api/getMessages.ts | 14 +-- .../{mcp => }/telegram/api/getParticipants.ts | 8 +- .../telegram/api/getPinnedMessages.ts | 24 ++-- .../telegram/api/getPrivacySettings.ts | 10 +- .../telegram/api/getRecentActions.ts | 8 +- .../{mcp => }/telegram/api/getStickerSets.ts | 6 +- .../{mcp => }/telegram/api/getUserPhotos.ts | 10 +- .../{mcp => }/telegram/api/getUserStatus.ts | 6 +- src/lib/{mcp => }/telegram/api/helpers.ts | 32 ++--- .../telegram/api/importChatInvite.ts | 4 +- .../{mcp => }/telegram/api/importContacts.ts | 8 +- src/lib/{mcp => }/telegram/api/index.ts | 0 .../{mcp => }/telegram/api/inviteToGroup.ts | 8 +- .../{mcp => }/telegram/api/joinChatByLink.ts | 4 +- src/lib/{mcp => }/telegram/api/leaveChat.ts | 8 +- .../{mcp => }/telegram/api/listContacts.ts | 2 +- .../telegram/api/listInlineButtons.ts | 0 src/lib/{mcp => }/telegram/api/listTopics.ts | 8 +- src/lib/{mcp => }/telegram/api/markAsRead.ts | 8 +- src/lib/{mcp => }/telegram/api/muteChat.ts | 6 +- src/lib/{mcp => }/telegram/api/pinMessage.ts | 8 +- .../telegram/api/pressInlineButton.ts | 10 +- .../{mcp => }/telegram/api/promoteAdmin.ts | 8 +- .../{mcp => }/telegram/api/removeReaction.ts | 10 +- .../{mcp => }/telegram/api/resolveUsername.ts | 22 ++-- src/lib/{mcp => }/telegram/api/saveDraft.ts | 10 +- src/lib/{mcp => }/telegram/api/searchChats.ts | 4 +- .../{mcp => }/telegram/api/searchContacts.ts | 4 +- .../{mcp => }/telegram/api/searchMessages.ts | 10 +- .../telegram/api/searchPublicChats.ts | 10 +- src/lib/{mcp => }/telegram/api/sendMessage.ts | 8 +- .../{mcp => }/telegram/api/sendReaction.ts | 10 +- .../{mcp => }/telegram/api/setBotCommands.ts | 8 +- .../telegram/api/setPrivacySettings.ts | 8 +- .../{mcp => }/telegram/api/setProfilePhoto.ts | 0 .../telegram/api/subscribePublicChannel.ts | 6 +- src/lib/{mcp => }/telegram/api/types.ts | 0 .../{mcp => }/telegram/api/unarchiveChat.ts | 6 +- src/lib/{mcp => }/telegram/api/unbanUser.ts | 6 +- src/lib/{mcp => }/telegram/api/unblockUser.ts | 8 +- src/lib/{mcp => }/telegram/api/unmuteChat.ts | 6 +- .../{mcp => }/telegram/api/unpinMessage.ts | 10 +- .../{mcp => }/telegram/api/updateProfile.ts | 14 +-- src/lib/{mcp => }/telegram/args.test.ts | 0 src/lib/{mcp => }/telegram/args.ts | 0 src/lib/{mcp => }/telegram/index.ts | 0 .../mcp-tools}/__tests__/getChats.test.ts | 92 +++++++++++--- .../mcp-tools}/__tests__/getMe.test.ts | 2 +- .../mcp-tools}/__tests__/getMessages.test.ts | 65 +++++----- .../mcp-tools}/__tests__/sendMessage.test.ts | 21 +--- .../__tests__/toolDefinitions.test.ts | 29 +++-- .../mcp-tools}/addContact.ts | 8 +- .../mcp-tools}/archiveChat.ts | 10 +- .../tools => telegram/mcp-tools}/banUser.ts | 10 +- .../tools => telegram/mcp-tools}/blockUser.ts | 10 +- .../mcp-tools}/clearDraft.ts | 10 +- .../mcp-tools}/createChannel.ts | 8 +- .../mcp-tools}/createGroup.ts | 10 +- .../mcp-tools}/createPoll.ts | 10 +- .../mcp-tools}/deleteChatPhoto.ts | 10 +- .../mcp-tools}/deleteContact.ts | 10 +- .../mcp-tools}/deleteMessage.ts | 10 +- .../mcp-tools}/deleteProfilePhoto.ts | 8 +- .../mcp-tools}/demoteAdmin.ts | 10 +- .../mcp-tools}/editChatPhoto.ts | 10 +- .../mcp-tools}/editChatTitle.ts | 10 +- .../mcp-tools}/editMessage.ts | 10 +- .../mcp-tools}/exportChatInvite.ts | 12 +- .../mcp-tools}/exportContacts.ts | 8 +- .../mcp-tools}/forwardMessage.ts | 16 ++- .../tools => telegram/mcp-tools}/getAdmins.ts | 10 +- .../mcp-tools}/getBannedUsers.ts | 12 +- .../mcp-tools}/getBlockedUsers.ts | 8 +- .../mcp-tools}/getBotInfo.ts | 10 +- .../tools => telegram/mcp-tools}/getChat.ts | 14 ++- .../tools => telegram/mcp-tools}/getChats.ts | 13 +- .../mcp-tools}/getContactChats.ts | 13 +- .../mcp-tools}/getContactIds.ts | 8 +- .../mcp-tools}/getDirectChatByContact.ts | 23 ++-- .../tools => telegram/mcp-tools}/getDrafts.ts | 8 +- .../mcp-tools}/getGifSearch.ts | 8 +- .../mcp-tools}/getHistory.ts | 20 ++-- .../mcp-tools}/getInviteLink.ts | 10 +- .../mcp-tools}/getLastInteraction.ts | 24 ++-- .../tools => telegram/mcp-tools}/getMe.ts | 8 +- .../mcp-tools}/getMediaInfo.ts | 10 +- .../mcp-tools}/getMessageContext.ts | 25 ++-- .../mcp-tools}/getMessageReactions.ts | 15 ++- .../mcp-tools}/getMessages.ts | 22 ++-- .../mcp-tools}/getParticipants.ts | 12 +- .../mcp-tools}/getPinnedMessages.ts | 16 +-- .../mcp-tools}/getPrivacySettings.ts | 8 +- .../mcp-tools}/getRecentActions.ts | 12 +- .../mcp-tools}/getStickerSets.ts | 10 +- .../mcp-tools}/getUserPhotos.ts | 15 ++- .../mcp-tools}/getUserStatus.ts | 16 +-- .../mcp-tools}/importChatInvite.ts | 8 +- .../mcp-tools}/importContacts.ts | 12 +- .../tools => telegram/mcp-tools}/index.ts | 0 .../mcp-tools}/inviteToGroup.ts | 14 ++- .../mcp-tools}/joinChatByLink.ts | 8 +- .../tools => telegram/mcp-tools}/leaveChat.ts | 10 +- .../tools => telegram/mcp-tools}/listChats.ts | 8 +- .../mcp-tools}/listContacts.ts | 8 +- .../mcp-tools}/listInlineButtons.ts | 17 +-- .../mcp-tools}/listMessages.ts | 22 ++-- .../mcp-tools}/listTopics.ts | 10 +- .../mcp-tools}/markAsRead.ts | 10 +- .../tools => telegram/mcp-tools}/muteChat.ts | 10 +- .../mcp-tools}/notImplemented.ts | 2 +- .../mcp-tools}/pinMessage.ts | 10 +- .../mcp-tools}/pressInlineButton.ts | 16 ++- .../mcp-tools}/promoteAdmin.ts | 10 +- .../mcp-tools}/removeReaction.ts | 10 +- .../mcp-tools}/replyToMessage.ts | 10 +- .../mcp-tools}/resolveUsername.ts | 12 +- .../tools => telegram/mcp-tools}/saveDraft.ts | 10 +- .../mcp-tools}/searchContacts.ts | 13 +- .../mcp-tools}/searchMessages.ts | 16 ++- .../mcp-tools}/searchPublicChats.ts | 8 +- .../mcp-tools}/sendMessage.ts | 20 ++-- .../mcp-tools}/sendReaction.ts | 10 +- .../mcp-tools}/setBotCommands.ts | 10 +- .../mcp-tools}/setPrivacySettings.ts | 8 +- .../mcp-tools}/setProfilePhoto.ts | 8 +- .../mcp-tools}/subscribePublicChannel.ts | 8 +- .../mcp-tools}/unarchiveChat.ts | 10 +- .../tools => telegram/mcp-tools}/unbanUser.ts | 10 +- .../mcp-tools}/unblockUser.ts | 10 +- .../mcp-tools}/unmuteChat.ts | 10 +- .../mcp-tools}/unpinMessage.ts | 10 +- .../mcp-tools}/updateProfile.ts | 8 +- src/lib/{mcp => }/telegram/server.test.ts | 113 ++++++++++++------ src/lib/{mcp => }/telegram/server.ts | 57 +++++---- .../telegram/services}/entityBuilders.ts | 15 ++- .../telegram/services}/index.ts | 0 .../telegram/services}/schedulers.ts | 0 .../telegram/services}/syncService.ts | 48 ++++---- .../telegram/services}/updateHandler.ts | 22 ++-- src/lib/{mcp => }/telegram/state/chatState.ts | 8 +- src/lib/{mcp => }/telegram/state/helpers.ts | 2 +- src/lib/{mcp => }/telegram/state/index.ts | 0 .../{mcp => }/telegram/state/messageState.ts | 15 +-- src/lib/{mcp => }/telegram/state/userState.ts | 6 +- .../{mcp => }/telegram/toolActionParser.ts | 0 src/lib/{mcp => }/telegram/types.ts | 8 +- src/providers/SocketProvider.tsx | 2 +- src/providers/TelegramProvider.tsx | 2 +- yarn.lock | 14 ++- 195 files changed, 1180 insertions(+), 1012 deletions(-) rename src/lib/{mcp => }/telegram/api/__tests__/getChats.test.ts (82%) rename src/lib/{mcp => }/telegram/api/__tests__/getCurrentUser.test.ts (87%) rename src/lib/{mcp => }/telegram/api/__tests__/getMessages.test.ts (88%) rename src/lib/{mcp => }/telegram/api/__tests__/helpers.test.ts (99%) rename src/lib/{mcp => }/telegram/api/__tests__/sendMessage.test.ts (95%) rename src/lib/{mcp => }/telegram/api/addContact.ts (88%) rename src/lib/{mcp => }/telegram/api/apiCastHelpers.ts (100%) rename src/lib/{mcp => }/telegram/api/apiResultTypes.ts (100%) rename src/lib/{mcp => }/telegram/api/archiveChat.ts (88%) rename src/lib/{mcp => }/telegram/api/banUser.ts (92%) rename src/lib/{mcp => }/telegram/api/blockUser.ts (73%) rename src/lib/{mcp => }/telegram/api/clearDraft.ts (77%) rename src/lib/{mcp => }/telegram/api/createChannel.ts (88%) rename src/lib/{mcp => }/telegram/api/createGroup.ts (90%) rename src/lib/{mcp => }/telegram/api/createPoll.ts (86%) rename src/lib/{mcp => }/telegram/api/deleteChatPhoto.ts (90%) rename src/lib/{mcp => }/telegram/api/deleteContact.ts (72%) rename src/lib/{mcp => }/telegram/api/deleteMessage.ts (75%) rename src/lib/{mcp => }/telegram/api/deleteProfilePhoto.ts (92%) rename src/lib/{mcp => }/telegram/api/demoteAdmin.ts (90%) rename src/lib/{mcp => }/telegram/api/editChatPhoto.ts (100%) rename src/lib/{mcp => }/telegram/api/editChatTitle.ts (90%) rename src/lib/{mcp => }/telegram/api/editMessage.ts (76%) rename src/lib/{mcp => }/telegram/api/exportChatInvite.ts (91%) rename src/lib/{mcp => }/telegram/api/exportContacts.ts (85%) rename src/lib/{mcp => }/telegram/api/forwardMessage.ts (91%) rename src/lib/{mcp => }/telegram/api/getAdmins.ts (91%) rename src/lib/{mcp => }/telegram/api/getBannedUsers.ts (94%) rename src/lib/{mcp => }/telegram/api/getBlockedUsers.ts (92%) rename src/lib/{mcp => }/telegram/api/getBotInfo.ts (89%) rename src/lib/{mcp => }/telegram/api/getChat.ts (91%) rename src/lib/{mcp => }/telegram/api/getChats.ts (88%) rename src/lib/{mcp => }/telegram/api/getContactChats.ts (82%) rename src/lib/{mcp => }/telegram/api/getContactIds.ts (85%) rename src/lib/{mcp => }/telegram/api/getCurrentUser.ts (88%) rename src/lib/{mcp => }/telegram/api/getDirectChatByContact.ts (81%) rename src/lib/{mcp => }/telegram/api/getDrafts.ts (94%) rename src/lib/{mcp => }/telegram/api/getGifSearch.ts (92%) rename src/lib/{mcp => }/telegram/api/getInviteLink.ts (89%) rename src/lib/{mcp => }/telegram/api/getLastInteraction.ts (100%) rename src/lib/{mcp => }/telegram/api/getMediaInfo.ts (100%) rename src/lib/{mcp => }/telegram/api/getMessageReactions.ts (89%) rename src/lib/{mcp => }/telegram/api/getMessages.ts (89%) rename src/lib/{mcp => }/telegram/api/getParticipants.ts (94%) rename src/lib/{mcp => }/telegram/api/getPinnedMessages.ts (79%) rename src/lib/{mcp => }/telegram/api/getPrivacySettings.ts (86%) rename src/lib/{mcp => }/telegram/api/getRecentActions.ts (94%) rename src/lib/{mcp => }/telegram/api/getStickerSets.ts (86%) rename src/lib/{mcp => }/telegram/api/getUserPhotos.ts (84%) rename src/lib/{mcp => }/telegram/api/getUserStatus.ts (92%) rename src/lib/{mcp => }/telegram/api/helpers.ts (92%) rename src/lib/{mcp => }/telegram/api/importChatInvite.ts (87%) rename src/lib/{mcp => }/telegram/api/importContacts.ts (91%) rename src/lib/{mcp => }/telegram/api/index.ts (100%) rename src/lib/{mcp => }/telegram/api/inviteToGroup.ts (92%) rename src/lib/{mcp => }/telegram/api/joinChatByLink.ts (90%) rename src/lib/{mcp => }/telegram/api/leaveChat.ts (90%) rename src/lib/{mcp => }/telegram/api/listContacts.ts (93%) rename src/lib/{mcp => }/telegram/api/listInlineButtons.ts (100%) rename src/lib/{mcp => }/telegram/api/listTopics.ts (93%) rename src/lib/{mcp => }/telegram/api/markAsRead.ts (72%) rename src/lib/{mcp => }/telegram/api/muteChat.ts (90%) rename src/lib/{mcp => }/telegram/api/pinMessage.ts (75%) rename src/lib/{mcp => }/telegram/api/pressInlineButton.ts (84%) rename src/lib/{mcp => }/telegram/api/promoteAdmin.ts (92%) rename src/lib/{mcp => }/telegram/api/removeReaction.ts (79%) rename src/lib/{mcp => }/telegram/api/resolveUsername.ts (86%) rename src/lib/{mcp => }/telegram/api/saveDraft.ts (78%) rename src/lib/{mcp => }/telegram/api/searchChats.ts (77%) rename src/lib/{mcp => }/telegram/api/searchContacts.ts (92%) rename src/lib/{mcp => }/telegram/api/searchMessages.ts (92%) rename src/lib/{mcp => }/telegram/api/searchPublicChats.ts (92%) rename src/lib/{mcp => }/telegram/api/sendMessage.ts (80%) rename src/lib/{mcp => }/telegram/api/sendReaction.ts (80%) rename src/lib/{mcp => }/telegram/api/setBotCommands.ts (87%) rename src/lib/{mcp => }/telegram/api/setPrivacySettings.ts (91%) rename src/lib/{mcp => }/telegram/api/setProfilePhoto.ts (100%) rename src/lib/{mcp => }/telegram/api/subscribePublicChannel.ts (84%) rename src/lib/{mcp => }/telegram/api/types.ts (100%) rename src/lib/{mcp => }/telegram/api/unarchiveChat.ts (88%) rename src/lib/{mcp => }/telegram/api/unbanUser.ts (91%) rename src/lib/{mcp => }/telegram/api/unblockUser.ts (62%) rename src/lib/{mcp => }/telegram/api/unmuteChat.ts (88%) rename src/lib/{mcp => }/telegram/api/unpinMessage.ts (79%) rename src/lib/{mcp => }/telegram/api/updateProfile.ts (83%) rename src/lib/{mcp => }/telegram/args.test.ts (100%) rename src/lib/{mcp => }/telegram/args.ts (100%) rename src/lib/{mcp => }/telegram/index.ts (100%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/__tests__/getChats.test.ts (69%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/__tests__/getMe.test.ts (98%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/__tests__/getMessages.test.ts (83%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/__tests__/sendMessage.test.ts (88%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/__tests__/toolDefinitions.test.ts (88%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/addContact.ts (86%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/archiveChat.ts (77%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/banUser.ts (81%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/blockUser.ts (76%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/clearDraft.ts (78%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/createChannel.ts (88%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/createGroup.ts (86%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/createPoll.ts (85%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/deleteChatPhoto.ts (78%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/deleteContact.ts (78%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/deleteMessage.ts (80%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/deleteProfilePhoto.ts (78%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/demoteAdmin.ts (82%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/editChatPhoto.ts (80%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/editChatTitle.ts (82%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/editMessage.ts (83%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/exportChatInvite.ts (84%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/exportContacts.ts (81%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/forwardMessage.ts (76%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getAdmins.ts (83%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getBannedUsers.ts (85%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getBlockedUsers.ts (86%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getBotInfo.ts (84%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getChat.ts (84%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getChats.ts (83%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getContactChats.ts (75%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getContactIds.ts (81%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getDirectChatByContact.ts (65%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getDrafts.ts (81%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getGifSearch.ts (88%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getHistory.ts (80%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getInviteLink.ts (78%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getLastInteraction.ts (67%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getMe.ts (86%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getMediaInfo.ts (85%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getMessageContext.ts (83%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getMessageReactions.ts (82%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getMessages.ts (84%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getParticipants.ts (85%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getPinnedMessages.ts (81%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getPrivacySettings.ts (87%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getRecentActions.ts (83%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getStickerSets.ts (83%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getUserPhotos.ts (78%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/getUserStatus.ts (74%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/importChatInvite.ts (84%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/importContacts.ts (82%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/index.ts (100%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/inviteToGroup.ts (77%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/joinChatByLink.ts (85%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/leaveChat.ts (79%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/listChats.ts (91%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/listContacts.ts (84%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/listInlineButtons.ts (84%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/listMessages.ts (85%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/listTopics.ts (81%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/markAsRead.ts (78%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/muteChat.ts (81%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/notImplemented.ts (76%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/pinMessage.ts (80%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/pressInlineButton.ts (80%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/promoteAdmin.ts (82%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/removeReaction.ts (81%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/replyToMessage.ts (90%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/resolveUsername.ts (84%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/saveDraft.ts (81%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/searchContacts.ts (85%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/searchMessages.ts (87%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/searchPublicChats.ts (89%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/sendMessage.ts (79%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/sendReaction.ts (82%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/setBotCommands.ts (82%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/setPrivacySettings.ts (85%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/setProfilePhoto.ts (82%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/subscribePublicChannel.ts (85%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/unarchiveChat.ts (77%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/unbanUser.ts (82%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/unblockUser.ts (76%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/unmuteChat.ts (77%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/unpinMessage.ts (80%) rename src/lib/{mcp/telegram/tools => telegram/mcp-tools}/updateProfile.ts (85%) rename src/lib/{mcp => }/telegram/server.test.ts (88%) rename src/lib/{mcp => }/telegram/server.ts (89%) rename src/{services/telegram => lib/telegram/services}/entityBuilders.ts (96%) rename src/{services/telegram => lib/telegram/services}/index.ts (100%) rename src/{services/telegram => lib/telegram/services}/schedulers.ts (100%) rename src/{services/telegram => lib/telegram/services}/syncService.ts (95%) rename src/{services/telegram => lib/telegram/services}/updateHandler.ts (95%) rename src/lib/{mcp => }/telegram/state/chatState.ts (93%) rename src/lib/{mcp => }/telegram/state/helpers.ts (87%) rename src/lib/{mcp => }/telegram/state/index.ts (100%) rename src/lib/{mcp => }/telegram/state/messageState.ts (73%) rename src/lib/{mcp => }/telegram/state/userState.ts (88%) rename src/lib/{mcp => }/telegram/toolActionParser.ts (100%) rename src/lib/{mcp => }/telegram/types.ts (90%) diff --git a/package-lock.json b/package-lock.json index 1aed6fed3..8f20d6f23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@tauri-apps/plugin-opener": "^2", "@types/react-router-dom": "^5.3.3", "buffer": "^6.0.3", + "debug": "^4.4.3", "lottie-react": "^2.4.1", "os-browserify": "^0.3.0", "process": "^0.11.10", @@ -33,6 +34,7 @@ "@tailwindcss/forms": "^0.5.11", "@tailwindcss/typography": "^0.5.19", "@tauri-apps/cli": "^2", + "@types/debug": "^4.1.12", "@types/node": "^25.0.10", "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", @@ -1663,6 +1665,16 @@ "assertion-error": "^2.0.1" } }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/deep-eql": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", @@ -1683,6 +1695,13 @@ "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", "license": "MIT" }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "25.0.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.10.tgz", diff --git a/package.json b/package.json index 4d0d5a955..9f44e58a5 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@tauri-apps/plugin-opener": "^2", "@types/react-router-dom": "^5.3.3", "buffer": "^6.0.3", + "debug": "^4.4.3", "lottie-react": "^2.4.1", "os-browserify": "^0.3.0", "process": "^0.11.10", @@ -41,6 +42,7 @@ "@tailwindcss/forms": "^0.5.11", "@tailwindcss/typography": "^0.5.19", "@tauri-apps/cli": "^2", + "@types/debug": "^4.1.12", "@types/node": "^25.0.10", "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", diff --git a/src/__tests__/fixtures/mcpContext.ts b/src/__tests__/fixtures/mcpContext.ts index ef0a949a0..18fd6d333 100644 --- a/src/__tests__/fixtures/mcpContext.ts +++ b/src/__tests__/fixtures/mcpContext.ts @@ -2,8 +2,8 @@ * Factory builder for TelegramMCPContext (used by tool handlers). */ -import { vi } from 'vitest'; -import type { TelegramMCPContext } from "../../lib/mcp/telegram/types"; +import { vi } from "vitest"; +import type { TelegramMCPContext } from "../../lib/telegram/types"; import type { TelegramState } from "../../store/telegram/types"; import { initialState } from "../../store/telegram/types"; @@ -18,7 +18,7 @@ function createMockTransport() { } export function createMockContext( - telegramOverrides: Partial = {}, + telegramOverrides: Partial = {} ): TelegramMCPContext { return { telegramState: { ...initialState, ...telegramOverrides }, diff --git a/src/lib/mcp/skills/bulk.ts b/src/lib/mcp/skills/bulk.ts index ab59abbaf..fecce4792 100644 --- a/src/lib/mcp/skills/bulk.ts +++ b/src/lib/mcp/skills/bulk.ts @@ -7,7 +7,7 @@ import type { MCPTool, MCPToolResult } from "../types"; import type { ExtraTool } from "./types"; -import { sendMessage } from "../telegram/api/sendMessage"; +import { sendMessage } from "../../telegram/api/sendMessage"; // --------------------------------------------------------------------------- // Constants @@ -148,7 +148,7 @@ IMPORTANT: Bulk operations execute sequentially with delays between items to avo export async function executeBulkTool( toolName: string, - args: Record, + args: Record ): Promise { switch (toolName) { case "bulk_send_message": @@ -174,7 +174,7 @@ export async function executeBulkTool( // --------------------------------------------------------------------------- async function executeBulkSendMessage( - args: Record, + args: Record ): Promise { const chatIds = args.chat_ids as string[]; const message = args.message as string; @@ -182,7 +182,10 @@ async function executeBulkSendMessage( if (!chatIds?.length || !message) { return { content: [ - { type: "text", text: "chat_ids (array) and message (string) are required" }, + { + type: "text", + text: "chat_ids (array) and message (string) are required", + }, ], isError: true, }; @@ -217,7 +220,7 @@ async function executeBulkSendMessage( } async function executeBulkArchiveChats( - args: Record, + args: Record ): Promise { const chatIds = args.chat_ids as string[]; if (!chatIds?.length) { @@ -240,7 +243,7 @@ async function executeBulkArchiveChats( } async function executeBulkMarkAsRead( - args: Record, + args: Record ): Promise { const chatIds = args.chat_ids as string[]; if (!chatIds?.length) { @@ -262,7 +265,7 @@ async function executeBulkMarkAsRead( } async function executeBulkDeleteMessages( - args: Record, + args: Record ): Promise { const chatId = args.chat_id as string; const messageIds = args.message_ids as string[]; @@ -291,7 +294,7 @@ async function executeBulkDeleteMessages( } async function executeBulkForwardMessages( - args: Record, + args: Record ): Promise { const fromChatId = args.from_chat_id as string; const messageIds = args.message_ids as string[]; diff --git a/src/lib/mcp/telegram/api/__tests__/getChats.test.ts b/src/lib/telegram/api/__tests__/getChats.test.ts similarity index 82% rename from src/lib/mcp/telegram/api/__tests__/getChats.test.ts rename to src/lib/telegram/api/__tests__/getChats.test.ts index b6dfc1879..f6e1ec7a9 100644 --- a/src/lib/mcp/telegram/api/__tests__/getChats.test.ts +++ b/src/lib/telegram/api/__tests__/getChats.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { getChats } from "../getChats"; -import type { TelegramChat } from "../../../../../store/telegram/types"; +import type { TelegramChat } from "../../../../store/telegram/types"; // Mock dependencies const mockClient = { @@ -10,7 +10,7 @@ const mockClient = { sendMessage: vi.fn(), }; -vi.mock("../../../../../services/mtprotoService", () => ({ +vi.mock("../../../../services/mtprotoService", () => ({ mtprotoService: { getClient: vi.fn(() => mockClient), withFloodWaitHandling: vi.fn(async (fn: any) => await fn()), @@ -20,7 +20,7 @@ vi.mock("../../../../../services/mtprotoService", () => ({ }, })); -vi.mock("../../../../../store", () => ({ +vi.mock("../../../../store", () => ({ store: { getState: vi.fn(() => ({ user: { user: { _id: "u1" } }, @@ -39,7 +39,7 @@ vi.mock("../../../../../store", () => ({ }, })); -vi.mock("../../../../../store/telegramSelectors", () => ({ +vi.mock("../../../../store/telegramSelectors", () => ({ selectTelegramUserState: vi.fn(() => ({ chats: {}, chatsOrder: [], @@ -51,7 +51,7 @@ vi.mock("../../../../../store/telegramSelectors", () => ({ selectOrderedChats: vi.fn(() => []), })); -vi.mock("../../../rateLimiter", () => ({ +vi.mock("../../../mcp/rateLimiter", () => ({ enforceRateLimit: vi.fn(), resetRequestCallCount: vi.fn(), })); @@ -97,7 +97,7 @@ describe("getChats", () => { expect(result.fromCache).toBe(true); const { mtprotoService } = await import( - "../../../../../services/mtprotoService" + "../../../../services/mtprotoService" ); expect(mtprotoService.getClient).not.toHaveBeenCalled(); }); @@ -106,7 +106,7 @@ describe("getChats", () => { const { getOrderedChats } = await import("../helpers"); vi.mocked(getOrderedChats).mockReturnValueOnce([]); - const { enforceRateLimit } = await import("../../../rateLimiter"); + const { enforceRateLimit } = await import("../../../mcp/rateLimiter"); vi.mocked(enforceRateLimit).mockResolvedValueOnce(undefined); const mockApiDialogs = { @@ -145,7 +145,7 @@ describe("getChats", () => { const { getOrderedChats } = await import("../helpers"); vi.mocked(getOrderedChats).mockReturnValueOnce([]); - const { enforceRateLimit } = await import("../../../rateLimiter"); + const { enforceRateLimit } = await import("../../../mcp/rateLimiter"); vi.mocked(enforceRateLimit).mockResolvedValueOnce(undefined); mockClient.invoke.mockRejectedValueOnce(new Error("API Error")); @@ -160,7 +160,7 @@ describe("getChats", () => { const { getOrderedChats } = await import("../helpers"); vi.mocked(getOrderedChats).mockReturnValueOnce([]); - const { enforceRateLimit } = await import("../../../rateLimiter"); + const { enforceRateLimit } = await import("../../../mcp/rateLimiter"); vi.mocked(enforceRateLimit).mockRejectedValueOnce( new Error("Rate limit exceeded") ); @@ -171,22 +171,27 @@ describe("getChats", () => { expect(result.fromCache).toBe(false); const { mtprotoService } = await import( - "../../../../../services/mtprotoService" + "../../../../services/mtprotoService" ); expect(mtprotoService.getClient).not.toHaveBeenCalled(); }); it("should respect custom limit parameter", async () => { - const mockCachedChats: TelegramChat[] = Array.from({ length: 50 }, (_, i) => ({ - id: String(i), - title: `Chat ${i}`, - type: "private", - unreadCount: 0, - isPinned: false, - })); + const mockCachedChats: TelegramChat[] = Array.from( + { length: 50 }, + (_, i) => ({ + id: String(i), + title: `Chat ${i}`, + type: "private", + unreadCount: 0, + isPinned: false, + }) + ); const { getOrderedChats } = await import("../helpers"); - vi.mocked(getOrderedChats).mockReturnValueOnce(mockCachedChats.slice(0, 50)); + vi.mocked(getOrderedChats).mockReturnValueOnce( + mockCachedChats.slice(0, 50) + ); const result = await getChats(50); diff --git a/src/lib/mcp/telegram/api/__tests__/getCurrentUser.test.ts b/src/lib/telegram/api/__tests__/getCurrentUser.test.ts similarity index 87% rename from src/lib/mcp/telegram/api/__tests__/getCurrentUser.test.ts rename to src/lib/telegram/api/__tests__/getCurrentUser.test.ts index 9ab3d0132..c4b106875 100644 --- a/src/lib/mcp/telegram/api/__tests__/getCurrentUser.test.ts +++ b/src/lib/telegram/api/__tests__/getCurrentUser.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { getCurrentUser } from "../getCurrentUser"; -import type { TelegramUser } from "../../../../../store/telegram/types"; +import type { TelegramUser } from "../../../../store/telegram/types"; // Mock dependencies const mockClient = { @@ -10,7 +10,7 @@ const mockClient = { sendMessage: vi.fn(), }; -vi.mock("../../../../../services/mtprotoService", () => ({ +vi.mock("../../../../services/mtprotoService", () => ({ mtprotoService: { getClient: vi.fn(() => mockClient), withFloodWaitHandling: vi.fn(async (fn: any) => await fn()), @@ -20,7 +20,7 @@ vi.mock("../../../../../services/mtprotoService", () => ({ }, })); -vi.mock("../../../../../store", () => ({ +vi.mock("../../../../store", () => ({ store: { getState: vi.fn(() => ({ user: { user: { _id: "u1" } }, @@ -40,7 +40,7 @@ vi.mock("../../../../../store", () => ({ }, })); -vi.mock("../../../../../store/telegramSelectors", () => ({ +vi.mock("../../../../store/telegramSelectors", () => ({ selectTelegramUserState: vi.fn(() => ({ chats: {}, chatsOrder: [], @@ -52,7 +52,7 @@ vi.mock("../../../../../store/telegramSelectors", () => ({ selectOrderedChats: vi.fn(() => []), })); -vi.mock("../../../rateLimiter", () => ({ +vi.mock("../../../mcp/rateLimiter", () => ({ enforceRateLimit: vi.fn(), resetRequestCallCount: vi.fn(), })); @@ -89,7 +89,7 @@ describe("getCurrentUser", () => { expect(result.fromCache).toBe(true); const { mtprotoService } = await import( - "../../../../../services/mtprotoService" + "../../../../services/mtprotoService" ); expect(mtprotoService.getClient).not.toHaveBeenCalled(); }); @@ -98,7 +98,7 @@ describe("getCurrentUser", () => { const { getCurrentUser: getCurrentUserHelper } = await import("../helpers"); vi.mocked(getCurrentUserHelper).mockReturnValueOnce(undefined); - const { enforceRateLimit } = await import("../../../rateLimiter"); + const { enforceRateLimit } = await import("../../../mcp/rateLimiter"); vi.mocked(enforceRateLimit).mockResolvedValueOnce(undefined); const mockApiUser = { @@ -124,7 +124,7 @@ describe("getCurrentUser", () => { const { getCurrentUser: getCurrentUserHelper } = await import("../helpers"); vi.mocked(getCurrentUserHelper).mockReturnValueOnce(undefined); - const { enforceRateLimit } = await import("../../../rateLimiter"); + const { enforceRateLimit } = await import("../../../mcp/rateLimiter"); vi.mocked(enforceRateLimit).mockResolvedValueOnce(undefined); mockClient.getMe.mockResolvedValueOnce(null); @@ -139,7 +139,7 @@ describe("getCurrentUser", () => { const { getCurrentUser: getCurrentUserHelper } = await import("../helpers"); vi.mocked(getCurrentUserHelper).mockReturnValueOnce(undefined); - const { enforceRateLimit } = await import("../../../rateLimiter"); + const { enforceRateLimit } = await import("../../../mcp/rateLimiter"); vi.mocked(enforceRateLimit).mockResolvedValueOnce(undefined); mockClient.getMe.mockRejectedValueOnce(new Error("API Error")); @@ -154,7 +154,7 @@ describe("getCurrentUser", () => { const { getCurrentUser: getCurrentUserHelper } = await import("../helpers"); vi.mocked(getCurrentUserHelper).mockReturnValueOnce(undefined); - const { enforceRateLimit } = await import("../../../rateLimiter"); + const { enforceRateLimit } = await import("../../../mcp/rateLimiter"); vi.mocked(enforceRateLimit).mockRejectedValueOnce( new Error("Rate limit exceeded") ); @@ -165,7 +165,7 @@ describe("getCurrentUser", () => { expect(result.fromCache).toBe(false); const { mtprotoService } = await import( - "../../../../../services/mtprotoService" + "../../../../services/mtprotoService" ); expect(mtprotoService.getClient).not.toHaveBeenCalled(); }); @@ -174,7 +174,7 @@ describe("getCurrentUser", () => { const { getCurrentUser: getCurrentUserHelper } = await import("../helpers"); vi.mocked(getCurrentUserHelper).mockReturnValueOnce(undefined); - const { enforceRateLimit } = await import("../../../rateLimiter"); + const { enforceRateLimit } = await import("../../../mcp/rateLimiter"); vi.mocked(enforceRateLimit).mockResolvedValueOnce(undefined); const mockApiUser = { diff --git a/src/lib/mcp/telegram/api/__tests__/getMessages.test.ts b/src/lib/telegram/api/__tests__/getMessages.test.ts similarity index 88% rename from src/lib/mcp/telegram/api/__tests__/getMessages.test.ts rename to src/lib/telegram/api/__tests__/getMessages.test.ts index ad5ac63de..778c61626 100644 --- a/src/lib/mcp/telegram/api/__tests__/getMessages.test.ts +++ b/src/lib/telegram/api/__tests__/getMessages.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { getMessages } from "../getMessages"; -import type { TelegramMessage } from "../../../../../store/telegram/types"; +import type { TelegramMessage } from "../../../../store/telegram/types"; // Mock dependencies const mockClient = { @@ -10,7 +10,7 @@ const mockClient = { sendMessage: vi.fn(), }; -vi.mock("../../../../../services/mtprotoService", () => ({ +vi.mock("../../../../services/mtprotoService", () => ({ mtprotoService: { getClient: vi.fn(() => mockClient), withFloodWaitHandling: vi.fn(async (fn: any) => await fn()), @@ -20,7 +20,7 @@ vi.mock("../../../../../services/mtprotoService", () => ({ }, })); -vi.mock("../../../../../store", () => ({ +vi.mock("../../../../store", () => ({ store: { getState: vi.fn(() => ({ user: { user: { _id: "u1" } }, @@ -39,7 +39,7 @@ vi.mock("../../../../../store", () => ({ }, })); -vi.mock("../../../../../store/telegramSelectors", () => ({ +vi.mock("../../../../store/telegramSelectors", () => ({ selectTelegramUserState: vi.fn(() => ({ chats: {}, chatsOrder: [], @@ -51,7 +51,7 @@ vi.mock("../../../../../store/telegramSelectors", () => ({ selectOrderedChats: vi.fn(() => []), })); -vi.mock("../../../rateLimiter", () => ({ +vi.mock("../../../mcp/rateLimiter", () => ({ enforceRateLimit: vi.fn(), resetRequestCallCount: vi.fn(), })); @@ -112,7 +112,7 @@ describe("getMessages", () => { expect(result.fromCache).toBe(true); const { mtprotoService } = await import( - "../../../../../services/mtprotoService" + "../../../../services/mtprotoService" ); expect(mtprotoService.getClient).not.toHaveBeenCalled(); }); @@ -128,7 +128,7 @@ describe("getMessages", () => { isPinned: false, }); - const { enforceRateLimit } = await import("../../../rateLimiter"); + const { enforceRateLimit } = await import("../../../mcp/rateLimiter"); vi.mocked(enforceRateLimit).mockResolvedValueOnce(undefined); const mockApiMessages = { @@ -151,7 +151,10 @@ describe("getMessages", () => { ], }; - mockClient.getInputEntity.mockResolvedValueOnce({ className: "InputPeerUser", userId: 1n }); + mockClient.getInputEntity.mockResolvedValueOnce({ + className: "InputPeerUser", + userId: 1n, + }); mockClient.invoke.mockResolvedValueOnce(mockApiMessages); const result = await getMessages("1", 20); @@ -176,7 +179,7 @@ describe("getMessages", () => { expect(result.fromCache).toBe(false); const { mtprotoService } = await import( - "../../../../../services/mtprotoService" + "../../../../services/mtprotoService" ); expect(mtprotoService.getClient).not.toHaveBeenCalled(); }); @@ -192,10 +195,13 @@ describe("getMessages", () => { isPinned: false, }); - const { enforceRateLimit } = await import("../../../rateLimiter"); + const { enforceRateLimit } = await import("../../../mcp/rateLimiter"); vi.mocked(enforceRateLimit).mockResolvedValueOnce(undefined); - mockClient.getInputEntity.mockResolvedValueOnce({ className: "InputPeerUser", userId: 1n }); + mockClient.getInputEntity.mockResolvedValueOnce({ + className: "InputPeerUser", + userId: 1n, + }); mockClient.invoke.mockRejectedValueOnce(new Error("API Error")); const result = await getMessages("1", 20); @@ -215,7 +221,7 @@ describe("getMessages", () => { isPinned: false, }); - const { enforceRateLimit } = await import("../../../rateLimiter"); + const { enforceRateLimit } = await import("../../../mcp/rateLimiter"); vi.mocked(enforceRateLimit).mockRejectedValueOnce( new Error("Rate limit exceeded") ); @@ -226,7 +232,7 @@ describe("getMessages", () => { expect(result.fromCache).toBe(false); const { mtprotoService } = await import( - "../../../../../services/mtprotoService" + "../../../../services/mtprotoService" ); expect(mtprotoService.getClient).not.toHaveBeenCalled(); }); diff --git a/src/lib/mcp/telegram/api/__tests__/helpers.test.ts b/src/lib/telegram/api/__tests__/helpers.test.ts similarity index 99% rename from src/lib/mcp/telegram/api/__tests__/helpers.test.ts rename to src/lib/telegram/api/__tests__/helpers.test.ts index 833674da0..c42d9e00c 100644 --- a/src/lib/mcp/telegram/api/__tests__/helpers.test.ts +++ b/src/lib/telegram/api/__tests__/helpers.test.ts @@ -10,7 +10,7 @@ import type { TelegramChat, TelegramUser, TelegramMessage, -} from "../../../../../store/telegram/types"; +} from "../../../../store/telegram/types"; // Mock the store module vi.mock("../../../../../store", () => ({ diff --git a/src/lib/mcp/telegram/api/__tests__/sendMessage.test.ts b/src/lib/telegram/api/__tests__/sendMessage.test.ts similarity index 95% rename from src/lib/mcp/telegram/api/__tests__/sendMessage.test.ts rename to src/lib/telegram/api/__tests__/sendMessage.test.ts index 0a815a796..fe0bca13e 100644 --- a/src/lib/mcp/telegram/api/__tests__/sendMessage.test.ts +++ b/src/lib/telegram/api/__tests__/sendMessage.test.ts @@ -2,7 +2,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { sendMessage } from "../sendMessage"; // Mock dependencies -vi.mock("../../../../../services/mtprotoService", () => { +vi.mock("../../../../services/mtprotoService", () => { const mockClient = { invoke: vi.fn(), getInputEntity: vi.fn(), @@ -21,7 +21,7 @@ vi.mock("../../../../../services/mtprotoService", () => { }; }); -vi.mock("../../../../../store", () => ({ +vi.mock("../../../../store", () => ({ store: { getState: vi.fn(() => ({ user: { user: { _id: "u1" } }, @@ -40,7 +40,7 @@ vi.mock("../../../../../store", () => ({ }, })); -vi.mock("../../../../../store/telegramSelectors", () => ({ +vi.mock("../../../../store/telegramSelectors", () => ({ selectTelegramUserState: vi.fn(() => ({ chats: {}, chatsOrder: [], @@ -52,7 +52,7 @@ vi.mock("../../../../../store/telegramSelectors", () => ({ selectOrderedChats: vi.fn(() => []), })); -vi.mock("../../../rateLimiter", () => ({ +vi.mock("../../../mcp/rateLimiter", () => ({ enforceRateLimit: vi.fn(), resetRequestCallCount: vi.fn(), })); @@ -71,7 +71,7 @@ describe("sendMessage", () => { beforeEach(async () => { vi.clearAllMocks(); - const mtproto = await import("../../../../../services/mtprotoService"); + const mtproto = await import("../../../../services/mtprotoService"); mockMtprotoService = mtproto.mtprotoService; mockClient = mockMtprotoService.getClient(); }); @@ -203,7 +203,10 @@ describe("sendMessage", () => { const result = await sendMessage("1", ""); - expect(mockMtprotoService.sendMessage).toHaveBeenCalledWith("@testuser", ""); + expect(mockMtprotoService.sendMessage).toHaveBeenCalledWith( + "@testuser", + "" + ); expect(result.data).toBeDefined(); }); @@ -225,7 +228,10 @@ describe("sendMessage", () => { const result = await sendMessage("1", longMessage); - expect(mockMtprotoService.sendMessage).toHaveBeenCalledWith("1", longMessage); + expect(mockMtprotoService.sendMessage).toHaveBeenCalledWith( + "1", + longMessage + ); expect(result.data).toBeDefined(); }); diff --git a/src/lib/mcp/telegram/api/addContact.ts b/src/lib/telegram/api/addContact.ts similarity index 88% rename from src/lib/mcp/telegram/api/addContact.ts rename to src/lib/telegram/api/addContact.ts index 7c7474e10..03e84178a 100644 --- a/src/lib/mcp/telegram/api/addContact.ts +++ b/src/lib/telegram/api/addContact.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import bigInt from "big-integer"; @@ -6,7 +6,7 @@ import bigInt from "big-integer"; export async function addContact( phone: string, firstName: string, - lastName?: string, + lastName?: string ): Promise> { if (!phone) { throw new Error("phone is required"); @@ -28,7 +28,7 @@ export async function addContact( lastName: lastName ?? "", }), ], - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/apiCastHelpers.ts b/src/lib/telegram/api/apiCastHelpers.ts similarity index 100% rename from src/lib/mcp/telegram/api/apiCastHelpers.ts rename to src/lib/telegram/api/apiCastHelpers.ts diff --git a/src/lib/mcp/telegram/api/apiResultTypes.ts b/src/lib/telegram/api/apiResultTypes.ts similarity index 100% rename from src/lib/mcp/telegram/api/apiResultTypes.ts rename to src/lib/telegram/api/apiResultTypes.ts diff --git a/src/lib/mcp/telegram/api/archiveChat.ts b/src/lib/telegram/api/archiveChat.ts similarity index 88% rename from src/lib/mcp/telegram/api/archiveChat.ts rename to src/lib/telegram/api/archiveChat.ts index c18c25e97..5b41301f9 100644 --- a/src/lib/mcp/telegram/api/archiveChat.ts +++ b/src/lib/telegram/api/archiveChat.ts @@ -1,10 +1,10 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; export async function archiveChat( - chatId: string | number, + chatId: string | number ): Promise> { const chat = getChatById(chatId); if (!chat) throw new Error(`Chat not found: ${chatId}`); @@ -22,7 +22,7 @@ export async function archiveChat( folderId: 1, // 1 = Archive folder }), ], - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/banUser.ts b/src/lib/telegram/api/banUser.ts similarity index 92% rename from src/lib/mcp/telegram/api/banUser.ts rename to src/lib/telegram/api/banUser.ts index 7735778d9..adb7b26d9 100644 --- a/src/lib/mcp/telegram/api/banUser.ts +++ b/src/lib/telegram/api/banUser.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import { toInputChannel, toInputPeer } from "./apiCastHelpers"; @@ -6,7 +6,7 @@ import { getChatById } from "./helpers"; export async function banUser( chatId: string | number, - userId: string | number, + userId: string | number ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -38,7 +38,7 @@ export async function banUser( embedLinks: true, untilDate: 0, }), - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/blockUser.ts b/src/lib/telegram/api/blockUser.ts similarity index 73% rename from src/lib/mcp/telegram/api/blockUser.ts rename to src/lib/telegram/api/blockUser.ts index 20669eb13..0daecf19f 100644 --- a/src/lib/mcp/telegram/api/blockUser.ts +++ b/src/lib/telegram/api/blockUser.ts @@ -1,9 +1,11 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import { toInputPeer } from "./apiCastHelpers"; -export async function blockUser(userId: string | number): Promise> { +export async function blockUser( + userId: string | number +): Promise> { const client = mtprotoService.getClient(); await mtprotoService.withFloodWaitHandling(async () => { diff --git a/src/lib/mcp/telegram/api/clearDraft.ts b/src/lib/telegram/api/clearDraft.ts similarity index 77% rename from src/lib/mcp/telegram/api/clearDraft.ts rename to src/lib/telegram/api/clearDraft.ts index 75c4a028e..af4b8ac6c 100644 --- a/src/lib/mcp/telegram/api/clearDraft.ts +++ b/src/lib/telegram/api/clearDraft.ts @@ -2,13 +2,13 @@ * API: Clear draft */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; export async function clearDraft( - chatId: string | number, + chatId: string | number ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -16,9 +16,7 @@ export async function clearDraft( } const client = mtprotoService.getClient(); - const entity = chat.username - ? `@${chat.username.replace("@", "")}` - : chat.id; + const entity = chat.username ? `@${chat.username.replace("@", "")}` : chat.id; await mtprotoService.withFloodWaitHandling(async () => { const inputPeer = await client.getInputEntity(entity); @@ -26,7 +24,7 @@ export async function clearDraft( new Api.messages.SaveDraft({ peer: inputPeer, message: "", - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/createChannel.ts b/src/lib/telegram/api/createChannel.ts similarity index 88% rename from src/lib/mcp/telegram/api/createChannel.ts rename to src/lib/telegram/api/createChannel.ts index de99e18ff..ccdd961f0 100644 --- a/src/lib/mcp/telegram/api/createChannel.ts +++ b/src/lib/telegram/api/createChannel.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import type { ResultWithChats } from "./apiResultTypes"; @@ -7,7 +7,7 @@ import { narrow } from "./apiCastHelpers"; export async function createChannel( title: string, about?: string, - megagroup?: boolean, + megagroup?: boolean ): Promise> { const client = mtprotoService.getClient(); @@ -18,7 +18,7 @@ export async function createChannel( about: about ?? "", megagroup: megagroup ?? false, broadcast: !megagroup, - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/createGroup.ts b/src/lib/telegram/api/createGroup.ts similarity index 90% rename from src/lib/mcp/telegram/api/createGroup.ts rename to src/lib/telegram/api/createGroup.ts index cde5df2b1..aa70195ae 100644 --- a/src/lib/mcp/telegram/api/createGroup.ts +++ b/src/lib/telegram/api/createGroup.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import type { ResultWithChats } from "./apiResultTypes"; @@ -6,7 +6,7 @@ import { toInputUser, narrow } from "./apiCastHelpers"; export async function createGroup( title: string, - userIds: string[], + userIds: string[] ): Promise> { if (userIds.length === 0) { throw new Error("user_ids must not be empty"); diff --git a/src/lib/mcp/telegram/api/createPoll.ts b/src/lib/telegram/api/createPoll.ts similarity index 86% rename from src/lib/mcp/telegram/api/createPoll.ts rename to src/lib/telegram/api/createPoll.ts index e21dec8db..a3847be29 100644 --- a/src/lib/mcp/telegram/api/createPoll.ts +++ b/src/lib/telegram/api/createPoll.ts @@ -2,7 +2,7 @@ * API: Create poll */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; @@ -11,7 +11,7 @@ import bigInt from "big-integer"; export async function createPoll( chatId: string | number, question: string, - options: string[], + options: string[] ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -19,9 +19,7 @@ export async function createPoll( } const client = mtprotoService.getClient(); - const entity = chat.username - ? `@${chat.username.replace("@", "")}` - : chat.id; + const entity = chat.username ? `@${chat.username.replace("@", "")}` : chat.id; await mtprotoService.withFloodWaitHandling(async () => { const inputPeer = await client.getInputEntity(entity); @@ -40,13 +38,13 @@ export async function createPoll( new Api.PollAnswer({ text: new Api.TextWithEntities({ text: opt, entities: [] }), option: Buffer.from([i]), - }), + }) ), }), }), message: "", randomId: bigInt(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)), - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/deleteChatPhoto.ts b/src/lib/telegram/api/deleteChatPhoto.ts similarity index 90% rename from src/lib/mcp/telegram/api/deleteChatPhoto.ts rename to src/lib/telegram/api/deleteChatPhoto.ts index 884ddd2c5..9ebd885f2 100644 --- a/src/lib/mcp/telegram/api/deleteChatPhoto.ts +++ b/src/lib/telegram/api/deleteChatPhoto.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; @@ -6,7 +6,7 @@ import bigInt from "big-integer"; import { toInputChannel } from "./apiCastHelpers"; export async function deleteChatPhoto( - chatId: string | number, + chatId: string | number ): Promise> { const chat = getChatById(chatId); if (!chat) throw new Error(`Chat not found: ${chatId}`); @@ -21,7 +21,7 @@ export async function deleteChatPhoto( new Api.channels.EditPhoto({ channel: toInputChannel(inputChannel), photo: new Api.InputChatPhotoEmpty(), - }), + }) ); }); } else { @@ -30,7 +30,7 @@ export async function deleteChatPhoto( new Api.messages.EditChatPhoto({ chatId: bigInt(chat.id), photo: new Api.InputChatPhotoEmpty(), - }), + }) ); }); } diff --git a/src/lib/mcp/telegram/api/deleteContact.ts b/src/lib/telegram/api/deleteContact.ts similarity index 72% rename from src/lib/mcp/telegram/api/deleteContact.ts rename to src/lib/telegram/api/deleteContact.ts index e2867a718..96540dd41 100644 --- a/src/lib/mcp/telegram/api/deleteContact.ts +++ b/src/lib/telegram/api/deleteContact.ts @@ -1,9 +1,11 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import { toInputUser } from "./apiCastHelpers"; -export async function deleteContact(userId: string | number): Promise> { +export async function deleteContact( + userId: string | number +): Promise> { const client = mtprotoService.getClient(); await mtprotoService.withFloodWaitHandling(async () => { @@ -11,7 +13,7 @@ export async function deleteContact(userId: string | number): Promise> { const chat = getChatById(chatId); if (!chat) { throw new Error(`Chat not found: ${chatId}`); } - const entity = chat.username - ? `@${chat.username.replace("@", "")}` - : chat.id; + const entity = chat.username ? `@${chat.username.replace("@", "")}` : chat.id; const client = mtprotoService.getClient(); await mtprotoService.withFloodWaitHandling(async () => { diff --git a/src/lib/mcp/telegram/api/deleteProfilePhoto.ts b/src/lib/telegram/api/deleteProfilePhoto.ts similarity index 92% rename from src/lib/mcp/telegram/api/deleteProfilePhoto.ts rename to src/lib/telegram/api/deleteProfilePhoto.ts index 0b5628663..bd70adf1d 100644 --- a/src/lib/mcp/telegram/api/deleteProfilePhoto.ts +++ b/src/lib/telegram/api/deleteProfilePhoto.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import bigInt from "big-integer"; @@ -15,7 +15,7 @@ export async function deleteProfilePhoto(): Promise> { offset: 0, maxId: bigInt(0), limit: 1, - }), + }) ); }); @@ -40,7 +40,7 @@ export async function deleteProfilePhoto(): Promise> { fileReference: photo.fileReference, }), ], - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/demoteAdmin.ts b/src/lib/telegram/api/demoteAdmin.ts similarity index 90% rename from src/lib/mcp/telegram/api/demoteAdmin.ts rename to src/lib/telegram/api/demoteAdmin.ts index 3ef52349d..db9216c8f 100644 --- a/src/lib/mcp/telegram/api/demoteAdmin.ts +++ b/src/lib/telegram/api/demoteAdmin.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import { toInputChannel, toInputUser } from "./apiCastHelpers"; @@ -6,7 +6,7 @@ import { getChatById } from "./helpers"; export async function demoteAdmin( chatId: string | number, - userId: string | number, + userId: string | number ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -15,7 +15,7 @@ export async function demoteAdmin( if (chat.type !== "channel" && chat.type !== "supergroup") { throw new Error( - "Admin demotion is only available for channels/supergroups.", + "Admin demotion is only available for channels/supergroups." ); } @@ -31,7 +31,7 @@ export async function demoteAdmin( userId: toInputUser(inputUser), adminRights: new Api.ChatAdminRights({}), rank: "", - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/editChatPhoto.ts b/src/lib/telegram/api/editChatPhoto.ts similarity index 100% rename from src/lib/mcp/telegram/api/editChatPhoto.ts rename to src/lib/telegram/api/editChatPhoto.ts diff --git a/src/lib/mcp/telegram/api/editChatTitle.ts b/src/lib/telegram/api/editChatTitle.ts similarity index 90% rename from src/lib/mcp/telegram/api/editChatTitle.ts rename to src/lib/telegram/api/editChatTitle.ts index 0e4575f7b..23a499cea 100644 --- a/src/lib/mcp/telegram/api/editChatTitle.ts +++ b/src/lib/telegram/api/editChatTitle.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; @@ -7,7 +7,7 @@ import { toInputChannel } from "./apiCastHelpers"; export async function editChatTitle( chatId: string | number, - title: string, + title: string ): Promise> { const chat = getChatById(chatId); if (!chat) throw new Error(`Chat not found: ${chatId}`); @@ -22,7 +22,7 @@ export async function editChatTitle( new Api.channels.EditTitle({ channel: toInputChannel(inputChannel), title, - }), + }) ); }); } else { @@ -31,7 +31,7 @@ export async function editChatTitle( new Api.messages.EditChatTitle({ chatId: bigInt(chat.id), title, - }), + }) ); }); } diff --git a/src/lib/mcp/telegram/api/editMessage.ts b/src/lib/telegram/api/editMessage.ts similarity index 76% rename from src/lib/mcp/telegram/api/editMessage.ts rename to src/lib/telegram/api/editMessage.ts index 337157b11..09613e4e8 100644 --- a/src/lib/mcp/telegram/api/editMessage.ts +++ b/src/lib/telegram/api/editMessage.ts @@ -2,23 +2,21 @@ * API: Edit message */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; export async function editMessage( chatId: string | number, messageId: number, - newText: string, + newText: string ): Promise> { const chat = getChatById(chatId); if (!chat) { throw new Error(`Chat not found: ${chatId}`); } - const entity = chat.username - ? `@${chat.username.replace("@", "")}` - : chat.id; + const entity = chat.username ? `@${chat.username.replace("@", "")}` : chat.id; const client = mtprotoService.getClient(); await mtprotoService.withFloodWaitHandling(async () => { diff --git a/src/lib/mcp/telegram/api/exportChatInvite.ts b/src/lib/telegram/api/exportChatInvite.ts similarity index 91% rename from src/lib/mcp/telegram/api/exportChatInvite.ts rename to src/lib/telegram/api/exportChatInvite.ts index d295f08db..4c3a3f675 100644 --- a/src/lib/mcp/telegram/api/exportChatInvite.ts +++ b/src/lib/telegram/api/exportChatInvite.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; @@ -9,7 +9,7 @@ export async function exportChatInvite( chatId: string | number, title?: string, expireDate?: number, - usageLimit?: number, + usageLimit?: number ): Promise> { const chat = getChatById(chatId); if (!chat) throw new Error(`Chat not found: ${chatId}`); @@ -25,7 +25,7 @@ export async function exportChatInvite( title: title ?? undefined, expireDate: expireDate ?? undefined, usageLimit: usageLimit ?? undefined, - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/exportContacts.ts b/src/lib/telegram/api/exportContacts.ts similarity index 85% rename from src/lib/mcp/telegram/api/exportContacts.ts rename to src/lib/telegram/api/exportContacts.ts index f28afa42f..3dff66fc7 100644 --- a/src/lib/mcp/telegram/api/exportContacts.ts +++ b/src/lib/telegram/api/exportContacts.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import bigInt from "big-integer"; @@ -12,9 +12,7 @@ export interface ExportedContact { phone: string; } -export async function exportContacts(): Promise< - ApiResult -> { +export async function exportContacts(): Promise> { const client = mtprotoService.getClient(); const result = await mtprotoService.withFloodWaitHandling(async () => { diff --git a/src/lib/mcp/telegram/api/forwardMessage.ts b/src/lib/telegram/api/forwardMessage.ts similarity index 91% rename from src/lib/mcp/telegram/api/forwardMessage.ts rename to src/lib/telegram/api/forwardMessage.ts index bfbfc939b..8eb2b1431 100644 --- a/src/lib/mcp/telegram/api/forwardMessage.ts +++ b/src/lib/telegram/api/forwardMessage.ts @@ -2,14 +2,14 @@ * API: Forward message */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; export async function forwardMessage( fromChatId: string | number, toChatId: string | number, - messageId: number, + messageId: number ): Promise> { const fromChat = getChatById(fromChatId); if (!fromChat) { diff --git a/src/lib/mcp/telegram/api/getAdmins.ts b/src/lib/telegram/api/getAdmins.ts similarity index 91% rename from src/lib/mcp/telegram/api/getAdmins.ts rename to src/lib/telegram/api/getAdmins.ts index ad81f1301..fc4bbddcf 100644 --- a/src/lib/mcp/telegram/api/getAdmins.ts +++ b/src/lib/telegram/api/getAdmins.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import bigInt from "big-integer"; @@ -13,7 +13,9 @@ export interface Admin { username?: string; } -export async function getAdmins(chatId: string | number): Promise> { +export async function getAdmins( + chatId: string | number +): Promise> { const chat = getChatById(chatId); if (!chat) { throw new Error(`Chat not found: ${chatId}`); @@ -34,7 +36,7 @@ export async function getAdmins(chatId: string | number): Promise { return client.invoke( - new Api.messages.GetFullChat({ chatId: bigInt(chat.id) }), + new Api.messages.GetFullChat({ chatId: bigInt(chat.id) }) ); }); if (result && "users" in result && Array.isArray(result.users)) { diff --git a/src/lib/mcp/telegram/api/getBannedUsers.ts b/src/lib/telegram/api/getBannedUsers.ts similarity index 94% rename from src/lib/mcp/telegram/api/getBannedUsers.ts rename to src/lib/telegram/api/getBannedUsers.ts index 7bba4a8be..22a846e52 100644 --- a/src/lib/mcp/telegram/api/getBannedUsers.ts +++ b/src/lib/telegram/api/getBannedUsers.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import bigInt from "big-integer"; @@ -15,7 +15,7 @@ export interface BannedUser { export async function getBannedUsers( chatId: string | number, - limit: number = 50, + limit: number = 50 ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -24,7 +24,7 @@ export async function getBannedUsers( if (chat.type !== "channel" && chat.type !== "supergroup") { throw new Error( - "Banned users list is only available for channels/supergroups.", + "Banned users list is only available for channels/supergroups." ); } @@ -40,7 +40,7 @@ export async function getBannedUsers( offset: 0, limit, hash: bigInt(0), - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/getBlockedUsers.ts b/src/lib/telegram/api/getBlockedUsers.ts similarity index 92% rename from src/lib/mcp/telegram/api/getBlockedUsers.ts rename to src/lib/telegram/api/getBlockedUsers.ts index dd8ee9814..53ba0c5dc 100644 --- a/src/lib/mcp/telegram/api/getBlockedUsers.ts +++ b/src/lib/telegram/api/getBlockedUsers.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import type { ApiUser } from "./apiResultTypes"; @@ -11,7 +11,7 @@ export interface BlockedUser { } export async function getBlockedUsers( - limit: number = 50, + limit: number = 50 ): Promise> { const client = mtprotoService.getClient(); diff --git a/src/lib/mcp/telegram/api/getBotInfo.ts b/src/lib/telegram/api/getBotInfo.ts similarity index 89% rename from src/lib/mcp/telegram/api/getBotInfo.ts rename to src/lib/telegram/api/getBotInfo.ts index e879f7e74..94c4bb7f0 100644 --- a/src/lib/mcp/telegram/api/getBotInfo.ts +++ b/src/lib/telegram/api/getBotInfo.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import type { FullUserResult } from "./apiResultTypes"; @@ -16,14 +16,14 @@ export interface BotInfo { } export async function getBotInfo( - botId: string | number, + botId: string | number ): Promise> { const client = mtprotoService.getClient(); const result = await mtprotoService.withFloodWaitHandling(async () => { const inputUser = await client.getInputEntity(botId); return client.invoke( - new Api.users.GetFullUser({ id: toInputUser(inputUser) }), + new Api.users.GetFullUser({ id: toInputUser(inputUser) }) ); }); diff --git a/src/lib/mcp/telegram/api/getChat.ts b/src/lib/telegram/api/getChat.ts similarity index 91% rename from src/lib/mcp/telegram/api/getChat.ts rename to src/lib/telegram/api/getChat.ts index 32a362604..f908ecaf4 100644 --- a/src/lib/mcp/telegram/api/getChat.ts +++ b/src/lib/telegram/api/getChat.ts @@ -2,11 +2,11 @@ * API: Get chat — cache-first with API fallback (hybrid). */ -import { mtprotoService } from "../../../../services/mtprotoService"; -import { enforceRateLimit } from "../../rateLimiter"; +import { mtprotoService } from "../../../services/mtprotoService"; +import { enforceRateLimit } from "../../mcp/rateLimiter"; import { getChatById, formatEntity } from "./helpers"; import type { ApiResult } from "./types"; -import type { TelegramChat } from "../../../../store/telegram/types"; +import type { TelegramChat } from "../../../store/telegram/types"; import { updateChatInState } from "../state"; export interface ChatInfo { @@ -26,7 +26,7 @@ export interface ChatInfo { } export async function getChat( - chatId: string | number, + chatId: string | number ): Promise> { // 1. Try cache const chat = getChatById(chatId); @@ -111,10 +111,10 @@ export async function getChat( className === "User" ? "private" : className === "Channel" - ? raw.megagroup - ? "supergroup" - : "channel" - : "group"; + ? raw.megagroup + ? "supergroup" + : "channel" + : "group"; updateChatInState({ id: info.id, title: info.name, diff --git a/src/lib/mcp/telegram/api/getChats.ts b/src/lib/telegram/api/getChats.ts similarity index 88% rename from src/lib/mcp/telegram/api/getChats.ts rename to src/lib/telegram/api/getChats.ts index abe34eece..e451e2cbd 100644 --- a/src/lib/mcp/telegram/api/getChats.ts +++ b/src/lib/telegram/api/getChats.ts @@ -2,19 +2,17 @@ * API: Get chats — cache-first with API fallback. */ -import type { TelegramChat } from "../../../../store/telegram/types"; -import { mtprotoService } from "../../../../services/mtprotoService"; +import type { TelegramChat } from "../../../store/telegram/types"; +import { mtprotoService } from "../../../services/mtprotoService"; import { Api } from "telegram"; import bigInt from "big-integer"; -import { enforceRateLimit } from "../../rateLimiter"; +import { enforceRateLimit } from "../../mcp/rateLimiter"; import { getOrderedChats, apiDialogToTelegramChat } from "./helpers"; import type { ApiResult } from "./types"; import { updateChatsInState, updateUsersFromApiUsers } from "../state"; import type { ApiUser } from "./apiResultTypes"; -export async function getChats( - limit = 20, -): Promise> { +export async function getChats(limit = 20): Promise> { // 1. Try cache const cached = getOrderedChats(limit); if (cached.length > 0) return { data: cached, fromCache: true }; @@ -38,7 +36,7 @@ export async function getChats( offsetPeer: new Api.InputPeerEmpty(), limit, hash: bigInt(0), - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/getContactChats.ts b/src/lib/telegram/api/getContactChats.ts similarity index 82% rename from src/lib/mcp/telegram/api/getContactChats.ts rename to src/lib/telegram/api/getContactChats.ts index 3d7317f9e..ce8e8ae8a 100644 --- a/src/lib/mcp/telegram/api/getContactChats.ts +++ b/src/lib/telegram/api/getContactChats.ts @@ -2,8 +2,8 @@ * API: Get contact chats — cache-only. */ -import { store } from "../../../../store"; -import { selectOrderedChats } from "../../../../store/telegramSelectors"; +import { store } from "../../../store"; +import { selectOrderedChats } from "../../../store/telegramSelectors"; import type { ApiResult } from "./types"; export interface ContactChat { diff --git a/src/lib/mcp/telegram/api/getContactIds.ts b/src/lib/telegram/api/getContactIds.ts similarity index 85% rename from src/lib/mcp/telegram/api/getContactIds.ts rename to src/lib/telegram/api/getContactIds.ts index bbe60bf2a..b065adacb 100644 --- a/src/lib/mcp/telegram/api/getContactIds.ts +++ b/src/lib/telegram/api/getContactIds.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import bigInt from "big-integer"; @@ -19,7 +19,7 @@ export async function getContactIds(): Promise> { } const ids = narrow(result).map((c) => - String(typeof c === "number" ? c : (c.userId ?? c)), + String(typeof c === "number" ? c : c.userId ?? c) ); return { data: ids, fromCache: false }; diff --git a/src/lib/mcp/telegram/api/getCurrentUser.ts b/src/lib/telegram/api/getCurrentUser.ts similarity index 88% rename from src/lib/mcp/telegram/api/getCurrentUser.ts rename to src/lib/telegram/api/getCurrentUser.ts index 90a96da12..f22997ced 100644 --- a/src/lib/mcp/telegram/api/getCurrentUser.ts +++ b/src/lib/telegram/api/getCurrentUser.ts @@ -2,9 +2,9 @@ * API: Get current user — cache-first with API fallback. */ -import type { TelegramUser } from "../../../../store/telegram/types"; -import { mtprotoService } from "../../../../services/mtprotoService"; -import { enforceRateLimit } from "../../rateLimiter"; +import type { TelegramUser } from "../../../store/telegram/types"; +import { mtprotoService } from "../../../services/mtprotoService"; +import { enforceRateLimit } from "../../mcp/rateLimiter"; import { getCurrentUser as getCachedCurrentUser } from "./helpers"; import type { ApiResult } from "./types"; import { updateCurrentUserInState } from "../state"; diff --git a/src/lib/mcp/telegram/api/getDirectChatByContact.ts b/src/lib/telegram/api/getDirectChatByContact.ts similarity index 81% rename from src/lib/mcp/telegram/api/getDirectChatByContact.ts rename to src/lib/telegram/api/getDirectChatByContact.ts index 5b606ad0b..4619b3dad 100644 --- a/src/lib/mcp/telegram/api/getDirectChatByContact.ts +++ b/src/lib/telegram/api/getDirectChatByContact.ts @@ -2,8 +2,8 @@ * API: Get direct chat by contact — cache-only. */ -import { store } from "../../../../store"; -import { selectOrderedChats } from "../../../../store/telegramSelectors"; +import { store } from "../../../store"; +import { selectOrderedChats } from "../../../store/telegramSelectors"; import type { ApiResult } from "./types"; export interface DirectChat { @@ -13,13 +13,13 @@ export interface DirectChat { } export async function getDirectChatByContact( - userId: string | number, + userId: string | number ): Promise> { const state = store.getState(); const chats = selectOrderedChats(state); const dmChat = chats.find( - (c) => c.type === "private" && String(c.id) === String(userId), + (c) => c.type === "private" && String(c.id) === String(userId) ); if (!dmChat) return { data: undefined, fromCache: true }; diff --git a/src/lib/mcp/telegram/api/getDrafts.ts b/src/lib/telegram/api/getDrafts.ts similarity index 94% rename from src/lib/mcp/telegram/api/getDrafts.ts rename to src/lib/telegram/api/getDrafts.ts index 442fde818..dcb2a50ac 100644 --- a/src/lib/mcp/telegram/api/getDrafts.ts +++ b/src/lib/telegram/api/getDrafts.ts @@ -2,7 +2,7 @@ * API: Get all drafts */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import type { UpdatesResult } from "./apiResultTypes"; import { Api } from "telegram"; diff --git a/src/lib/mcp/telegram/api/getGifSearch.ts b/src/lib/telegram/api/getGifSearch.ts similarity index 92% rename from src/lib/mcp/telegram/api/getGifSearch.ts rename to src/lib/telegram/api/getGifSearch.ts index c69472d9e..925071ae8 100644 --- a/src/lib/mcp/telegram/api/getGifSearch.ts +++ b/src/lib/telegram/api/getGifSearch.ts @@ -4,7 +4,7 @@ * Uses the @gif bot to search for GIFs. */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import type { InlineBotResults } from "./apiResultTypes"; import { toInputUser, narrow } from "./apiCastHelpers"; @@ -17,7 +17,7 @@ export interface GifResult { export async function getGifSearch( query: string, - limit: number, + limit: number ): Promise> { const client = mtprotoService.getClient(); @@ -29,7 +29,7 @@ export async function getGifSearch( peer: new Api.InputPeerSelf(), query, offset: "", - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/getInviteLink.ts b/src/lib/telegram/api/getInviteLink.ts similarity index 89% rename from src/lib/mcp/telegram/api/getInviteLink.ts rename to src/lib/telegram/api/getInviteLink.ts index bbffdec6f..0a8a54f81 100644 --- a/src/lib/mcp/telegram/api/getInviteLink.ts +++ b/src/lib/telegram/api/getInviteLink.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; @@ -6,7 +6,7 @@ import type { ChatInviteResult } from "./apiResultTypes"; import { narrow } from "./apiCastHelpers"; export async function getInviteLink( - chatId: string | number, + chatId: string | number ): Promise> { const chat = getChatById(chatId); if (!chat) throw new Error(`Chat not found: ${chatId}`); @@ -20,7 +20,7 @@ export async function getInviteLink( new Api.messages.ExportChatInvite({ peer: inputPeer, legacyRevokePermanent: true, - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/getLastInteraction.ts b/src/lib/telegram/api/getLastInteraction.ts similarity index 100% rename from src/lib/mcp/telegram/api/getLastInteraction.ts rename to src/lib/telegram/api/getLastInteraction.ts diff --git a/src/lib/mcp/telegram/api/getMediaInfo.ts b/src/lib/telegram/api/getMediaInfo.ts similarity index 100% rename from src/lib/mcp/telegram/api/getMediaInfo.ts rename to src/lib/telegram/api/getMediaInfo.ts diff --git a/src/lib/mcp/telegram/api/getMessageReactions.ts b/src/lib/telegram/api/getMessageReactions.ts similarity index 89% rename from src/lib/mcp/telegram/api/getMessageReactions.ts rename to src/lib/telegram/api/getMessageReactions.ts index 1d164be33..a90ddf28d 100644 --- a/src/lib/mcp/telegram/api/getMessageReactions.ts +++ b/src/lib/telegram/api/getMessageReactions.ts @@ -2,7 +2,7 @@ * API: Get message reactions */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { updateMessageReactionsInState } from "../state"; @@ -17,7 +17,7 @@ export interface ReactionData { export async function getMessageReactions( chatId: string | number, - messageId: number, + messageId: number ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -25,9 +25,7 @@ export async function getMessageReactions( } const client = mtprotoService.getClient(); - const entity = chat.username - ? `@${chat.username.replace("@", "")}` - : chat.id; + const entity = chat.username ? `@${chat.username.replace("@", "")}` : chat.id; const result = await mtprotoService.withFloodWaitHandling(async () => { const inputPeer = await client.getInputEntity(entity); @@ -35,7 +33,7 @@ export async function getMessageReactions( new Api.messages.GetMessagesReactions({ peer: inputPeer, id: [messageId], - }), + }) ); }); @@ -60,7 +58,7 @@ export async function getMessageReactions( updateMessageReactionsInState( chat.id, String(messageId), - reactions.map((r) => ({ emoticon: r.emoji, count: r.count })), + reactions.map((r) => ({ emoticon: r.emoji, count: r.count })) ); } diff --git a/src/lib/mcp/telegram/api/getMessages.ts b/src/lib/telegram/api/getMessages.ts similarity index 89% rename from src/lib/mcp/telegram/api/getMessages.ts rename to src/lib/telegram/api/getMessages.ts index 114844d5c..3541bc032 100644 --- a/src/lib/mcp/telegram/api/getMessages.ts +++ b/src/lib/telegram/api/getMessages.ts @@ -2,11 +2,11 @@ * API: Get messages — cache-first with API fallback. */ -import type { TelegramMessage } from "../../../../store/telegram/types"; -import { mtprotoService } from "../../../../services/mtprotoService"; +import type { TelegramMessage } from "../../../store/telegram/types"; +import { mtprotoService } from "../../../services/mtprotoService"; import { Api } from "telegram"; import bigInt from "big-integer"; -import { enforceRateLimit } from "../../rateLimiter"; +import { enforceRateLimit } from "../../mcp/rateLimiter"; import { getChatById, getCachedMessages, @@ -19,7 +19,7 @@ import type { ApiUser } from "./apiResultTypes"; export async function getMessages( chatId: string | number, limit = 20, - offset = 0, + offset = 0 ): Promise> { // 1. Try cache const cached = getCachedMessages(chatId, limit, offset); @@ -55,14 +55,12 @@ export async function getMessages( maxId: 0, minId: 0, hash: bigInt(0), - }), + }) ); }); if ("messages" in result && Array.isArray(result.messages)) { - const messages = ( - result.messages as unknown as Record[] - ) + const messages = (result.messages as unknown as Record[]) .filter((m) => m.className !== "MessageEmpty") .map((m) => apiMessageToTelegramMessage(m, chat.id)); diff --git a/src/lib/mcp/telegram/api/getParticipants.ts b/src/lib/telegram/api/getParticipants.ts similarity index 94% rename from src/lib/mcp/telegram/api/getParticipants.ts rename to src/lib/telegram/api/getParticipants.ts index 75bbfba95..576aeb1db 100644 --- a/src/lib/mcp/telegram/api/getParticipants.ts +++ b/src/lib/telegram/api/getParticipants.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import bigInt from "big-integer"; @@ -15,7 +15,7 @@ export interface Participant { export async function getParticipants( chatId: string | number, - limit: number = 50, + limit: number = 50 ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -37,7 +37,7 @@ export async function getParticipants( offset: 0, limit, hash: bigInt(0), - }), + }) ); }); if (result && "users" in result && Array.isArray(result.users)) { @@ -46,7 +46,7 @@ export async function getParticipants( } else { const result = await mtprotoService.withFloodWaitHandling(async () => { return client.invoke( - new Api.messages.GetFullChat({ chatId: bigInt(chat.id) }), + new Api.messages.GetFullChat({ chatId: bigInt(chat.id) }) ); }); if (result && "users" in result && Array.isArray(result.users)) { diff --git a/src/lib/mcp/telegram/api/getPinnedMessages.ts b/src/lib/telegram/api/getPinnedMessages.ts similarity index 79% rename from src/lib/mcp/telegram/api/getPinnedMessages.ts rename to src/lib/telegram/api/getPinnedMessages.ts index cc41b0d06..398de5acf 100644 --- a/src/lib/mcp/telegram/api/getPinnedMessages.ts +++ b/src/lib/telegram/api/getPinnedMessages.ts @@ -2,7 +2,7 @@ * API: Get pinned messages (API-first with cache fallback) */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import type { ApiMessage } from "./apiResultTypes"; @@ -17,16 +17,14 @@ export interface PinnedMessage { } export async function getPinnedMessages( - chatId: string | number, + chatId: string | number ): Promise> { const chat = getChatById(chatId); if (!chat) { throw new Error(`Chat not found: ${chatId}`); } - const entity = chat.username - ? `@${chat.username.replace("@", "")}` - : chat.id; + const entity = chat.username ? `@${chat.username.replace("@", "")}` : chat.id; const client = mtprotoService.getClient(); // Try API first @@ -45,17 +43,17 @@ export async function getPinnedMessages( maxId: 0, minId: 0, hash: bigInt(0), - }), + }) ); if ("messages" in result && Array.isArray(result.messages)) { - const pinnedMessages = narrow(result.messages).map((msg) => ({ - id: msg.id ?? "?", - date: msg.date - ? new Date(msg.date * 1000).toISOString() - : "unknown", - text: msg.message ?? "[Media/No text]", - })); + const pinnedMessages = narrow(result.messages).map( + (msg) => ({ + id: msg.id ?? "?", + date: msg.date ? new Date(msg.date * 1000).toISOString() : "unknown", + text: msg.message ?? "[Media/No text]", + }) + ); return { data: pinnedMessages, fromCache: false }; } } catch { diff --git a/src/lib/mcp/telegram/api/getPrivacySettings.ts b/src/lib/telegram/api/getPrivacySettings.ts similarity index 86% rename from src/lib/mcp/telegram/api/getPrivacySettings.ts rename to src/lib/telegram/api/getPrivacySettings.ts index 407e8722e..685dfbf17 100644 --- a/src/lib/mcp/telegram/api/getPrivacySettings.ts +++ b/src/lib/telegram/api/getPrivacySettings.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import type { PrivacyResult } from "./apiResultTypes"; @@ -27,14 +27,14 @@ const keyMap: Record = { }; export async function getPrivacySettings( - key: string = "last_seen", + key: string = "last_seen" ): Promise> { if (!(key in keyMap)) { throw new Error( "Unknown privacy key: " + key + ". Valid keys: " + - Object.keys(keyMap).join(", "), + Object.keys(keyMap).join(", ") ); } @@ -42,7 +42,9 @@ export async function getPrivacySettings( const client = mtprotoService.getClient(); const result = await mtprotoService.withFloodWaitHandling(async () => { - return client.invoke(new Api.account.GetPrivacy({ key: keyMap[privacyKey] })); + return client.invoke( + new Api.account.GetPrivacy({ key: keyMap[privacyKey] }) + ); }); const rules = narrow(result)?.rules; diff --git a/src/lib/mcp/telegram/api/getRecentActions.ts b/src/lib/telegram/api/getRecentActions.ts similarity index 94% rename from src/lib/mcp/telegram/api/getRecentActions.ts rename to src/lib/telegram/api/getRecentActions.ts index 8421017c7..3fddbbf9d 100644 --- a/src/lib/mcp/telegram/api/getRecentActions.ts +++ b/src/lib/telegram/api/getRecentActions.ts @@ -4,7 +4,7 @@ * Fetches admin log from channels/supergroups only. */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import type { AdminLogResult } from "./apiResultTypes"; @@ -19,7 +19,7 @@ export interface AdminActionResult { export async function getRecentActions( chatId: string | number, - limit: number, + limit: number ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -28,7 +28,7 @@ export async function getRecentActions( if (chat.type !== "channel" && chat.type !== "supergroup") { throw new Error( - "Recent actions are only available for channels/supergroups.", + "Recent actions are only available for channels/supergroups." ); } @@ -44,7 +44,7 @@ export async function getRecentActions( maxId: bigInt(0), minId: bigInt(0), limit, - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/getStickerSets.ts b/src/lib/telegram/api/getStickerSets.ts similarity index 86% rename from src/lib/mcp/telegram/api/getStickerSets.ts rename to src/lib/telegram/api/getStickerSets.ts index 9c33504ff..cf0ef9a6e 100644 --- a/src/lib/mcp/telegram/api/getStickerSets.ts +++ b/src/lib/telegram/api/getStickerSets.ts @@ -4,7 +4,7 @@ * Fetches all available sticker sets for the current user. */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import type { StickerSetsResult } from "./apiResultTypes"; import { narrow } from "./apiCastHelpers"; @@ -17,9 +17,7 @@ export interface StickerSetResult { count: number; } -export async function getStickerSets(): Promise< - ApiResult -> { +export async function getStickerSets(): Promise> { const client = mtprotoService.getClient(); const result = await mtprotoService.withFloodWaitHandling(async () => { diff --git a/src/lib/mcp/telegram/api/getUserPhotos.ts b/src/lib/telegram/api/getUserPhotos.ts similarity index 84% rename from src/lib/mcp/telegram/api/getUserPhotos.ts rename to src/lib/telegram/api/getUserPhotos.ts index 80919708f..4941115d3 100644 --- a/src/lib/mcp/telegram/api/getUserPhotos.ts +++ b/src/lib/telegram/api/getUserPhotos.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import bigInt from "big-integer"; @@ -12,7 +12,7 @@ export interface UserPhoto { export async function getUserPhotos( userId: string | number, - limit: number = 10, + limit: number = 10 ): Promise> { const client = mtprotoService.getClient(); @@ -24,7 +24,7 @@ export async function getUserPhotos( offset: 0, maxId: bigInt(0), limit, - }), + }) ); }); @@ -39,9 +39,7 @@ export async function getUserPhotos( const photos = narrow(result.photos).map((photo) => ({ id: String(photo.id), - date: photo.date - ? new Date(photo.date * 1000).toISOString() - : "unknown", + date: photo.date ? new Date(photo.date * 1000).toISOString() : "unknown", })); return { data: photos, fromCache: false }; diff --git a/src/lib/mcp/telegram/api/getUserStatus.ts b/src/lib/telegram/api/getUserStatus.ts similarity index 92% rename from src/lib/mcp/telegram/api/getUserStatus.ts rename to src/lib/telegram/api/getUserStatus.ts index beca6bed8..ed9ed0498 100644 --- a/src/lib/mcp/telegram/api/getUserStatus.ts +++ b/src/lib/telegram/api/getUserStatus.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import type { ApiUser } from "./apiResultTypes"; @@ -13,14 +13,14 @@ export interface UserStatus { } export async function getUserStatus( - userId: string | number, + userId: string | number ): Promise> { const client = mtprotoService.getClient(); const result = await mtprotoService.withFloodWaitHandling(async () => { const inputUser = await client.getInputEntity(userId); return client.invoke( - new Api.users.GetUsers({ id: [toInputUser(inputUser)] }), + new Api.users.GetUsers({ id: [toInputUser(inputUser)] }) ); }); diff --git a/src/lib/mcp/telegram/api/helpers.ts b/src/lib/telegram/api/helpers.ts similarity index 92% rename from src/lib/mcp/telegram/api/helpers.ts rename to src/lib/telegram/api/helpers.ts index 071f588ad..6459cc859 100644 --- a/src/lib/mcp/telegram/api/helpers.ts +++ b/src/lib/telegram/api/helpers.ts @@ -5,17 +5,17 @@ * These are used by both api/ functions and (transitionally) by tool wrappers. */ -import { store } from "../../../../store"; +import { store } from "../../../store"; import { selectOrderedChats, selectCurrentUser, selectTelegramUserState, -} from "../../../../store/telegramSelectors"; +} from "../../../store/telegramSelectors"; import type { TelegramChat, TelegramUser, TelegramMessage, -} from "../../../../store/telegram/types"; +} from "../../../store/telegram/types"; // --------------------------------------------------------------------------- // Redux state helpers @@ -32,9 +32,7 @@ export function getTelegramState() { /** * Get chat by ID or username from Redux cache. */ -export function getChatById( - chatId: string | number, -): TelegramChat | undefined { +export function getChatById(chatId: string | number): TelegramChat | undefined { const state = getTelegramState(); const idStr = String(chatId); @@ -49,7 +47,7 @@ export function getChatById( return Object.values(state.chats).find( (c) => c.username && - (c.username === username || c.username === username.slice(1)), + (c.username === username || c.username === username.slice(1)) ); } @@ -59,9 +57,7 @@ export function getChatById( /** * Get user by ID (current user only; no full user cache). */ -export function getUserById( - userId: string | number, -): TelegramUser | undefined { +export function getUserById(userId: string | number): TelegramUser | undefined { const state = getTelegramState(); const current = state.currentUser; if (!current) return undefined; @@ -92,7 +88,7 @@ export function getOrderedChats(limit = 20): TelegramChat[] { export function getCachedMessages( chatId: string | number, limit = 20, - offset = 0, + offset = 0 ): TelegramMessage[] | undefined { const chat = getChatById(chatId); if (!chat) return undefined; @@ -145,7 +141,7 @@ export interface FormattedMessage { * Format entity (chat or user) for display. */ export function formatEntity( - entity: TelegramChat | TelegramUser, + entity: TelegramChat | TelegramUser ): FormattedEntity { if ("title" in entity) { const chat = entity as TelegramChat; @@ -153,8 +149,8 @@ export function formatEntity( chat.type === "channel" ? "channel" : chat.type === "supergroup" - ? "group" - : chat.type; + ? "group" + : chat.type; return { id: chat.id, name: chat.title ?? "Unknown", @@ -198,7 +194,7 @@ export function formatMessage(message: TelegramMessage): FormattedMessage { /** Convert a raw GramJS message to our TelegramMessage format */ export function apiMessageToTelegramMessage( msg: Record, - chatId: string, + chatId: string ): TelegramMessage { const fromId = msg.fromId && @@ -225,9 +221,7 @@ export function apiMessageToTelegramMessage( isEdited: msg.editDate != null, isForwarded: msg.fwdFrom != null, replyToMessageId: - replyTo?.replyToMsgId != null - ? String(replyTo.replyToMsgId) - : undefined, + replyTo?.replyToMsgId != null ? String(replyTo.replyToMsgId) : undefined, media: mediaInfo, }; } @@ -236,7 +230,7 @@ export function apiMessageToTelegramMessage( export function apiDialogToTelegramChat( dialog: Record, chatsById: Map>, - usersById: Map>, + usersById: Map> ): TelegramChat | undefined { const peer = dialog.peer as | { diff --git a/src/lib/mcp/telegram/api/importChatInvite.ts b/src/lib/telegram/api/importChatInvite.ts similarity index 87% rename from src/lib/mcp/telegram/api/importChatInvite.ts rename to src/lib/telegram/api/importChatInvite.ts index 7aae33aa1..ae652d582 100644 --- a/src/lib/mcp/telegram/api/importChatInvite.ts +++ b/src/lib/telegram/api/importChatInvite.ts @@ -1,11 +1,11 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import type { ResultWithChats } from "./apiResultTypes"; import { narrow } from "./apiCastHelpers"; export async function importChatInvite( - hash: string, + hash: string ): Promise> { const client = mtprotoService.getClient(); diff --git a/src/lib/mcp/telegram/api/importContacts.ts b/src/lib/telegram/api/importContacts.ts similarity index 91% rename from src/lib/mcp/telegram/api/importContacts.ts rename to src/lib/telegram/api/importContacts.ts index e6f831091..c172f932f 100644 --- a/src/lib/mcp/telegram/api/importContacts.ts +++ b/src/lib/telegram/api/importContacts.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import bigInt from "big-integer"; @@ -11,7 +11,7 @@ export interface ImportContactsResponse { } export async function importContacts( - contacts: ContactInput[], + contacts: ContactInput[] ): Promise> { if (!Array.isArray(contacts) || contacts.length === 0) { throw new Error("contacts array is required and must not be empty."); @@ -24,14 +24,14 @@ export async function importContacts( phone: String(c.phone ?? ""), firstName: String(c.first_name ?? ""), lastName: String(c.last_name ?? ""), - }), + }) ); const client = mtprotoService.getClient(); const result = await mtprotoService.withFloodWaitHandling(async () => { return client.invoke( - new Api.contacts.ImportContacts({ contacts: inputContacts }), + new Api.contacts.ImportContacts({ contacts: inputContacts }) ); }); diff --git a/src/lib/mcp/telegram/api/index.ts b/src/lib/telegram/api/index.ts similarity index 100% rename from src/lib/mcp/telegram/api/index.ts rename to src/lib/telegram/api/index.ts diff --git a/src/lib/mcp/telegram/api/inviteToGroup.ts b/src/lib/telegram/api/inviteToGroup.ts similarity index 92% rename from src/lib/mcp/telegram/api/inviteToGroup.ts rename to src/lib/telegram/api/inviteToGroup.ts index 9bf97c665..a204d1f34 100644 --- a/src/lib/mcp/telegram/api/inviteToGroup.ts +++ b/src/lib/telegram/api/inviteToGroup.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import bigInt from "big-integer"; @@ -7,7 +7,7 @@ import { getChatById } from "./helpers"; export async function inviteToGroup( chatId: string | number, - userIds: string[], + userIds: string[] ): Promise> { if (userIds.length === 0) { throw new Error("user_ids must not be empty"); @@ -35,7 +35,7 @@ export async function inviteToGroup( new Api.channels.InviteToChannel({ channel: toInputChannel(inputPeer), users, - }), + }) ); }); } else { @@ -46,7 +46,7 @@ export async function inviteToGroup( chatId: bigInt(chat.id), userId: user, fwdLimit: 100, - }), + }) ); }); } diff --git a/src/lib/mcp/telegram/api/joinChatByLink.ts b/src/lib/telegram/api/joinChatByLink.ts similarity index 90% rename from src/lib/mcp/telegram/api/joinChatByLink.ts rename to src/lib/telegram/api/joinChatByLink.ts index 5c6757076..6e3391e51 100644 --- a/src/lib/mcp/telegram/api/joinChatByLink.ts +++ b/src/lib/telegram/api/joinChatByLink.ts @@ -1,11 +1,11 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import type { ResultWithChats } from "./apiResultTypes"; import { narrow } from "./apiCastHelpers"; export async function joinChatByLink( - link: string, + link: string ): Promise> { // Extract hash from link let hash = link; diff --git a/src/lib/mcp/telegram/api/leaveChat.ts b/src/lib/telegram/api/leaveChat.ts similarity index 90% rename from src/lib/mcp/telegram/api/leaveChat.ts rename to src/lib/telegram/api/leaveChat.ts index 7898c8d4a..e8fd11bce 100644 --- a/src/lib/mcp/telegram/api/leaveChat.ts +++ b/src/lib/telegram/api/leaveChat.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; @@ -6,7 +6,7 @@ import bigInt from "big-integer"; import { toInputChannel } from "./apiCastHelpers"; export async function leaveChat( - chatId: string | number, + chatId: string | number ): Promise> { const chat = getChatById(chatId); if (!chat) throw new Error(`Chat not found: ${chatId}`); @@ -20,7 +20,7 @@ export async function leaveChat( await client.invoke( new Api.channels.LeaveChannel({ channel: toInputChannel(inputChannel), - }), + }) ); }); } else { @@ -29,7 +29,7 @@ export async function leaveChat( new Api.messages.DeleteChatUser({ chatId: bigInt(chat.id), userId: new Api.InputUserSelf(), - }), + }) ); }); } diff --git a/src/lib/mcp/telegram/api/listContacts.ts b/src/lib/telegram/api/listContacts.ts similarity index 93% rename from src/lib/mcp/telegram/api/listContacts.ts rename to src/lib/telegram/api/listContacts.ts index 0ad815d78..965367849 100644 --- a/src/lib/mcp/telegram/api/listContacts.ts +++ b/src/lib/telegram/api/listContacts.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import bigInt from "big-integer"; diff --git a/src/lib/mcp/telegram/api/listInlineButtons.ts b/src/lib/telegram/api/listInlineButtons.ts similarity index 100% rename from src/lib/mcp/telegram/api/listInlineButtons.ts rename to src/lib/telegram/api/listInlineButtons.ts diff --git a/src/lib/mcp/telegram/api/listTopics.ts b/src/lib/telegram/api/listTopics.ts similarity index 93% rename from src/lib/mcp/telegram/api/listTopics.ts rename to src/lib/telegram/api/listTopics.ts index 762aa5178..b241d9d89 100644 --- a/src/lib/mcp/telegram/api/listTopics.ts +++ b/src/lib/telegram/api/listTopics.ts @@ -4,7 +4,7 @@ * Fetches forum topics from channels/supergroups only. */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import type { ForumTopicsResult } from "./apiResultTypes"; @@ -17,7 +17,7 @@ export interface TopicResult { } export async function listTopics( - chatId: string | number, + chatId: string | number ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -26,7 +26,7 @@ export async function listTopics( if (chat.type !== "channel" && chat.type !== "supergroup") { throw new Error( - "Forum topics are only available for channels/supergroups.", + "Forum topics are only available for channels/supergroups." ); } @@ -42,7 +42,7 @@ export async function listTopics( offsetId: 0, offsetTopic: 0, limit: 100, - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/markAsRead.ts b/src/lib/telegram/api/markAsRead.ts similarity index 72% rename from src/lib/mcp/telegram/api/markAsRead.ts rename to src/lib/telegram/api/markAsRead.ts index 64929557f..59ef0e7f5 100644 --- a/src/lib/mcp/telegram/api/markAsRead.ts +++ b/src/lib/telegram/api/markAsRead.ts @@ -2,21 +2,19 @@ * API: Mark as read */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; export async function markAsRead( - chatId: string | number, + chatId: string | number ): Promise> { const chat = getChatById(chatId); if (!chat) { throw new Error(`Chat not found: ${chatId}`); } - const entity = chat.username - ? `@${chat.username.replace("@", "")}` - : chat.id; + const entity = chat.username ? `@${chat.username.replace("@", "")}` : chat.id; const client = mtprotoService.getClient(); await mtprotoService.withFloodWaitHandling(async () => { diff --git a/src/lib/mcp/telegram/api/muteChat.ts b/src/lib/telegram/api/muteChat.ts similarity index 90% rename from src/lib/mcp/telegram/api/muteChat.ts rename to src/lib/telegram/api/muteChat.ts index 6298fd4ec..e07224d2d 100644 --- a/src/lib/mcp/telegram/api/muteChat.ts +++ b/src/lib/telegram/api/muteChat.ts @@ -1,11 +1,11 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; export async function muteChat( chatId: string | number, - duration?: number, + duration?: number ): Promise> { const chat = getChatById(chatId); if (!chat) throw new Error(`Chat not found: ${chatId}`); @@ -26,7 +26,7 @@ export async function muteChat( settings: new Api.InputPeerNotifySettings({ muteUntil, }), - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/pinMessage.ts b/src/lib/telegram/api/pinMessage.ts similarity index 75% rename from src/lib/mcp/telegram/api/pinMessage.ts rename to src/lib/telegram/api/pinMessage.ts index f56e1882f..7b645df4b 100644 --- a/src/lib/mcp/telegram/api/pinMessage.ts +++ b/src/lib/telegram/api/pinMessage.ts @@ -2,22 +2,20 @@ * API: Pin message */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; export async function pinMessage( chatId: string | number, - messageId: number, + messageId: number ): Promise> { const chat = getChatById(chatId); if (!chat) { throw new Error(`Chat not found: ${chatId}`); } - const entity = chat.username - ? `@${chat.username.replace("@", "")}` - : chat.id; + const entity = chat.username ? `@${chat.username.replace("@", "")}` : chat.id; const client = mtprotoService.getClient(); await mtprotoService.withFloodWaitHandling(async () => { diff --git a/src/lib/mcp/telegram/api/pressInlineButton.ts b/src/lib/telegram/api/pressInlineButton.ts similarity index 84% rename from src/lib/mcp/telegram/api/pressInlineButton.ts rename to src/lib/telegram/api/pressInlineButton.ts index 99f540862..f2d82e33e 100644 --- a/src/lib/mcp/telegram/api/pressInlineButton.ts +++ b/src/lib/telegram/api/pressInlineButton.ts @@ -2,7 +2,7 @@ * API: Press inline button */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import type { BotCallbackAnswer } from "./apiResultTypes"; @@ -12,7 +12,7 @@ import { narrow } from "./apiCastHelpers"; export async function pressInlineButton( chatId: string | number, messageId: number, - buttonData: string, + buttonData: string ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -20,9 +20,7 @@ export async function pressInlineButton( } const client = mtprotoService.getClient(); - const entity = chat.username - ? `@${chat.username.replace("@", "")}` - : chat.id; + const entity = chat.username ? `@${chat.username.replace("@", "")}` : chat.id; const result = await mtprotoService.withFloodWaitHandling(async () => { const inputPeer = await client.getInputEntity(entity); @@ -31,7 +29,7 @@ export async function pressInlineButton( peer: inputPeer, msgId: messageId, data: Buffer.from(buttonData, "base64"), - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/promoteAdmin.ts b/src/lib/telegram/api/promoteAdmin.ts similarity index 92% rename from src/lib/mcp/telegram/api/promoteAdmin.ts rename to src/lib/telegram/api/promoteAdmin.ts index 572597c2b..5eca51f23 100644 --- a/src/lib/mcp/telegram/api/promoteAdmin.ts +++ b/src/lib/telegram/api/promoteAdmin.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import { toInputChannel, toInputUser } from "./apiCastHelpers"; @@ -6,7 +6,7 @@ import { getChatById } from "./helpers"; export async function promoteAdmin( chatId: string | number, - userId: string | number, + userId: string | number ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -15,7 +15,7 @@ export async function promoteAdmin( if (chat.type !== "channel" && chat.type !== "supergroup") { throw new Error( - "Admin promotion is only available for channels/supergroups.", + "Admin promotion is only available for channels/supergroups." ); } @@ -38,7 +38,7 @@ export async function promoteAdmin( manageCall: true, }), rank: "Admin", - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/removeReaction.ts b/src/lib/telegram/api/removeReaction.ts similarity index 79% rename from src/lib/mcp/telegram/api/removeReaction.ts rename to src/lib/telegram/api/removeReaction.ts index 2ef62d18e..996dd93dd 100644 --- a/src/lib/mcp/telegram/api/removeReaction.ts +++ b/src/lib/telegram/api/removeReaction.ts @@ -2,14 +2,14 @@ * API: Remove reaction */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; export async function removeReaction( chatId: string | number, - messageId: number, + messageId: number ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -17,9 +17,7 @@ export async function removeReaction( } const client = mtprotoService.getClient(); - const entity = chat.username - ? `@${chat.username.replace("@", "")}` - : chat.id; + const entity = chat.username ? `@${chat.username.replace("@", "")}` : chat.id; await mtprotoService.withFloodWaitHandling(async () => { const inputPeer = await client.getInputEntity(entity); @@ -28,7 +26,7 @@ export async function removeReaction( peer: inputPeer, msgId: messageId, reaction: [], - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/resolveUsername.ts b/src/lib/telegram/api/resolveUsername.ts similarity index 86% rename from src/lib/mcp/telegram/api/resolveUsername.ts rename to src/lib/telegram/api/resolveUsername.ts index de4a3e9b4..911f675bf 100644 --- a/src/lib/mcp/telegram/api/resolveUsername.ts +++ b/src/lib/telegram/api/resolveUsername.ts @@ -2,7 +2,7 @@ * API: Resolve username — API-first with cache fallback (hybrid). */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { Api } from "telegram"; import { getChatById, formatEntity } from "./helpers"; import type { ApiResult } from "./types"; @@ -17,7 +17,7 @@ export interface ResolvedEntity { } export async function resolveUsername( - username: string, + username: string ): Promise> { const clean = username.startsWith("@") ? username.slice(1) : username; @@ -27,7 +27,7 @@ export async function resolveUsername( const result = await mtprotoService.withFloodWaitHandling(async () => { return client.invoke( - new Api.contacts.ResolveUsername({ username: clean }), + new Api.contacts.ResolveUsername({ username: clean }) ); }); @@ -37,19 +37,19 @@ export async function resolveUsername( peer.className === "PeerUser" ? "user" : peer.className === "PeerChannel" - ? "channel" - : peer.className === "PeerChat" - ? "chat" - : "unknown"; + ? "channel" + : peer.className === "PeerChat" + ? "chat" + : "unknown"; const peerId = "userId" in peer ? String(peer.userId) : "channelId" in peer - ? String(peer.channelId) - : "chatId" in peer - ? String(peer.chatId) - : "unknown"; + ? String(peer.channelId) + : "chatId" in peer + ? String(peer.chatId) + : "unknown"; let name = clean; if ("users" in result && Array.isArray(result.users)) { diff --git a/src/lib/mcp/telegram/api/saveDraft.ts b/src/lib/telegram/api/saveDraft.ts similarity index 78% rename from src/lib/mcp/telegram/api/saveDraft.ts rename to src/lib/telegram/api/saveDraft.ts index 182e8b4d3..4cc26d4aa 100644 --- a/src/lib/mcp/telegram/api/saveDraft.ts +++ b/src/lib/telegram/api/saveDraft.ts @@ -2,14 +2,14 @@ * API: Save draft */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; export async function saveDraft( chatId: string | number, - text: string, + text: string ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -17,9 +17,7 @@ export async function saveDraft( } const client = mtprotoService.getClient(); - const entity = chat.username - ? `@${chat.username.replace("@", "")}` - : chat.id; + const entity = chat.username ? `@${chat.username.replace("@", "")}` : chat.id; await mtprotoService.withFloodWaitHandling(async () => { const inputPeer = await client.getInputEntity(entity); @@ -27,7 +25,7 @@ export async function saveDraft( new Api.messages.SaveDraft({ peer: inputPeer, message: text, - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/searchChats.ts b/src/lib/telegram/api/searchChats.ts similarity index 77% rename from src/lib/mcp/telegram/api/searchChats.ts rename to src/lib/telegram/api/searchChats.ts index aa397815b..02fe480a0 100644 --- a/src/lib/mcp/telegram/api/searchChats.ts +++ b/src/lib/telegram/api/searchChats.ts @@ -2,12 +2,12 @@ * API: Search chats — cache-only. */ -import type { TelegramChat } from "../../../../store/telegram/types"; +import type { TelegramChat } from "../../../store/telegram/types"; import { searchChatsInCache } from "./helpers"; import type { ApiResult } from "./types"; export async function searchChats( - query: string, + query: string ): Promise> { const data = searchChatsInCache(query); return { data, fromCache: true }; diff --git a/src/lib/mcp/telegram/api/searchContacts.ts b/src/lib/telegram/api/searchContacts.ts similarity index 92% rename from src/lib/mcp/telegram/api/searchContacts.ts rename to src/lib/telegram/api/searchContacts.ts index c97c804f4..88041acc4 100644 --- a/src/lib/mcp/telegram/api/searchContacts.ts +++ b/src/lib/telegram/api/searchContacts.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import type { ApiUser } from "./apiResultTypes"; @@ -12,7 +12,7 @@ export interface ContactSearchResult { export async function searchContacts( query: string, - limit: number = 20, + limit: number = 20 ): Promise> { if (!query) { throw new Error("query is required"); diff --git a/src/lib/mcp/telegram/api/searchMessages.ts b/src/lib/telegram/api/searchMessages.ts similarity index 92% rename from src/lib/mcp/telegram/api/searchMessages.ts rename to src/lib/telegram/api/searchMessages.ts index 9e23ba3f2..45290a4cc 100644 --- a/src/lib/mcp/telegram/api/searchMessages.ts +++ b/src/lib/telegram/api/searchMessages.ts @@ -2,7 +2,7 @@ * API: Search messages (API-first with cache fallback) */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById, formatMessage, getCachedMessages } from "./helpers"; import type { ApiResult } from "./types"; import type { ApiMessage } from "./apiResultTypes"; @@ -20,7 +20,7 @@ export interface SearchedMessage { export async function searchMessages( chatId: string | number, query: string, - limit: number, + limit: number ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -49,7 +49,7 @@ export async function searchMessages( maxId: 0, minId: 0, hash: bigInt(0), - }), + }) ); }); @@ -57,9 +57,7 @@ export async function searchMessages( const messages = narrow(result.messages); const searchedMessages = messages.map((msg) => ({ id: msg.id ?? "?", - date: msg.date - ? new Date(msg.date * 1000).toISOString() - : "unknown", + date: msg.date ? new Date(msg.date * 1000).toISOString() : "unknown", text: msg.message ?? "[Media/No text]", })); return { data: searchedMessages, fromCache: false }; diff --git a/src/lib/mcp/telegram/api/searchPublicChats.ts b/src/lib/telegram/api/searchPublicChats.ts similarity index 92% rename from src/lib/mcp/telegram/api/searchPublicChats.ts rename to src/lib/telegram/api/searchPublicChats.ts index 7c8b6088f..f96e3c757 100644 --- a/src/lib/mcp/telegram/api/searchPublicChats.ts +++ b/src/lib/telegram/api/searchPublicChats.ts @@ -5,7 +5,7 @@ * Falls back to filtering cached chats if the API call fails. */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { searchChatsInCache } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; @@ -20,7 +20,7 @@ export interface PublicChatResult { } export async function searchPublicChats( - query: string, + query: string ): Promise> { // Try server-side search via Telegram API try { @@ -42,11 +42,7 @@ export async function searchPublicChats( megagroup?: boolean; broadcast?: boolean; }; - const type = c.broadcast - ? "channel" - : c.megagroup - ? "group" - : "chat"; + const type = c.broadcast ? "channel" : c.megagroup ? "group" : "chat"; entries.push({ id: String(c.id), name: c.title ?? "Unknown", diff --git a/src/lib/mcp/telegram/api/sendMessage.ts b/src/lib/telegram/api/sendMessage.ts similarity index 80% rename from src/lib/mcp/telegram/api/sendMessage.ts rename to src/lib/telegram/api/sendMessage.ts index 39f108931..dc6c6c95d 100644 --- a/src/lib/mcp/telegram/api/sendMessage.ts +++ b/src/lib/telegram/api/sendMessage.ts @@ -2,21 +2,19 @@ * API: Send message — always API (write operation). */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; export async function sendMessage( chatId: string | number, message: string, - replyToMessageId?: number, + replyToMessageId?: number ): Promise> { const chat = getChatById(chatId); if (!chat) return { data: undefined, fromCache: false }; - const entity = chat.username - ? `@${chat.username.replace("@", "")}` - : chat.id; + const entity = chat.username ? `@${chat.username.replace("@", "")}` : chat.id; if (replyToMessageId !== undefined) { const client = mtprotoService.getClient(); diff --git a/src/lib/mcp/telegram/api/sendReaction.ts b/src/lib/telegram/api/sendReaction.ts similarity index 80% rename from src/lib/mcp/telegram/api/sendReaction.ts rename to src/lib/telegram/api/sendReaction.ts index 0af0ac0a5..741b85e32 100644 --- a/src/lib/mcp/telegram/api/sendReaction.ts +++ b/src/lib/telegram/api/sendReaction.ts @@ -2,7 +2,7 @@ * API: Send reaction */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; @@ -10,7 +10,7 @@ import { Api } from "telegram"; export async function sendReaction( chatId: string | number, messageId: number, - emoji: string, + emoji: string ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -18,9 +18,7 @@ export async function sendReaction( } const client = mtprotoService.getClient(); - const entity = chat.username - ? `@${chat.username.replace("@", "")}` - : chat.id; + const entity = chat.username ? `@${chat.username.replace("@", "")}` : chat.id; await mtprotoService.withFloodWaitHandling(async () => { const inputPeer = await client.getInputEntity(entity); @@ -29,7 +27,7 @@ export async function sendReaction( peer: inputPeer, msgId: messageId, reaction: [new Api.ReactionEmoji({ emoticon: emoji })], - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/setBotCommands.ts b/src/lib/telegram/api/setBotCommands.ts similarity index 87% rename from src/lib/mcp/telegram/api/setBotCommands.ts rename to src/lib/telegram/api/setBotCommands.ts index 02a1caa41..3b2cc804b 100644 --- a/src/lib/mcp/telegram/api/setBotCommands.ts +++ b/src/lib/telegram/api/setBotCommands.ts @@ -1,10 +1,10 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import type { BotCommandInput } from "./apiResultTypes"; export async function setBotCommands( - commands: BotCommandInput[], + commands: BotCommandInput[] ): Promise> { if (!Array.isArray(commands) || commands.length === 0) { throw new Error("commands array is required and must not be empty"); @@ -17,7 +17,7 @@ export async function setBotCommands( new Api.BotCommand({ command: String(c.command ?? ""), description: String(c.description ?? ""), - }), + }) ); await mtprotoService.withFloodWaitHandling(async () => { @@ -26,7 +26,7 @@ export async function setBotCommands( scope: new Api.BotCommandScopeDefault(), langCode: "", commands: botCommands, - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/setPrivacySettings.ts b/src/lib/telegram/api/setPrivacySettings.ts similarity index 91% rename from src/lib/mcp/telegram/api/setPrivacySettings.ts rename to src/lib/telegram/api/setPrivacySettings.ts index 3460559eb..a9cbe29d1 100644 --- a/src/lib/mcp/telegram/api/setPrivacySettings.ts +++ b/src/lib/telegram/api/setPrivacySettings.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; @@ -29,7 +29,7 @@ const ruleMap: Record = { export async function setPrivacySettings( setting: string, - value: string, + value: string ): Promise> { if (!setting) { throw new Error("setting is required"); @@ -46,7 +46,7 @@ export async function setPrivacySettings( throw new Error( "Unknown rule: " + value + - ". Valid: allow_all, allow_contacts, disallow_all", + ". Valid: allow_all, allow_contacts, disallow_all" ); } @@ -60,7 +60,7 @@ export async function setPrivacySettings( new Api.account.SetPrivacy({ key: keyMap[privacyKey], rules: [ruleMap[privacyRule]], - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/setProfilePhoto.ts b/src/lib/telegram/api/setProfilePhoto.ts similarity index 100% rename from src/lib/mcp/telegram/api/setProfilePhoto.ts rename to src/lib/telegram/api/setProfilePhoto.ts diff --git a/src/lib/mcp/telegram/api/subscribePublicChannel.ts b/src/lib/telegram/api/subscribePublicChannel.ts similarity index 84% rename from src/lib/mcp/telegram/api/subscribePublicChannel.ts rename to src/lib/telegram/api/subscribePublicChannel.ts index 787710496..abfbd181f 100644 --- a/src/lib/mcp/telegram/api/subscribePublicChannel.ts +++ b/src/lib/telegram/api/subscribePublicChannel.ts @@ -1,10 +1,10 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import { toInputChannel } from "./apiCastHelpers"; export async function subscribePublicChannel( - username: string, + username: string ): Promise> { const client = mtprotoService.getClient(); @@ -13,7 +13,7 @@ export async function subscribePublicChannel( await client.invoke( new Api.channels.JoinChannel({ channel: toInputChannel(inputChannel), - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/types.ts b/src/lib/telegram/api/types.ts similarity index 100% rename from src/lib/mcp/telegram/api/types.ts rename to src/lib/telegram/api/types.ts diff --git a/src/lib/mcp/telegram/api/unarchiveChat.ts b/src/lib/telegram/api/unarchiveChat.ts similarity index 88% rename from src/lib/mcp/telegram/api/unarchiveChat.ts rename to src/lib/telegram/api/unarchiveChat.ts index c7f26160c..243618a83 100644 --- a/src/lib/mcp/telegram/api/unarchiveChat.ts +++ b/src/lib/telegram/api/unarchiveChat.ts @@ -1,10 +1,10 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; export async function unarchiveChat( - chatId: string | number, + chatId: string | number ): Promise> { const chat = getChatById(chatId); if (!chat) throw new Error(`Chat not found: ${chatId}`); @@ -22,7 +22,7 @@ export async function unarchiveChat( folderId: 0, // 0 = Main folder (unarchive) }), ], - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/unbanUser.ts b/src/lib/telegram/api/unbanUser.ts similarity index 91% rename from src/lib/mcp/telegram/api/unbanUser.ts rename to src/lib/telegram/api/unbanUser.ts index 4338bc2aa..e8cf048fd 100644 --- a/src/lib/mcp/telegram/api/unbanUser.ts +++ b/src/lib/telegram/api/unbanUser.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import { toInputChannel, toInputPeer } from "./apiCastHelpers"; @@ -6,7 +6,7 @@ import { getChatById } from "./helpers"; export async function unbanUser( chatId: string | number, - userId: string | number, + userId: string | number ): Promise> { const chat = getChatById(chatId); if (!chat) { @@ -28,7 +28,7 @@ export async function unbanUser( channel: toInputChannel(inputChannel), participant: toInputPeer(inputUser), bannedRights: new Api.ChatBannedRights({ untilDate: 0 }), - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/unblockUser.ts b/src/lib/telegram/api/unblockUser.ts similarity index 62% rename from src/lib/mcp/telegram/api/unblockUser.ts rename to src/lib/telegram/api/unblockUser.ts index ea915ac47..1daab75a6 100644 --- a/src/lib/mcp/telegram/api/unblockUser.ts +++ b/src/lib/telegram/api/unblockUser.ts @@ -1,15 +1,17 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; import { toInputPeer } from "./apiCastHelpers"; -export async function unblockUser(userId: string | number): Promise> { +export async function unblockUser( + userId: string | number +): Promise> { const client = mtprotoService.getClient(); await mtprotoService.withFloodWaitHandling(async () => { const inputUser = await client.getInputEntity(userId); await client.invoke( - new Api.contacts.Unblock({ id: toInputPeer(inputUser) }), + new Api.contacts.Unblock({ id: toInputPeer(inputUser) }) ); }); diff --git a/src/lib/mcp/telegram/api/unmuteChat.ts b/src/lib/telegram/api/unmuteChat.ts similarity index 88% rename from src/lib/mcp/telegram/api/unmuteChat.ts rename to src/lib/telegram/api/unmuteChat.ts index d4093745a..433141270 100644 --- a/src/lib/mcp/telegram/api/unmuteChat.ts +++ b/src/lib/telegram/api/unmuteChat.ts @@ -1,10 +1,10 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; export async function unmuteChat( - chatId: string | number, + chatId: string | number ): Promise> { const chat = getChatById(chatId); if (!chat) throw new Error(`Chat not found: ${chatId}`); @@ -20,7 +20,7 @@ export async function unmuteChat( settings: new Api.InputPeerNotifySettings({ muteUntil: 0, }), - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/unpinMessage.ts b/src/lib/telegram/api/unpinMessage.ts similarity index 79% rename from src/lib/mcp/telegram/api/unpinMessage.ts rename to src/lib/telegram/api/unpinMessage.ts index a26fb4f50..17dbb10a2 100644 --- a/src/lib/mcp/telegram/api/unpinMessage.ts +++ b/src/lib/telegram/api/unpinMessage.ts @@ -2,23 +2,21 @@ * API: Unpin message */ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import { getChatById } from "./helpers"; import type { ApiResult } from "./types"; import { Api } from "telegram"; export async function unpinMessage( chatId: string | number, - messageId: number, + messageId: number ): Promise> { const chat = getChatById(chatId); if (!chat) { throw new Error(`Chat not found: ${chatId}`); } - const entity = chat.username - ? `@${chat.username.replace("@", "")}` - : chat.id; + const entity = chat.username ? `@${chat.username.replace("@", "")}` : chat.id; const client = mtprotoService.getClient(); await mtprotoService.withFloodWaitHandling(async () => { @@ -28,7 +26,7 @@ export async function unpinMessage( peer: inputPeer, id: messageId, unpin: true, - }), + }) ); }); diff --git a/src/lib/mcp/telegram/api/updateProfile.ts b/src/lib/telegram/api/updateProfile.ts similarity index 83% rename from src/lib/mcp/telegram/api/updateProfile.ts rename to src/lib/telegram/api/updateProfile.ts index 3330c0619..1f344186a 100644 --- a/src/lib/mcp/telegram/api/updateProfile.ts +++ b/src/lib/telegram/api/updateProfile.ts @@ -1,4 +1,4 @@ -import { mtprotoService } from "../../../../services/mtprotoService"; +import { mtprotoService } from "../../../services/mtprotoService"; import type { ApiResult } from "./types"; import { Api } from "telegram"; @@ -9,15 +9,11 @@ export interface ProfileUpdate { } export async function updateProfile( - update: ProfileUpdate, + update: ProfileUpdate ): Promise> { - if ( - !update.firstName && - !update.lastName && - !update.about - ) { + if (!update.firstName && !update.lastName && !update.about) { throw new Error( - "At least one of firstName, lastName, or about is required.", + "At least one of firstName, lastName, or about is required." ); } @@ -29,7 +25,7 @@ export async function updateProfile( firstName: update.firstName ?? undefined, lastName: update.lastName ?? undefined, about: update.about ?? undefined, - }), + }) ); }); diff --git a/src/lib/mcp/telegram/args.test.ts b/src/lib/telegram/args.test.ts similarity index 100% rename from src/lib/mcp/telegram/args.test.ts rename to src/lib/telegram/args.test.ts diff --git a/src/lib/mcp/telegram/args.ts b/src/lib/telegram/args.ts similarity index 100% rename from src/lib/mcp/telegram/args.ts rename to src/lib/telegram/args.ts diff --git a/src/lib/mcp/telegram/index.ts b/src/lib/telegram/index.ts similarity index 100% rename from src/lib/mcp/telegram/index.ts rename to src/lib/telegram/index.ts diff --git a/src/lib/mcp/telegram/tools/__tests__/getChats.test.ts b/src/lib/telegram/mcp-tools/__tests__/getChats.test.ts similarity index 69% rename from src/lib/mcp/telegram/tools/__tests__/getChats.test.ts rename to src/lib/telegram/mcp-tools/__tests__/getChats.test.ts index f039f4aeb..405712941 100644 --- a/src/lib/mcp/telegram/tools/__tests__/getChats.test.ts +++ b/src/lib/telegram/mcp-tools/__tests__/getChats.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { getChats, tool } from "../getChats"; import type { TelegramMCPContext } from "../../types"; -import type { TelegramState } from "../../../../../store/telegram/types"; +import type { TelegramState } from "../../../../store/telegram/types"; vi.mock("../../api/getChats"); @@ -27,9 +27,27 @@ describe("getChats tool handler", () => { it("should return formatted chat list with IDs and titles", async () => { const mockChats = [ - { id: "123", title: "Tech Group", type: "group" as const, unreadCount: 0, isPinned: false }, - { id: "456", title: "Trading Chat", type: "group" as const, unreadCount: 0, isPinned: false }, - { id: "789", title: "John Doe", type: "private" as const, unreadCount: 0, isPinned: false }, + { + id: "123", + title: "Tech Group", + type: "group" as const, + unreadCount: 0, + isPinned: false, + }, + { + id: "456", + title: "Trading Chat", + type: "group" as const, + unreadCount: 0, + isPinned: false, + }, + { + id: "789", + title: "John Doe", + type: "private" as const, + unreadCount: 0, + isPinned: false, + }, ]; vi.mocked(getChatsApi).mockResolvedValue({ @@ -62,8 +80,20 @@ describe("getChats tool handler", () => { it("should return error for empty page", async () => { const mockChats = [ - { id: "123", title: "Chat 1", type: "private" as const, unreadCount: 0, isPinned: false }, - { id: "456", title: "Chat 2", type: "private" as const, unreadCount: 0, isPinned: false }, + { + id: "123", + title: "Chat 1", + type: "private" as const, + unreadCount: 0, + isPinned: false, + }, + { + id: "456", + title: "Chat 2", + type: "private" as const, + unreadCount: 0, + isPinned: false, + }, ]; vi.mocked(getChatsApi).mockResolvedValue({ @@ -71,21 +101,48 @@ describe("getChats tool handler", () => { fromCache: false, }); - const result = await getChats( - { page: 5, page_size: 10 }, - mockContext - ); + const result = await getChats({ page: 5, page_size: 10 }, mockContext); expect(result.content[0].text).toContain("Page out of range"); }); it("should handle pagination with page 2 and page_size 2", async () => { const mockChats = [ - { id: "1", title: "Chat 1", type: "private" as const, unreadCount: 0, isPinned: false }, - { id: "2", title: "Chat 2", type: "private" as const, unreadCount: 0, isPinned: false }, - { id: "3", title: "Chat 3", type: "private" as const, unreadCount: 0, isPinned: false }, - { id: "4", title: "Chat 4", type: "private" as const, unreadCount: 0, isPinned: false }, - { id: "5", title: "Chat 5", type: "private" as const, unreadCount: 0, isPinned: false }, + { + id: "1", + title: "Chat 1", + type: "private" as const, + unreadCount: 0, + isPinned: false, + }, + { + id: "2", + title: "Chat 2", + type: "private" as const, + unreadCount: 0, + isPinned: false, + }, + { + id: "3", + title: "Chat 3", + type: "private" as const, + unreadCount: 0, + isPinned: false, + }, + { + id: "4", + title: "Chat 4", + type: "private" as const, + unreadCount: 0, + isPinned: false, + }, + { + id: "5", + title: "Chat 5", + type: "private" as const, + unreadCount: 0, + isPinned: false, + }, ]; vi.mocked(getChatsApi).mockResolvedValue({ @@ -93,10 +150,7 @@ describe("getChats tool handler", () => { fromCache: false, }); - const result = await getChats( - { page: 2, page_size: 2 }, - mockContext - ); + const result = await getChats({ page: 2, page_size: 2 }, mockContext); expect(result.isError).toBeFalsy(); const text = result.content[0].text; diff --git a/src/lib/mcp/telegram/tools/__tests__/getMe.test.ts b/src/lib/telegram/mcp-tools/__tests__/getMe.test.ts similarity index 98% rename from src/lib/mcp/telegram/tools/__tests__/getMe.test.ts rename to src/lib/telegram/mcp-tools/__tests__/getMe.test.ts index 9bdabc130..c0cfe0744 100644 --- a/src/lib/mcp/telegram/tools/__tests__/getMe.test.ts +++ b/src/lib/telegram/mcp-tools/__tests__/getMe.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { getMe, tool } from "../getMe"; import type { TelegramMCPContext } from "../../types"; -import type { TelegramState } from "../../../../../store/telegram/types"; +import type { TelegramState } from "../../../../store/telegram/types"; vi.mock("../../api/getCurrentUser"); diff --git a/src/lib/mcp/telegram/tools/__tests__/getMessages.test.ts b/src/lib/telegram/mcp-tools/__tests__/getMessages.test.ts similarity index 83% rename from src/lib/mcp/telegram/tools/__tests__/getMessages.test.ts rename to src/lib/telegram/mcp-tools/__tests__/getMessages.test.ts index 650f2ceb5..f6148bcb0 100644 --- a/src/lib/mcp/telegram/tools/__tests__/getMessages.test.ts +++ b/src/lib/telegram/mcp-tools/__tests__/getMessages.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { getMessages, tool } from "../getMessages"; import type { TelegramMCPContext } from "../../types"; -import type { TelegramState } from "../../../../../store/telegram/types"; +import type { TelegramState } from "../../../../store/telegram/types"; vi.mock("../../api/getMessages"); vi.mock("../../api/helpers", async (importOriginal) => { @@ -44,10 +44,7 @@ describe("getMessages tool handler", () => { it("should return error when chat is not found", async () => { vi.mocked(getChatById).mockReturnValue(undefined); - const result = await getMessages( - { chat_id: "123456789" }, - mockContext - ); + const result = await getMessages({ chat_id: "123456789" }, mockContext); expect(result.isError).toBe(true); expect(result.content[0].text).toContain("Chat not found: 123456789"); @@ -90,10 +87,7 @@ describe("getMessages tool handler", () => { fromCache: false, }); - const result = await getMessages( - { chat_id: "123456789" }, - mockContext - ); + const result = await getMessages({ chat_id: "123456789" }, mockContext); expect(result.isError).toBeFalsy(); const text = result.content[0].text; @@ -117,10 +111,7 @@ describe("getMessages tool handler", () => { fromCache: false, }); - const result = await getMessages( - { chat_id: "123456789" }, - mockContext - ); + const result = await getMessages({ chat_id: "123456789" }, mockContext); expect(result.isError).toBeFalsy(); expect(result.content[0].text).toContain("No messages found for this page"); @@ -133,8 +124,26 @@ describe("getMessages tool handler", () => { }; const mockMessages = [ - { id: "3", chatId: "123456789", fromId: "user3", message: "Message 3", date: 1609459300, isOutgoing: false, isEdited: false, isForwarded: false }, - { id: "4", chatId: "123456789", fromId: "user4", message: "Message 4", date: 1609459400, isOutgoing: false, isEdited: false, isForwarded: false }, + { + id: "3", + chatId: "123456789", + fromId: "user3", + message: "Message 3", + date: 1609459300, + isOutgoing: false, + isEdited: false, + isForwarded: false, + }, + { + id: "4", + chatId: "123456789", + fromId: "user4", + message: "Message 4", + date: 1609459400, + isOutgoing: false, + isEdited: false, + isForwarded: false, + }, ]; vi.mocked(getChatById).mockReturnValue(mockChat as any); @@ -150,11 +159,7 @@ describe("getMessages tool handler", () => { expect(result.isError).toBeFalsy(); // validateId converts string to number - expect(getMessagesApi).toHaveBeenCalledWith( - 123456789, - 2, - 2 - ); + expect(getMessagesApi).toHaveBeenCalledWith(123456789, 2, 2); }); it("should use default pagination values", async () => { @@ -172,11 +177,7 @@ describe("getMessages tool handler", () => { await getMessages({ chat_id: "123456789" }, mockContext); // validateId converts string to number - expect(getMessagesApi).toHaveBeenCalledWith( - 123456789, - 20, - 0 - ); + expect(getMessagesApi).toHaveBeenCalledWith(123456789, 20, 0); }); it("should handle messages without sender ID", async () => { @@ -205,10 +206,7 @@ describe("getMessages tool handler", () => { fromCache: false, }); - const result = await getMessages( - { chat_id: "123456789" }, - mockContext - ); + const result = await getMessages({ chat_id: "123456789" }, mockContext); expect(result.isError).toBeFalsy(); const text = result.content[0].text; @@ -224,14 +222,9 @@ describe("getMessages tool handler", () => { }; vi.mocked(getChatById).mockReturnValue(mockChat as any); - vi.mocked(getMessagesApi).mockRejectedValue( - new Error("Network error") - ); + vi.mocked(getMessagesApi).mockRejectedValue(new Error("Network error")); - const result = await getMessages( - { chat_id: "123456789" }, - mockContext - ); + const result = await getMessages({ chat_id: "123456789" }, mockContext); expect(result.isError).toBe(true); expect(result.content[0].text).toContain("MSG-ERR"); diff --git a/src/lib/mcp/telegram/tools/__tests__/sendMessage.test.ts b/src/lib/telegram/mcp-tools/__tests__/sendMessage.test.ts similarity index 88% rename from src/lib/mcp/telegram/tools/__tests__/sendMessage.test.ts rename to src/lib/telegram/mcp-tools/__tests__/sendMessage.test.ts index dea3969eb..e919770bf 100644 --- a/src/lib/mcp/telegram/tools/__tests__/sendMessage.test.ts +++ b/src/lib/telegram/mcp-tools/__tests__/sendMessage.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { sendMessage, tool } from "../sendMessage"; import type { TelegramMCPContext } from "../../types"; -import type { TelegramState } from "../../../../../store/telegram/types"; +import type { TelegramState } from "../../../../store/telegram/types"; vi.mock("../../api/sendMessage"); @@ -26,20 +26,14 @@ describe("sendMessage tool handler", () => { }); it("should return error when chat_id is missing", async () => { - const result = await sendMessage( - { message: "test message" }, - mockContext - ); + const result = await sendMessage({ message: "test message" }, mockContext); expect(result.isError).toBe(true); expect(result.content[0].text).toContain("chat_id"); }); it("should return error when message is missing", async () => { - const result = await sendMessage( - { chat_id: "123456789" }, - mockContext - ); + const result = await sendMessage({ chat_id: "123456789" }, mockContext); expect(result.isError).toBe(true); expect(result.content[0].text).toBe("Message content is required"); @@ -82,10 +76,7 @@ describe("sendMessage tool handler", () => { expect(result.isError).toBeFalsy(); expect(result.content[0].text).toBe("Message sent successfully."); // validateId converts string to number - expect(sendMessageApi).toHaveBeenCalledWith( - 123456789, - "Hello, world!" - ); + expect(sendMessageApi).toHaveBeenCalledWith(123456789, "Hello, world!"); }); it("should return error when API returns undefined", async () => { @@ -107,9 +98,7 @@ describe("sendMessage tool handler", () => { }); it("should handle API errors gracefully", async () => { - vi.mocked(sendMessageApi).mockRejectedValue( - new Error("Network error") - ); + vi.mocked(sendMessageApi).mockRejectedValue(new Error("Network error")); const result = await sendMessage( { diff --git a/src/lib/mcp/telegram/tools/__tests__/toolDefinitions.test.ts b/src/lib/telegram/mcp-tools/__tests__/toolDefinitions.test.ts similarity index 88% rename from src/lib/mcp/telegram/tools/__tests__/toolDefinitions.test.ts rename to src/lib/telegram/mcp-tools/__tests__/toolDefinitions.test.ts index a1780c73e..4aaf05ef5 100644 --- a/src/lib/mcp/telegram/tools/__tests__/toolDefinitions.test.ts +++ b/src/lib/telegram/mcp-tools/__tests__/toolDefinitions.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect } from "vitest"; import * as tools from "../index"; import { TELEGRAM_MCP_TOOL_NAMES } from "../../types"; -import type { MCPTool } from "../../../types"; +import type { MCPTool } from "../../../mcp/types"; describe("Tool Definitions", () => { // Extract tool definitions (exports ending with "Tool") @@ -96,7 +96,14 @@ describe("Tool Definitions", () => { }); it("should have valid property types in inputSchema", () => { - const validTypes = ["string", "number", "integer", "boolean", "array", "object"]; + const validTypes = [ + "string", + "number", + "integer", + "boolean", + "array", + "object", + ]; const toolDefs = getToolDefinitions(); toolDefs.forEach(({ tool }) => { @@ -112,14 +119,16 @@ describe("Tool Definitions", () => { const toolDefs = getToolDefinitions(); toolDefs.forEach(({ tool }) => { - Object.entries(tool.inputSchema.properties).forEach(([propName, prop]: [string, any]) => { - expect( - prop.description, - `Property "${propName}" in tool "${tool.name}" should have a description` - ).toBeDefined(); - expect(typeof prop.description).toBe("string"); - expect(prop.description.length).toBeGreaterThan(0); - }); + Object.entries(tool.inputSchema.properties).forEach( + ([propName, prop]: [string, any]) => { + expect( + prop.description, + `Property "${propName}" in tool "${tool.name}" should have a description` + ).toBeDefined(); + expect(typeof prop.description).toBe("string"); + expect(prop.description.length).toBeGreaterThan(0); + } + ); }); }); diff --git a/src/lib/mcp/telegram/tools/addContact.ts b/src/lib/telegram/mcp-tools/addContact.ts similarity index 86% rename from src/lib/mcp/telegram/tools/addContact.ts rename to src/lib/telegram/mcp-tools/addContact.ts index 4960a173d..c7085a2c7 100644 --- a/src/lib/mcp/telegram/tools/addContact.ts +++ b/src/lib/telegram/mcp-tools/addContact.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { optString } from "../args"; import { addContact as addContactApi } from "../api/addContact"; @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function addContact( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const phone = typeof args.phone === "string" ? args.phone : ""; @@ -42,7 +42,7 @@ export async function addContact( return logAndFormatError( "add_contact", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/archiveChat.ts b/src/lib/telegram/mcp-tools/archiveChat.ts similarity index 77% rename from src/lib/mcp/telegram/tools/archiveChat.ts rename to src/lib/telegram/mcp-tools/archiveChat.ts index b09830d3f..b733efd96 100644 --- a/src/lib/mcp/telegram/tools/archiveChat.ts +++ b/src/lib/telegram/mcp-tools/archiveChat.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { archiveChat as archiveChatApi } from "../api/archiveChat"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function archiveChat( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -31,7 +31,7 @@ export async function archiveChat( return logAndFormatError( "archive_chat", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CHAT, + ErrorCategory.CHAT ); } } diff --git a/src/lib/mcp/telegram/tools/banUser.ts b/src/lib/telegram/mcp-tools/banUser.ts similarity index 81% rename from src/lib/mcp/telegram/tools/banUser.ts rename to src/lib/telegram/mcp-tools/banUser.ts index 35888b9b4..3a3687cf1 100644 --- a/src/lib/mcp/telegram/tools/banUser.ts +++ b/src/lib/telegram/mcp-tools/banUser.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { banUser as banUserApi } from "../api/banUser"; import { getChatById } from "../api/helpers"; @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function banUser( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -41,7 +41,7 @@ export async function banUser( return logAndFormatError( "ban_user", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.ADMIN, + ErrorCategory.ADMIN ); } } diff --git a/src/lib/mcp/telegram/tools/blockUser.ts b/src/lib/telegram/mcp-tools/blockUser.ts similarity index 76% rename from src/lib/mcp/telegram/tools/blockUser.ts rename to src/lib/telegram/mcp-tools/blockUser.ts index d7af31044..a593c010e 100644 --- a/src/lib/mcp/telegram/tools/blockUser.ts +++ b/src/lib/telegram/mcp-tools/blockUser.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { blockUser as blockUserApi } from "../api/blockUser"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function blockUser( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const userId = validateId(args.user_id, "user_id"); @@ -32,7 +32,7 @@ export async function blockUser( return logAndFormatError( "block_user", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/clearDraft.ts b/src/lib/telegram/mcp-tools/clearDraft.ts similarity index 78% rename from src/lib/mcp/telegram/tools/clearDraft.ts rename to src/lib/telegram/mcp-tools/clearDraft.ts index baa8b3f79..46c95148d 100644 --- a/src/lib/mcp/telegram/tools/clearDraft.ts +++ b/src/lib/telegram/mcp-tools/clearDraft.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { clearDraft as clearDraftApi } from "../api/clearDraft"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function clearDraft( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -35,7 +35,7 @@ export async function clearDraft( return logAndFormatError( "clear_draft", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.DRAFT, + ErrorCategory.DRAFT ); } } diff --git a/src/lib/mcp/telegram/tools/createChannel.ts b/src/lib/telegram/mcp-tools/createChannel.ts similarity index 88% rename from src/lib/mcp/telegram/tools/createChannel.ts rename to src/lib/telegram/mcp-tools/createChannel.ts index c42bc71c5..e26e85f4c 100644 --- a/src/lib/mcp/telegram/tools/createChannel.ts +++ b/src/lib/telegram/mcp-tools/createChannel.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { optString } from "../args"; import { createChannel as createChannelApi } from "../api/createChannel"; @@ -24,7 +24,7 @@ export const tool: MCPTool = { export async function createChannel( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const title = typeof args.title === "string" ? args.title : ""; @@ -51,7 +51,7 @@ export async function createChannel( return logAndFormatError( "create_channel", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.GROUP, + ErrorCategory.GROUP ); } } diff --git a/src/lib/mcp/telegram/tools/createGroup.ts b/src/lib/telegram/mcp-tools/createGroup.ts similarity index 86% rename from src/lib/mcp/telegram/tools/createGroup.ts rename to src/lib/telegram/mcp-tools/createGroup.ts index 93bd25459..76a01e10c 100644 --- a/src/lib/mcp/telegram/tools/createGroup.ts +++ b/src/lib/telegram/mcp-tools/createGroup.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { createGroup as createGroupApi } from "../api/createGroup"; export const tool: MCPTool = { @@ -22,7 +22,7 @@ export const tool: MCPTool = { export async function createGroup( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const title = typeof args.title === "string" ? args.title : ""; @@ -41,7 +41,7 @@ export async function createGroup( const { data, fromCache } = await createGroupApi( title, - userIds.map(String), + userIds.map(String) ); return { content: [ @@ -53,7 +53,7 @@ export async function createGroup( return logAndFormatError( "create_group", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.GROUP, + ErrorCategory.GROUP ); } } diff --git a/src/lib/mcp/telegram/tools/createPoll.ts b/src/lib/telegram/mcp-tools/createPoll.ts similarity index 85% rename from src/lib/mcp/telegram/tools/createPoll.ts rename to src/lib/telegram/mcp-tools/createPoll.ts index 43fa1bcd4..c8919f9eb 100644 --- a/src/lib/mcp/telegram/tools/createPoll.ts +++ b/src/lib/telegram/mcp-tools/createPoll.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { createPoll as createPollApi } from "../api/createPoll"; export const tool: MCPTool = { @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function createPoll( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -48,7 +48,7 @@ export async function createPoll( return logAndFormatError( "create_poll", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/deleteChatPhoto.ts b/src/lib/telegram/mcp-tools/deleteChatPhoto.ts similarity index 78% rename from src/lib/mcp/telegram/tools/deleteChatPhoto.ts rename to src/lib/telegram/mcp-tools/deleteChatPhoto.ts index bd2e4dbb6..81b422067 100644 --- a/src/lib/mcp/telegram/tools/deleteChatPhoto.ts +++ b/src/lib/telegram/mcp-tools/deleteChatPhoto.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { deleteChatPhoto as deleteChatPhotoApi } from "../api/deleteChatPhoto"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function deleteChatPhoto( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -31,7 +31,7 @@ export async function deleteChatPhoto( return logAndFormatError( "delete_chat_photo", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.GROUP, + ErrorCategory.GROUP ); } } diff --git a/src/lib/mcp/telegram/tools/deleteContact.ts b/src/lib/telegram/mcp-tools/deleteContact.ts similarity index 78% rename from src/lib/mcp/telegram/tools/deleteContact.ts rename to src/lib/telegram/mcp-tools/deleteContact.ts index ab6130502..2889dac33 100644 --- a/src/lib/mcp/telegram/tools/deleteContact.ts +++ b/src/lib/telegram/mcp-tools/deleteContact.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { deleteContact as deleteContactApi } from "../api/deleteContact"; export const tool: MCPTool = { @@ -21,7 +21,7 @@ export const tool: MCPTool = { export async function deleteContact( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const userId = validateId(args.user_id, "user_id"); @@ -35,7 +35,7 @@ export async function deleteContact( return logAndFormatError( "delete_contact", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/deleteMessage.ts b/src/lib/telegram/mcp-tools/deleteMessage.ts similarity index 80% rename from src/lib/mcp/telegram/tools/deleteMessage.ts rename to src/lib/telegram/mcp-tools/deleteMessage.ts index 2835220c1..3e9796503 100644 --- a/src/lib/mcp/telegram/tools/deleteMessage.ts +++ b/src/lib/telegram/mcp-tools/deleteMessage.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId, validatePositiveInt } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId, validatePositiveInt } from "../../mcp/validation"; import { deleteMessage as deleteMessageApi } from "../api/deleteMessage"; export const tool: MCPTool = { @@ -19,7 +19,7 @@ export const tool: MCPTool = { export async function deleteMessage( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -37,7 +37,7 @@ export async function deleteMessage( return logAndFormatError( "delete_message", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/deleteProfilePhoto.ts b/src/lib/telegram/mcp-tools/deleteProfilePhoto.ts similarity index 78% rename from src/lib/mcp/telegram/tools/deleteProfilePhoto.ts rename to src/lib/telegram/mcp-tools/deleteProfilePhoto.ts index d53422ea0..9db9f5678 100644 --- a/src/lib/mcp/telegram/tools/deleteProfilePhoto.ts +++ b/src/lib/telegram/mcp-tools/deleteProfilePhoto.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { deleteProfilePhoto as deleteProfilePhotoApi } from "../api/deleteProfilePhoto"; export const tool: MCPTool = { @@ -11,7 +11,7 @@ export const tool: MCPTool = { export async function deleteProfilePhoto( _args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const { fromCache } = await deleteProfilePhotoApi(); @@ -24,7 +24,7 @@ export async function deleteProfilePhoto( return logAndFormatError( "delete_profile_photo", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.PROFILE, + ErrorCategory.PROFILE ); } } diff --git a/src/lib/mcp/telegram/tools/demoteAdmin.ts b/src/lib/telegram/mcp-tools/demoteAdmin.ts similarity index 82% rename from src/lib/mcp/telegram/tools/demoteAdmin.ts rename to src/lib/telegram/mcp-tools/demoteAdmin.ts index 74571a439..fb670665e 100644 --- a/src/lib/mcp/telegram/tools/demoteAdmin.ts +++ b/src/lib/telegram/mcp-tools/demoteAdmin.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { demoteAdmin as demoteAdminApi } from "../api/demoteAdmin"; import { getChatById } from "../api/helpers"; @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function demoteAdmin( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -41,7 +41,7 @@ export async function demoteAdmin( return logAndFormatError( "demote_admin", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.ADMIN, + ErrorCategory.ADMIN ); } } diff --git a/src/lib/mcp/telegram/tools/editChatPhoto.ts b/src/lib/telegram/mcp-tools/editChatPhoto.ts similarity index 80% rename from src/lib/mcp/telegram/tools/editChatPhoto.ts rename to src/lib/telegram/mcp-tools/editChatPhoto.ts index f24aaeeb8..2ab5f9a14 100644 --- a/src/lib/mcp/telegram/tools/editChatPhoto.ts +++ b/src/lib/telegram/mcp-tools/editChatPhoto.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { editChatPhoto as editChatPhotoApi } from "../api/editChatPhoto"; export const tool: MCPTool = { @@ -19,7 +19,7 @@ export const tool: MCPTool = { export async function editChatPhoto( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -33,7 +33,7 @@ export async function editChatPhoto( return logAndFormatError( "edit_chat_photo", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.GROUP, + ErrorCategory.GROUP ); } } diff --git a/src/lib/mcp/telegram/tools/editChatTitle.ts b/src/lib/telegram/mcp-tools/editChatTitle.ts similarity index 82% rename from src/lib/mcp/telegram/tools/editChatTitle.ts rename to src/lib/telegram/mcp-tools/editChatTitle.ts index be100a941..ccf7b7c44 100644 --- a/src/lib/mcp/telegram/tools/editChatTitle.ts +++ b/src/lib/telegram/mcp-tools/editChatTitle.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { editChatTitle as editChatTitleApi } from "../api/editChatTitle"; export const tool: MCPTool = { @@ -19,7 +19,7 @@ export const tool: MCPTool = { export async function editChatTitle( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -39,7 +39,7 @@ export async function editChatTitle( return logAndFormatError( "edit_chat_title", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.GROUP, + ErrorCategory.GROUP ); } } diff --git a/src/lib/mcp/telegram/tools/editMessage.ts b/src/lib/telegram/mcp-tools/editMessage.ts similarity index 83% rename from src/lib/mcp/telegram/tools/editMessage.ts rename to src/lib/telegram/mcp-tools/editMessage.ts index 98940f3aa..c93bb3365 100644 --- a/src/lib/mcp/telegram/tools/editMessage.ts +++ b/src/lib/telegram/mcp-tools/editMessage.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId, validatePositiveInt } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId, validatePositiveInt } from "../../mcp/validation"; import { editMessage as editMessageApi } from "../api/editMessage"; export const tool: MCPTool = { @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function editMessage( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -46,7 +46,7 @@ export async function editMessage( return logAndFormatError( "edit_message", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/exportChatInvite.ts b/src/lib/telegram/mcp-tools/exportChatInvite.ts similarity index 84% rename from src/lib/mcp/telegram/tools/exportChatInvite.ts rename to src/lib/telegram/mcp-tools/exportChatInvite.ts index e387a9ab6..be1463456 100644 --- a/src/lib/mcp/telegram/tools/exportChatInvite.ts +++ b/src/lib/telegram/mcp-tools/exportChatInvite.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { optString } from "../args"; import { exportChatInvite as exportChatInviteApi } from "../api/exportChatInvite"; @@ -22,7 +22,7 @@ export const tool: MCPTool = { export async function exportChatInvite( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -36,7 +36,7 @@ export async function exportChatInvite( chatId, title, expireDate, - usageLimit, + usageLimit ); return { content: [{ type: "text", text: `Invite link created: ${data.link}` }], @@ -46,7 +46,7 @@ export async function exportChatInvite( return logAndFormatError( "export_chat_invite", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.GROUP, + ErrorCategory.GROUP ); } } diff --git a/src/lib/mcp/telegram/tools/exportContacts.ts b/src/lib/telegram/mcp-tools/exportContacts.ts similarity index 81% rename from src/lib/mcp/telegram/tools/exportContacts.ts rename to src/lib/telegram/mcp-tools/exportContacts.ts index 9dc3a9dc0..9fc845c64 100644 --- a/src/lib/mcp/telegram/tools/exportContacts.ts +++ b/src/lib/telegram/mcp-tools/exportContacts.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { exportContacts as exportContactsApi } from "../api/exportContacts"; export const tool: MCPTool = { @@ -11,7 +11,7 @@ export const tool: MCPTool = { export async function exportContacts( _args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const { data: contacts, fromCache } = await exportContactsApi(); @@ -31,7 +31,7 @@ export async function exportContacts( return logAndFormatError( "export_contacts", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/forwardMessage.ts b/src/lib/telegram/mcp-tools/forwardMessage.ts similarity index 76% rename from src/lib/mcp/telegram/tools/forwardMessage.ts rename to src/lib/telegram/mcp-tools/forwardMessage.ts index 4636d9086..c5b6422cf 100644 --- a/src/lib/mcp/telegram/tools/forwardMessage.ts +++ b/src/lib/telegram/mcp-tools/forwardMessage.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId, validatePositiveInt } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId, validatePositiveInt } from "../../mcp/validation"; import { forwardMessage as forwardMessageApi } from "../api/forwardMessage"; export const tool: MCPTool = { @@ -20,14 +20,18 @@ export const tool: MCPTool = { export async function forwardMessage( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const fromChatId = validateId(args.from_chat_id, "from_chat_id"); const toChatId = validateId(args.to_chat_id, "to_chat_id"); const messageId = validatePositiveInt(args.message_id, "message_id"); - const { fromCache } = await forwardMessageApi(fromChatId, toChatId, messageId); + const { fromCache } = await forwardMessageApi( + fromChatId, + toChatId, + messageId + ); return { content: [ @@ -42,7 +46,7 @@ export async function forwardMessage( return logAndFormatError( "forward_message", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/getAdmins.ts b/src/lib/telegram/mcp-tools/getAdmins.ts similarity index 83% rename from src/lib/mcp/telegram/tools/getAdmins.ts rename to src/lib/telegram/mcp-tools/getAdmins.ts index 91dba58d2..e37dc9b5a 100644 --- a/src/lib/mcp/telegram/tools/getAdmins.ts +++ b/src/lib/telegram/mcp-tools/getAdmins.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { getAdmins as getAdminsApi } from "../api/getAdmins"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function getAdmins( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -47,7 +47,7 @@ export async function getAdmins( return logAndFormatError( "get_admins", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.ADMIN, + ErrorCategory.ADMIN ); } } diff --git a/src/lib/mcp/telegram/tools/getBannedUsers.ts b/src/lib/telegram/mcp-tools/getBannedUsers.ts similarity index 85% rename from src/lib/mcp/telegram/tools/getBannedUsers.ts rename to src/lib/telegram/mcp-tools/getBannedUsers.ts index 367f102fb..d4efc328b 100644 --- a/src/lib/mcp/telegram/tools/getBannedUsers.ts +++ b/src/lib/telegram/mcp-tools/getBannedUsers.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { optNumber } from "../args"; import { getBannedUsers as getBannedUsersApi } from "../api/getBannedUsers"; @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function getBannedUsers( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -28,7 +28,7 @@ export async function getBannedUsers( const { data: bannedUsers, fromCache } = await getBannedUsersApi( chatId, - limit, + limit ); if (bannedUsers.length === 0) { @@ -56,7 +56,7 @@ export async function getBannedUsers( return logAndFormatError( "get_banned_users", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.ADMIN, + ErrorCategory.ADMIN ); } } diff --git a/src/lib/mcp/telegram/tools/getBlockedUsers.ts b/src/lib/telegram/mcp-tools/getBlockedUsers.ts similarity index 86% rename from src/lib/mcp/telegram/tools/getBlockedUsers.ts rename to src/lib/telegram/mcp-tools/getBlockedUsers.ts index 1cc073614..737a265e2 100644 --- a/src/lib/mcp/telegram/tools/getBlockedUsers.ts +++ b/src/lib/telegram/mcp-tools/getBlockedUsers.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { optNumber } from "../args"; import { getBlockedUsers as getBlockedUsersApi } from "../api/getBlockedUsers"; @@ -17,7 +17,7 @@ export const tool: MCPTool = { export async function getBlockedUsers( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const limit = optNumber(args, "limit", 50); @@ -44,7 +44,7 @@ export async function getBlockedUsers( return logAndFormatError( "get_blocked_users", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/getBotInfo.ts b/src/lib/telegram/mcp-tools/getBotInfo.ts similarity index 84% rename from src/lib/mcp/telegram/tools/getBotInfo.ts rename to src/lib/telegram/mcp-tools/getBotInfo.ts index 97eea2ad7..adcd13bd1 100644 --- a/src/lib/mcp/telegram/tools/getBotInfo.ts +++ b/src/lib/telegram/mcp-tools/getBotInfo.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { getBotInfo as getBotInfoApi } from "../api/getBotInfo"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function getBotInfo( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const botId = validateId(args.chat_id, "chat_id"); @@ -49,7 +49,7 @@ export async function getBotInfo( return logAndFormatError( "get_bot_info", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/getChat.ts b/src/lib/telegram/mcp-tools/getChat.ts similarity index 84% rename from src/lib/mcp/telegram/tools/getChat.ts rename to src/lib/telegram/mcp-tools/getChat.ts index 3c8f80c99..f16e8e36b 100644 --- a/src/lib/mcp/telegram/tools/getChat.ts +++ b/src/lib/telegram/mcp-tools/getChat.ts @@ -4,11 +4,11 @@ * Tries cached Redux state first, falls back to Telegram API when cache misses. */ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { getChat as getChatApi } from "../api/getChat"; export const tool: MCPTool = { @@ -28,7 +28,7 @@ export const tool: MCPTool = { export async function getChat( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -57,7 +57,9 @@ export async function getChat( if (chatInfo.unreadCount !== undefined) result.push(`Unread Messages: ${chatInfo.unreadCount}`); if (chatInfo.lastMessage) { - result.push(`Last Message: From ${chatInfo.lastMessage.from} at ${chatInfo.lastMessage.date}`); + result.push( + `Last Message: From ${chatInfo.lastMessage.from} at ${chatInfo.lastMessage.date}` + ); result.push(`Message: ${chatInfo.lastMessage.text}`); } @@ -69,7 +71,7 @@ export async function getChat( return logAndFormatError( "get_chat", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CHAT, + ErrorCategory.CHAT ); } } diff --git a/src/lib/mcp/telegram/tools/getChats.ts b/src/lib/telegram/mcp-tools/getChats.ts similarity index 83% rename from src/lib/mcp/telegram/tools/getChats.ts rename to src/lib/telegram/mcp-tools/getChats.ts index 18b1a2e98..a14709b2e 100644 --- a/src/lib/mcp/telegram/tools/getChats.ts +++ b/src/lib/telegram/mcp-tools/getChats.ts @@ -2,10 +2,10 @@ * Get Chats tool - Get a paginated list of chats */ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { optNumber } from "../args"; import { getChats as getChatsApi } from "../api/getChats"; import { formatEntity } from "../api/helpers"; @@ -32,7 +32,7 @@ export const tool: MCPTool = { export async function getChats( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const page = optNumber(args, "page", 1); @@ -43,7 +43,10 @@ export async function getChats( const paginatedChats = allChats.slice(start, start + pageSize); if (paginatedChats.length === 0) { - return { content: [{ type: "text", text: "Page out of range." }], fromCache }; + return { + content: [{ type: "text", text: "Page out of range." }], + fromCache, + }; } const lines = paginatedChats.map((chat) => { @@ -56,7 +59,7 @@ export async function getChats( return logAndFormatError( "get_chats", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CHAT, + ErrorCategory.CHAT ); } } diff --git a/src/lib/mcp/telegram/tools/getContactChats.ts b/src/lib/telegram/mcp-tools/getContactChats.ts similarity index 75% rename from src/lib/mcp/telegram/tools/getContactChats.ts rename to src/lib/telegram/mcp-tools/getContactChats.ts index c7ecc1f31..8b6e894fe 100644 --- a/src/lib/mcp/telegram/tools/getContactChats.ts +++ b/src/lib/telegram/mcp-tools/getContactChats.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { getContactChats as getContactChatsApi } from "../api/getContactChats"; export const tool: MCPTool = { @@ -11,13 +11,16 @@ export const tool: MCPTool = { export async function getContactChats( _args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const { data: dmChats, fromCache } = await getContactChatsApi(); if (dmChats.length === 0) { - return { content: [{ type: "text", text: "No contact chats found." }], fromCache }; + return { + content: [{ type: "text", text: "No contact chats found." }], + fromCache, + }; } const lines = dmChats.map((c) => { @@ -30,7 +33,7 @@ export async function getContactChats( return logAndFormatError( "get_contact_chats", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/getContactIds.ts b/src/lib/telegram/mcp-tools/getContactIds.ts similarity index 81% rename from src/lib/mcp/telegram/tools/getContactIds.ts rename to src/lib/telegram/mcp-tools/getContactIds.ts index bc70a59a3..ba669d38c 100644 --- a/src/lib/mcp/telegram/tools/getContactIds.ts +++ b/src/lib/telegram/mcp-tools/getContactIds.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { getContactIds as getContactIdsApi } from "../api/getContactIds"; export const tool: MCPTool = { @@ -11,7 +11,7 @@ export const tool: MCPTool = { export async function getContactIds( _args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const { data: ids, fromCache } = await getContactIdsApi(); @@ -33,7 +33,7 @@ export async function getContactIds( return logAndFormatError( "get_contact_ids", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/getDirectChatByContact.ts b/src/lib/telegram/mcp-tools/getDirectChatByContact.ts similarity index 65% rename from src/lib/mcp/telegram/tools/getDirectChatByContact.ts rename to src/lib/telegram/mcp-tools/getDirectChatByContact.ts index 28a82fb25..7cb6480a4 100644 --- a/src/lib/mcp/telegram/tools/getDirectChatByContact.ts +++ b/src/lib/telegram/mcp-tools/getDirectChatByContact.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { getDirectChatByContact as getDirectChatApi } from "../api/getDirectChatByContact"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function getDirectChatByContact( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const userId = validateId(args.user_id, "user_id"); @@ -27,7 +27,10 @@ export async function getDirectChatByContact( if (!dmChat) { return { content: [ - { type: "text", text: "No direct chat found with user " + userId + "." }, + { + type: "text", + text: "No direct chat found with user " + userId + ".", + }, ], fromCache, }; @@ -37,7 +40,13 @@ export async function getDirectChatByContact( content: [ { type: "text", - text: "Chat ID: " + dmChat.id + " | Title: " + dmChat.title + " | Username: " + (dmChat.username ?? "N/A"), + text: + "Chat ID: " + + dmChat.id + + " | Title: " + + dmChat.title + + " | Username: " + + (dmChat.username ?? "N/A"), }, ], fromCache, @@ -46,7 +55,7 @@ export async function getDirectChatByContact( return logAndFormatError( "get_direct_chat_by_contact", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/getDrafts.ts b/src/lib/telegram/mcp-tools/getDrafts.ts similarity index 81% rename from src/lib/mcp/telegram/tools/getDrafts.ts rename to src/lib/telegram/mcp-tools/getDrafts.ts index 10491dc80..5ada13b2b 100644 --- a/src/lib/mcp/telegram/tools/getDrafts.ts +++ b/src/lib/telegram/mcp-tools/getDrafts.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { getDrafts as getDraftsApi } from "../api/getDrafts"; export const tool: MCPTool = { @@ -11,7 +11,7 @@ export const tool: MCPTool = { export async function getDrafts( _args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const { data: drafts, fromCache } = await getDraftsApi(); @@ -33,7 +33,7 @@ export async function getDrafts( return logAndFormatError( "get_drafts", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.DRAFT, + ErrorCategory.DRAFT ); } } diff --git a/src/lib/mcp/telegram/tools/getGifSearch.ts b/src/lib/telegram/mcp-tools/getGifSearch.ts similarity index 88% rename from src/lib/mcp/telegram/tools/getGifSearch.ts rename to src/lib/telegram/mcp-tools/getGifSearch.ts index e477759db..03d5f209a 100644 --- a/src/lib/mcp/telegram/tools/getGifSearch.ts +++ b/src/lib/telegram/mcp-tools/getGifSearch.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { optNumber } from "../args"; import { getGifSearch as getGifSearchApi } from "../api/getGifSearch"; @@ -19,7 +19,7 @@ export const tool: MCPTool = { export async function getGifSearch( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const query = typeof args.query === "string" ? args.query : ""; @@ -54,7 +54,7 @@ export async function getGifSearch( return logAndFormatError( "get_gif_search", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MEDIA, + ErrorCategory.MEDIA ); } } diff --git a/src/lib/mcp/telegram/tools/getHistory.ts b/src/lib/telegram/mcp-tools/getHistory.ts similarity index 80% rename from src/lib/mcp/telegram/tools/getHistory.ts rename to src/lib/telegram/mcp-tools/getHistory.ts index a36bc42f6..2cd5b1b42 100644 --- a/src/lib/mcp/telegram/tools/getHistory.ts +++ b/src/lib/telegram/mcp-tools/getHistory.ts @@ -1,9 +1,9 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { getMessages as getMessagesApi } from "../api/getMessages"; import { getChatById, formatMessage } from "../api/helpers"; -import { validateId } from "../../validation"; +import { validateId } from "../../mcp/validation"; import { optNumber } from "../args"; export const tool: MCPTool = { @@ -21,7 +21,7 @@ export const tool: MCPTool = { export async function getHistory( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -35,7 +35,11 @@ export async function getHistory( }; } - const { data: messagesData, fromCache } = await getMessagesApi(chatId, limit, 0); + const { data: messagesData, fromCache } = await getMessagesApi( + chatId, + limit, + 0 + ); const messages = messagesData.length > 0 ? messagesData : undefined; if (!messages || messages.length === 0) { return { @@ -47,7 +51,9 @@ export async function getHistory( const lines = messages.map((msg) => { const f = formatMessage(msg); const from = msg.fromName ?? msg.fromId ?? "Unknown"; - return `ID: ${f.id} | ${from} | ${f.date} | ${f.text || "[Media/No text]"}`; + return `ID: ${f.id} | ${from} | ${f.date} | ${ + f.text || "[Media/No text]" + }`; }); return { content: [{ type: "text", text: lines.join("\n") }], fromCache }; @@ -55,7 +61,7 @@ export async function getHistory( return logAndFormatError( "get_history", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/getInviteLink.ts b/src/lib/telegram/mcp-tools/getInviteLink.ts similarity index 78% rename from src/lib/mcp/telegram/tools/getInviteLink.ts rename to src/lib/telegram/mcp-tools/getInviteLink.ts index c23d97372..4e946cfde 100644 --- a/src/lib/mcp/telegram/tools/getInviteLink.ts +++ b/src/lib/telegram/mcp-tools/getInviteLink.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { getInviteLink as getInviteLinkApi } from "../api/getInviteLink"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function getInviteLink( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -31,7 +31,7 @@ export async function getInviteLink( return logAndFormatError( "get_invite_link", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.GROUP, + ErrorCategory.GROUP ); } } diff --git a/src/lib/mcp/telegram/tools/getLastInteraction.ts b/src/lib/telegram/mcp-tools/getLastInteraction.ts similarity index 67% rename from src/lib/mcp/telegram/tools/getLastInteraction.ts rename to src/lib/telegram/mcp-tools/getLastInteraction.ts index bcd67d224..8430cd95b 100644 --- a/src/lib/mcp/telegram/tools/getLastInteraction.ts +++ b/src/lib/telegram/mcp-tools/getLastInteraction.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { getLastInteraction as getLastInteractionApi } from "../api/getLastInteraction"; export const tool: MCPTool = { @@ -18,11 +18,13 @@ export const tool: MCPTool = { export async function getLastInteraction( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); - const { data: interaction, fromCache } = await getLastInteractionApi(chatId); + const { data: interaction, fromCache } = await getLastInteractionApi( + chatId + ); if (!interaction) { return { @@ -35,7 +37,15 @@ export async function getLastInteraction( content: [ { type: "text", - text: "Last message in " + interaction.chatTitle + ":\nFrom: " + interaction.from + " | Date: " + interaction.date + " | " + interaction.text, + text: + "Last message in " + + interaction.chatTitle + + ":\nFrom: " + + interaction.from + + " | Date: " + + interaction.date + + " | " + + interaction.text, }, ], fromCache, @@ -44,7 +54,7 @@ export async function getLastInteraction( return logAndFormatError( "get_last_interaction", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/getMe.ts b/src/lib/telegram/mcp-tools/getMe.ts similarity index 86% rename from src/lib/mcp/telegram/tools/getMe.ts rename to src/lib/telegram/mcp-tools/getMe.ts index 1b2e4248a..9572e695a 100644 --- a/src/lib/mcp/telegram/tools/getMe.ts +++ b/src/lib/telegram/mcp-tools/getMe.ts @@ -2,10 +2,10 @@ * Get Me tool - Get your own user information */ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { getCurrentUser } from "../api/getCurrentUser"; import { formatEntity } from "../api/helpers"; @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function getMe( _args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const { data: user, fromCache } = await getCurrentUser(); @@ -47,7 +47,7 @@ export async function getMe( return logAndFormatError( "get_me", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.PROFILE, + ErrorCategory.PROFILE ); } } diff --git a/src/lib/mcp/telegram/tools/getMediaInfo.ts b/src/lib/telegram/mcp-tools/getMediaInfo.ts similarity index 85% rename from src/lib/mcp/telegram/tools/getMediaInfo.ts rename to src/lib/telegram/mcp-tools/getMediaInfo.ts index e66d027a8..9c39204cd 100644 --- a/src/lib/mcp/telegram/tools/getMediaInfo.ts +++ b/src/lib/telegram/mcp-tools/getMediaInfo.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { getMediaInfo as getMediaInfoApi } from "../api/getMediaInfo"; export const tool: MCPTool = { @@ -19,7 +19,7 @@ export const tool: MCPTool = { export async function getMediaInfo( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -56,7 +56,7 @@ export async function getMediaInfo( return logAndFormatError( "get_media_info", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MEDIA, + ErrorCategory.MEDIA ); } } diff --git a/src/lib/mcp/telegram/tools/getMessageContext.ts b/src/lib/telegram/mcp-tools/getMessageContext.ts similarity index 83% rename from src/lib/mcp/telegram/tools/getMessageContext.ts rename to src/lib/telegram/mcp-tools/getMessageContext.ts index abecc7687..c3df6dca2 100644 --- a/src/lib/mcp/telegram/tools/getMessageContext.ts +++ b/src/lib/telegram/mcp-tools/getMessageContext.ts @@ -1,9 +1,9 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { getMessages as getMessagesApi } from "../api/getMessages"; import { getChatById, formatMessage } from "../api/helpers"; -import { validateId } from "../../validation"; +import { validateId } from "../../mcp/validation"; import { optNumber } from "../args"; export const tool: MCPTool = { @@ -26,7 +26,7 @@ export const tool: MCPTool = { export async function getMessageContext( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -53,8 +53,13 @@ export async function getMessageContext( }; } - const { data: allMessagesData, fromCache } = await getMessagesApi(chatId, 200, 0); - const allMessages = allMessagesData.length > 0 ? allMessagesData : undefined; + const { data: allMessagesData, fromCache } = await getMessagesApi( + chatId, + 200, + 0 + ); + const allMessages = + allMessagesData.length > 0 ? allMessagesData : undefined; if (!allMessages || allMessages.length === 0) { return { content: [{ type: "text", text: "No messages found in this chat." }], @@ -63,7 +68,7 @@ export async function getMessageContext( } const targetIndex = allMessages.findIndex( - (m) => String(m.id) === String(messageId), + (m) => String(m.id) === String(messageId) ); if (targetIndex === -1) { return { @@ -85,7 +90,9 @@ export async function getMessageContext( const f = formatMessage(msg); const from = msg.fromName ?? msg.fromId ?? "Unknown"; const marker = String(msg.id) === String(messageId) ? " >>> " : " "; - return `${marker}ID: ${f.id} | ${from} | ${f.date} | ${f.text || "[Media/No text]"}`; + return `${marker}ID: ${f.id} | ${from} | ${f.date} | ${ + f.text || "[Media/No text]" + }`; }); return { content: [{ type: "text", text: lines.join("\n") }], fromCache }; @@ -93,7 +100,7 @@ export async function getMessageContext( return logAndFormatError( "get_message_context", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/getMessageReactions.ts b/src/lib/telegram/mcp-tools/getMessageReactions.ts similarity index 82% rename from src/lib/mcp/telegram/tools/getMessageReactions.ts rename to src/lib/telegram/mcp-tools/getMessageReactions.ts index 50b11b234..cdd7d6a20 100644 --- a/src/lib/mcp/telegram/tools/getMessageReactions.ts +++ b/src/lib/telegram/mcp-tools/getMessageReactions.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId, validatePositiveInt } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId, validatePositiveInt } from "../../mcp/validation"; import { getMessageReactions as getMessageReactionsApi } from "../api/getMessageReactions"; export const tool: MCPTool = { @@ -19,13 +19,16 @@ export const tool: MCPTool = { export async function getMessageReactions( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); const messageId = validatePositiveInt(args.message_id, "message_id"); - const { data: reactions, fromCache } = await getMessageReactionsApi(chatId, messageId); + const { data: reactions, fromCache } = await getMessageReactionsApi( + chatId, + messageId + ); if (reactions.length === 0) { return { @@ -54,7 +57,7 @@ export async function getMessageReactions( return logAndFormatError( "get_message_reactions", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/getMessages.ts b/src/lib/telegram/mcp-tools/getMessages.ts similarity index 84% rename from src/lib/mcp/telegram/tools/getMessages.ts rename to src/lib/telegram/mcp-tools/getMessages.ts index 7994caebb..a72c22589 100644 --- a/src/lib/mcp/telegram/tools/getMessages.ts +++ b/src/lib/telegram/mcp-tools/getMessages.ts @@ -2,14 +2,14 @@ * Get Messages tool - Get paginated messages from a specific chat */ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { getMessages as getMessagesApi } from "../api/getMessages"; import { getChatById, formatMessage } from "../api/helpers"; -import { validateId } from "../../validation"; -import type { TelegramMessage } from "../../../../store/telegram/types"; +import { validateId } from "../../mcp/validation"; +import type { TelegramMessage } from "../../../store/telegram/types"; import { optNumber } from "../args"; export const tool: MCPTool = { @@ -43,7 +43,7 @@ function senderDisplay(msg: TelegramMessage): string { export async function getMessages( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -59,7 +59,11 @@ export async function getMessages( }; } - const { data: messagesData, fromCache } = await getMessagesApi(chatId, pageSize, offset); + const { data: messagesData, fromCache } = await getMessagesApi( + chatId, + pageSize, + offset + ); const messages = messagesData.length > 0 ? messagesData : undefined; if (!messages || messages.length === 0) { return { @@ -74,7 +78,9 @@ export async function getMessages( ? ` | reply to ${msg.replyToMessageId}` : ""; const msgText = formatted.text || "[Media/No text]"; - return `ID: ${formatted.id} | ${senderDisplay(msg)} | Date: ${formatted.date}${replyStr} | Message: ${msgText}`; + return `ID: ${formatted.id} | ${senderDisplay(msg)} | Date: ${ + formatted.date + }${replyStr} | Message: ${msgText}`; }); return { content: [{ type: "text", text: lines.join("\n") }], fromCache }; @@ -82,7 +88,7 @@ export async function getMessages( return logAndFormatError( "get_messages", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/getParticipants.ts b/src/lib/telegram/mcp-tools/getParticipants.ts similarity index 85% rename from src/lib/mcp/telegram/tools/getParticipants.ts rename to src/lib/telegram/mcp-tools/getParticipants.ts index 0f552b043..2a60fd4c8 100644 --- a/src/lib/mcp/telegram/tools/getParticipants.ts +++ b/src/lib/telegram/mcp-tools/getParticipants.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { optNumber } from "../args"; import { getParticipants as getParticipantsApi } from "../api/getParticipants"; @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function getParticipants( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -28,7 +28,7 @@ export async function getParticipants( const { data: participants, fromCache } = await getParticipantsApi( chatId, - limit, + limit ); if (participants.length === 0) { @@ -56,7 +56,7 @@ export async function getParticipants( return logAndFormatError( "get_participants", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.GROUP, + ErrorCategory.GROUP ); } } diff --git a/src/lib/mcp/telegram/tools/getPinnedMessages.ts b/src/lib/telegram/mcp-tools/getPinnedMessages.ts similarity index 81% rename from src/lib/mcp/telegram/tools/getPinnedMessages.ts rename to src/lib/telegram/mcp-tools/getPinnedMessages.ts index 749c08526..5634877e7 100644 --- a/src/lib/mcp/telegram/tools/getPinnedMessages.ts +++ b/src/lib/telegram/mcp-tools/getPinnedMessages.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { getPinnedMessages as getPinnedMessagesApi } from "../api/getPinnedMessages"; export const tool: MCPTool = { @@ -18,12 +18,14 @@ export const tool: MCPTool = { export async function getPinnedMessages( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); - const { data: pinnedMessages, fromCache } = await getPinnedMessagesApi(chatId); + const { data: pinnedMessages, fromCache } = await getPinnedMessagesApi( + chatId + ); if (pinnedMessages.length === 0) { return { @@ -33,7 +35,7 @@ export async function getPinnedMessages( } const pinnedLines = pinnedMessages.map( - (msg) => `ID: ${msg.id} | Date: ${msg.date} | ${msg.text}`, + (msg) => `ID: ${msg.id} | Date: ${msg.date} | ${msg.text}` ); return { @@ -44,7 +46,7 @@ export async function getPinnedMessages( return logAndFormatError( "get_pinned_messages", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/getPrivacySettings.ts b/src/lib/telegram/mcp-tools/getPrivacySettings.ts similarity index 87% rename from src/lib/mcp/telegram/tools/getPrivacySettings.ts rename to src/lib/telegram/mcp-tools/getPrivacySettings.ts index b32588e9d..3238abdf3 100644 --- a/src/lib/mcp/telegram/tools/getPrivacySettings.ts +++ b/src/lib/telegram/mcp-tools/getPrivacySettings.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { getPrivacySettings as getPrivacySettingsApi } from "../api/getPrivacySettings"; export const tool: MCPTool = { @@ -21,7 +21,7 @@ export const tool: MCPTool = { export async function getPrivacySettings( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const keyStr = typeof args.key === "string" ? args.key : "last_seen"; @@ -57,7 +57,7 @@ export async function getPrivacySettings( return logAndFormatError( "get_privacy_settings", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.PROFILE, + ErrorCategory.PROFILE ); } } diff --git a/src/lib/mcp/telegram/tools/getRecentActions.ts b/src/lib/telegram/mcp-tools/getRecentActions.ts similarity index 83% rename from src/lib/mcp/telegram/tools/getRecentActions.ts rename to src/lib/telegram/mcp-tools/getRecentActions.ts index abdb48921..ab0925924 100644 --- a/src/lib/mcp/telegram/tools/getRecentActions.ts +++ b/src/lib/telegram/mcp-tools/getRecentActions.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { optNumber } from "../args"; import { getRecentActions as getRecentActionsApi } from "../api/getRecentActions"; @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function getRecentActions( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -28,7 +28,7 @@ export async function getRecentActions( const { data: actions, fromCache } = await getRecentActionsApi( chatId, - limit, + limit ); if (actions.length === 0) { @@ -48,7 +48,7 @@ export async function getRecentActions( return logAndFormatError( "get_recent_actions", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.ADMIN, + ErrorCategory.ADMIN ); } } diff --git a/src/lib/mcp/telegram/tools/getStickerSets.ts b/src/lib/telegram/mcp-tools/getStickerSets.ts similarity index 83% rename from src/lib/mcp/telegram/tools/getStickerSets.ts rename to src/lib/telegram/mcp-tools/getStickerSets.ts index 1d867f700..2974a1393 100644 --- a/src/lib/mcp/telegram/tools/getStickerSets.ts +++ b/src/lib/telegram/mcp-tools/getStickerSets.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { getStickerSets as getStickerSetsApi } from "../api/getStickerSets"; export const tool: MCPTool = { @@ -11,7 +11,7 @@ export const tool: MCPTool = { export async function getStickerSets( _args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const { data: sets, fromCache } = await getStickerSetsApi(); @@ -24,7 +24,7 @@ export async function getStickerSets( } const lines = sets.map( - (s) => "ID: " + s.id + " | " + s.title + " (" + s.count + " stickers)", + (s) => "ID: " + s.id + " | " + s.title + " (" + s.count + " stickers)" ); return { @@ -40,7 +40,7 @@ export async function getStickerSets( return logAndFormatError( "get_sticker_sets", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MEDIA, + ErrorCategory.MEDIA ); } } diff --git a/src/lib/mcp/telegram/tools/getUserPhotos.ts b/src/lib/telegram/mcp-tools/getUserPhotos.ts similarity index 78% rename from src/lib/mcp/telegram/tools/getUserPhotos.ts rename to src/lib/telegram/mcp-tools/getUserPhotos.ts index 882c8c4a8..a8f174b71 100644 --- a/src/lib/mcp/telegram/tools/getUserPhotos.ts +++ b/src/lib/telegram/mcp-tools/getUserPhotos.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { optNumber } from "../args"; import { getUserPhotos as getUserPhotosApi } from "../api/getUserPhotos"; @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function getUserPhotos( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const userId = validateId(args.user_id, "user_id"); @@ -29,7 +29,10 @@ export async function getUserPhotos( const { data: photos, fromCache } = await getUserPhotosApi(userId, limit); if (photos.length === 0) { - return { content: [{ type: "text", text: "No photos found." }], fromCache }; + return { + content: [{ type: "text", text: "No photos found." }], + fromCache, + }; } const lines = photos.map((photo, i: number) => { @@ -49,7 +52,7 @@ export async function getUserPhotos( return logAndFormatError( "get_user_photos", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.PROFILE, + ErrorCategory.PROFILE ); } } diff --git a/src/lib/mcp/telegram/tools/getUserStatus.ts b/src/lib/telegram/mcp-tools/getUserStatus.ts similarity index 74% rename from src/lib/mcp/telegram/tools/getUserStatus.ts rename to src/lib/telegram/mcp-tools/getUserStatus.ts index f53c1e6d5..a5a89c386 100644 --- a/src/lib/mcp/telegram/tools/getUserStatus.ts +++ b/src/lib/telegram/mcp-tools/getUserStatus.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { getUserStatus as getUserStatusApi } from "../api/getUserStatus"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function getUserStatus( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const userId = validateId(args.user_id, "user_id"); @@ -35,11 +35,7 @@ export async function getUserStatus( { type: "text", text: - userStatus.name + - " (ID: " + - userStatus.userId + - "): " + - statusText, + userStatus.name + " (ID: " + userStatus.userId + "): " + statusText, }, ], fromCache, @@ -48,7 +44,7 @@ export async function getUserStatus( return logAndFormatError( "get_user_status", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/importChatInvite.ts b/src/lib/telegram/mcp-tools/importChatInvite.ts similarity index 84% rename from src/lib/mcp/telegram/tools/importChatInvite.ts rename to src/lib/telegram/mcp-tools/importChatInvite.ts index 1a7380720..a9d8b56da 100644 --- a/src/lib/mcp/telegram/tools/importChatInvite.ts +++ b/src/lib/telegram/mcp-tools/importChatInvite.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { importChatInvite as importChatInviteApi } from "../api/importChatInvite"; export const tool: MCPTool = { @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function importChatInvite( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const hash = typeof args.hash === "string" ? args.hash : ""; @@ -39,7 +39,7 @@ export async function importChatInvite( return logAndFormatError( "import_chat_invite", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.GROUP, + ErrorCategory.GROUP ); } } diff --git a/src/lib/mcp/telegram/tools/importContacts.ts b/src/lib/telegram/mcp-tools/importContacts.ts similarity index 82% rename from src/lib/mcp/telegram/tools/importContacts.ts rename to src/lib/telegram/mcp-tools/importContacts.ts index f32c6fd73..d99b7d411 100644 --- a/src/lib/mcp/telegram/tools/importContacts.ts +++ b/src/lib/telegram/mcp-tools/importContacts.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import type { ContactInput } from "../api/apiResultTypes"; import { importContacts as importContactsApi } from "../api/importContacts"; @@ -30,7 +30,7 @@ export const tool: MCPTool = { export async function importContacts( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const contactsArg = args.contacts; @@ -38,9 +38,7 @@ export async function importContacts( throw new Error("contacts must be an array"); } - const { data } = await importContactsApi( - contactsArg as ContactInput[], - ); + const { data } = await importContactsApi(contactsArg as ContactInput[]); return { content: [ @@ -54,7 +52,7 @@ export async function importContacts( return logAndFormatError( "import_contacts", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/index.ts b/src/lib/telegram/mcp-tools/index.ts similarity index 100% rename from src/lib/mcp/telegram/tools/index.ts rename to src/lib/telegram/mcp-tools/index.ts diff --git a/src/lib/mcp/telegram/tools/inviteToGroup.ts b/src/lib/telegram/mcp-tools/inviteToGroup.ts similarity index 77% rename from src/lib/mcp/telegram/tools/inviteToGroup.ts rename to src/lib/telegram/mcp-tools/inviteToGroup.ts index ee56d0fc5..cd4cf5057 100644 --- a/src/lib/mcp/telegram/tools/inviteToGroup.ts +++ b/src/lib/telegram/mcp-tools/inviteToGroup.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { inviteToGroup as inviteToGroupApi } from "../api/inviteToGroup"; import { getChatById } from "../api/helpers"; @@ -24,7 +24,7 @@ export const tool: MCPTool = { export async function inviteToGroup( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -39,7 +39,9 @@ export async function inviteToGroup( content: [ { type: "text", - text: `Invited ${userIds.length} user(s) to ${chat?.title ?? chatId}.`, + text: `Invited ${userIds.length} user(s) to ${ + chat?.title ?? chatId + }.`, }, ], }; @@ -47,7 +49,7 @@ export async function inviteToGroup( return logAndFormatError( "invite_to_group", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.GROUP, + ErrorCategory.GROUP ); } } diff --git a/src/lib/mcp/telegram/tools/joinChatByLink.ts b/src/lib/telegram/mcp-tools/joinChatByLink.ts similarity index 85% rename from src/lib/mcp/telegram/tools/joinChatByLink.ts rename to src/lib/telegram/mcp-tools/joinChatByLink.ts index b41bbb7c2..6a100d3ea 100644 --- a/src/lib/mcp/telegram/tools/joinChatByLink.ts +++ b/src/lib/telegram/mcp-tools/joinChatByLink.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { joinChatByLink as joinChatByLinkApi } from "../api/joinChatByLink"; export const tool: MCPTool = { @@ -21,7 +21,7 @@ export const tool: MCPTool = { export async function joinChatByLink( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const link = typeof args.link === "string" ? args.link : ""; @@ -40,7 +40,7 @@ export async function joinChatByLink( return logAndFormatError( "join_chat_by_link", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.GROUP, + ErrorCategory.GROUP ); } } diff --git a/src/lib/mcp/telegram/tools/leaveChat.ts b/src/lib/telegram/mcp-tools/leaveChat.ts similarity index 79% rename from src/lib/mcp/telegram/tools/leaveChat.ts rename to src/lib/telegram/mcp-tools/leaveChat.ts index a7703846c..5c9a28a26 100644 --- a/src/lib/mcp/telegram/tools/leaveChat.ts +++ b/src/lib/telegram/mcp-tools/leaveChat.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { getChatById } from "../api/helpers"; import { leaveChat as leaveChatApi } from "../api/leaveChat"; @@ -19,7 +19,7 @@ export const tool: MCPTool = { export async function leaveChat( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -33,7 +33,7 @@ export async function leaveChat( return logAndFormatError( "leave_chat", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.GROUP, + ErrorCategory.GROUP ); } } diff --git a/src/lib/mcp/telegram/tools/listChats.ts b/src/lib/telegram/mcp-tools/listChats.ts similarity index 91% rename from src/lib/mcp/telegram/tools/listChats.ts rename to src/lib/telegram/mcp-tools/listChats.ts index 7d1263f1d..6a1a0ada8 100644 --- a/src/lib/mcp/telegram/tools/listChats.ts +++ b/src/lib/telegram/mcp-tools/listChats.ts @@ -2,10 +2,10 @@ * List Chats tool - List available chats with metadata */ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { optNumber, optString } from "../args"; import { getChats as getChatsApi } from "../api/getChats"; import { formatEntity } from "../api/helpers"; @@ -35,7 +35,7 @@ export const tool: MCPTool = { export async function listChats( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const limit = optNumber(args, "limit", 20); @@ -72,7 +72,7 @@ export async function listChats( return logAndFormatError( "list_chats", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CHAT, + ErrorCategory.CHAT ); } } diff --git a/src/lib/mcp/telegram/tools/listContacts.ts b/src/lib/telegram/mcp-tools/listContacts.ts similarity index 84% rename from src/lib/mcp/telegram/tools/listContacts.ts rename to src/lib/telegram/mcp-tools/listContacts.ts index c39dbbc8a..c15bf1fbe 100644 --- a/src/lib/mcp/telegram/tools/listContacts.ts +++ b/src/lib/telegram/mcp-tools/listContacts.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { listContacts as listContactsApi } from "../api/listContacts"; export const tool: MCPTool = { @@ -11,7 +11,7 @@ export const tool: MCPTool = { export async function listContacts( _args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const { data: contacts, fromCache } = await listContactsApi(); @@ -37,7 +37,7 @@ export async function listContacts( return logAndFormatError( "list_contacts", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/listInlineButtons.ts b/src/lib/telegram/mcp-tools/listInlineButtons.ts similarity index 84% rename from src/lib/mcp/telegram/tools/listInlineButtons.ts rename to src/lib/telegram/mcp-tools/listInlineButtons.ts index 9d2120e7f..3b8e35805 100644 --- a/src/lib/mcp/telegram/tools/listInlineButtons.ts +++ b/src/lib/telegram/mcp-tools/listInlineButtons.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { listInlineButtons as listInlineButtonsApi } from "../api/listInlineButtons"; export const tool: MCPTool = { @@ -19,7 +19,7 @@ export const tool: MCPTool = { export async function listInlineButtons( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -37,7 +37,10 @@ export async function listInlineButtons( }; } - const { data: buttons, fromCache } = await listInlineButtonsApi(chatId, messageId); + const { data: buttons, fromCache } = await listInlineButtonsApi( + chatId, + messageId + ); if (buttons.length === 0) { return { @@ -52,7 +55,7 @@ export async function listInlineButtons( } const lines = buttons.map( - (b) => "Row " + b.row + ", Button " + b.button + ': "' + b.text + '"', + (b) => "Row " + b.row + ", Button " + b.button + ': "' + b.text + '"' ); return { content: [{ type: "text", text: lines.join("\n") }], fromCache }; @@ -60,7 +63,7 @@ export async function listInlineButtons( return logAndFormatError( "list_inline_buttons", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/listMessages.ts b/src/lib/telegram/mcp-tools/listMessages.ts similarity index 85% rename from src/lib/mcp/telegram/tools/listMessages.ts rename to src/lib/telegram/mcp-tools/listMessages.ts index 3c399bfad..7e619dacc 100644 --- a/src/lib/mcp/telegram/tools/listMessages.ts +++ b/src/lib/telegram/mcp-tools/listMessages.ts @@ -2,14 +2,14 @@ * List Messages tool - Retrieve messages with optional filters */ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { optNumber, optString } from "../args"; import { getMessages as getMessagesApi } from "../api/getMessages"; import { getChatById, formatMessage } from "../api/helpers"; -import { validateId } from "../../validation"; +import { validateId } from "../../mcp/validation"; export const tool: MCPTool = { name: "list_messages", @@ -45,7 +45,7 @@ export const tool: MCPTool = { export async function listMessages( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -62,7 +62,11 @@ export async function listMessages( }; } - const { data: messagesRaw, fromCache } = await getMessagesApi(chatId, limit * 2, 0); + const { data: messagesRaw, fromCache } = await getMessagesApi( + chatId, + limit * 2, + 0 + ); let messages = messagesRaw.length > 0 ? messagesRaw : undefined; if (!messages || messages.length === 0) { return { @@ -76,7 +80,7 @@ export async function listMessages( if (searchQuery) { const q = searchQuery.toLowerCase(); messages = messages.filter((m) => - (m.message ?? "").toLowerCase().includes(q), + (m.message ?? "").toLowerCase().includes(q) ); } @@ -100,7 +104,9 @@ export async function listMessages( const replyStr = msg.replyToMessageId ? ` | reply to ${msg.replyToMessageId}` : ""; - const text = `ID: ${formatted.id} | ${from} | Date: ${formatted.date}${replyStr} | Message: ${formatted.text || "[Media/No text]"}`; + const text = `ID: ${formatted.id} | ${from} | Date: ${ + formatted.date + }${replyStr} | Message: ${formatted.text || "[Media/No text]"}`; return { type: "text" as const, text }; }); @@ -109,7 +115,7 @@ export async function listMessages( return logAndFormatError( "list_messages", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/listTopics.ts b/src/lib/telegram/mcp-tools/listTopics.ts similarity index 81% rename from src/lib/mcp/telegram/tools/listTopics.ts rename to src/lib/telegram/mcp-tools/listTopics.ts index edc36459e..0435e7cae 100644 --- a/src/lib/mcp/telegram/tools/listTopics.ts +++ b/src/lib/telegram/mcp-tools/listTopics.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { listTopics as listTopicsApi } from "../api/listTopics"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function listTopics( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -42,7 +42,7 @@ export async function listTopics( return logAndFormatError( "list_topics", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.GROUP, + ErrorCategory.GROUP ); } } diff --git a/src/lib/mcp/telegram/tools/markAsRead.ts b/src/lib/telegram/mcp-tools/markAsRead.ts similarity index 78% rename from src/lib/mcp/telegram/tools/markAsRead.ts rename to src/lib/telegram/mcp-tools/markAsRead.ts index cb2619b63..3982b3128 100644 --- a/src/lib/mcp/telegram/tools/markAsRead.ts +++ b/src/lib/telegram/mcp-tools/markAsRead.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { markAsRead as markAsReadApi } from "../api/markAsRead"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function markAsRead( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -35,7 +35,7 @@ export async function markAsRead( return logAndFormatError( "mark_as_read", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/muteChat.ts b/src/lib/telegram/mcp-tools/muteChat.ts similarity index 81% rename from src/lib/mcp/telegram/tools/muteChat.ts rename to src/lib/telegram/mcp-tools/muteChat.ts index bf069e246..24fda6b3c 100644 --- a/src/lib/mcp/telegram/tools/muteChat.ts +++ b/src/lib/telegram/mcp-tools/muteChat.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { muteChat as muteChatApi } from "../api/muteChat"; export const tool: MCPTool = { @@ -23,7 +23,7 @@ export const tool: MCPTool = { export async function muteChat( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -37,7 +37,7 @@ export async function muteChat( return logAndFormatError( "mute_chat", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CHAT, + ErrorCategory.CHAT ); } } diff --git a/src/lib/mcp/telegram/tools/notImplemented.ts b/src/lib/telegram/mcp-tools/notImplemented.ts similarity index 76% rename from src/lib/mcp/telegram/tools/notImplemented.ts rename to src/lib/telegram/mcp-tools/notImplemented.ts index 7d87c2676..3aa7a8931 100644 --- a/src/lib/mcp/telegram/tools/notImplemented.ts +++ b/src/lib/telegram/mcp-tools/notImplemented.ts @@ -1,4 +1,4 @@ -import type { MCPToolResult } from "../../types"; +import type { MCPToolResult } from "../../mcp/types"; export function notImplemented(name: string): MCPToolResult { return { diff --git a/src/lib/mcp/telegram/tools/pinMessage.ts b/src/lib/telegram/mcp-tools/pinMessage.ts similarity index 80% rename from src/lib/mcp/telegram/tools/pinMessage.ts rename to src/lib/telegram/mcp-tools/pinMessage.ts index 7eaf29607..31b327a13 100644 --- a/src/lib/mcp/telegram/tools/pinMessage.ts +++ b/src/lib/telegram/mcp-tools/pinMessage.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId, validatePositiveInt } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId, validatePositiveInt } from "../../mcp/validation"; import { pinMessage as pinMessageApi } from "../api/pinMessage"; export const tool: MCPTool = { @@ -19,7 +19,7 @@ export const tool: MCPTool = { export async function pinMessage( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -40,7 +40,7 @@ export async function pinMessage( return logAndFormatError( "pin_message", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/pressInlineButton.ts b/src/lib/telegram/mcp-tools/pressInlineButton.ts similarity index 80% rename from src/lib/mcp/telegram/tools/pressInlineButton.ts rename to src/lib/telegram/mcp-tools/pressInlineButton.ts index c1ca0ce2c..a70ed6482 100644 --- a/src/lib/mcp/telegram/tools/pressInlineButton.ts +++ b/src/lib/telegram/mcp-tools/pressInlineButton.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId, validatePositiveInt } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId, validatePositiveInt } from "../../mcp/validation"; import { pressInlineButton as pressInlineButtonApi } from "../api/pressInlineButton"; export const tool: MCPTool = { @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function pressInlineButton( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -33,7 +33,11 @@ export async function pressInlineButton( isError: true, }; - const { data: answer, fromCache } = await pressInlineButtonApi(chatId, messageId, data); + const { data: answer, fromCache } = await pressInlineButtonApi( + chatId, + messageId, + data + ); return { content: [{ type: "text", text: answer }], @@ -43,7 +47,7 @@ export async function pressInlineButton( return logAndFormatError( "press_inline_button", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/promoteAdmin.ts b/src/lib/telegram/mcp-tools/promoteAdmin.ts similarity index 82% rename from src/lib/mcp/telegram/tools/promoteAdmin.ts rename to src/lib/telegram/mcp-tools/promoteAdmin.ts index 865ae48f2..d53f688e0 100644 --- a/src/lib/mcp/telegram/tools/promoteAdmin.ts +++ b/src/lib/telegram/mcp-tools/promoteAdmin.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { promoteAdmin as promoteAdminApi } from "../api/promoteAdmin"; import { getChatById } from "../api/helpers"; @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function promoteAdmin( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -41,7 +41,7 @@ export async function promoteAdmin( return logAndFormatError( "promote_admin", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.ADMIN, + ErrorCategory.ADMIN ); } } diff --git a/src/lib/mcp/telegram/tools/removeReaction.ts b/src/lib/telegram/mcp-tools/removeReaction.ts similarity index 81% rename from src/lib/mcp/telegram/tools/removeReaction.ts rename to src/lib/telegram/mcp-tools/removeReaction.ts index d1fbe99e1..cb4165837 100644 --- a/src/lib/mcp/telegram/tools/removeReaction.ts +++ b/src/lib/telegram/mcp-tools/removeReaction.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId, validatePositiveInt } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId, validatePositiveInt } from "../../mcp/validation"; import { removeReaction as removeReactionApi } from "../api/removeReaction"; export const tool: MCPTool = { @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function removeReaction( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -41,7 +41,7 @@ export async function removeReaction( return logAndFormatError( "remove_reaction", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/replyToMessage.ts b/src/lib/telegram/mcp-tools/replyToMessage.ts similarity index 90% rename from src/lib/mcp/telegram/tools/replyToMessage.ts rename to src/lib/telegram/mcp-tools/replyToMessage.ts index a141c819d..df062c92c 100644 --- a/src/lib/mcp/telegram/tools/replyToMessage.ts +++ b/src/lib/telegram/mcp-tools/replyToMessage.ts @@ -2,14 +2,14 @@ * Reply To Message tool - Reply to a specific message in a chat */ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { sendMessage } from "../api/sendMessage"; import { getChatById } from "../api/helpers"; import { toHumanReadableAction } from "../toolActionParser"; -import { validateId } from "../../validation"; +import { validateId } from "../../mcp/validation"; export const tool: MCPTool = { name: "reply_to_message", @@ -32,7 +32,7 @@ export const tool: MCPTool = { export async function replyToMessage( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -89,7 +89,7 @@ export async function replyToMessage( return logAndFormatError( "reply_to_message", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/resolveUsername.ts b/src/lib/telegram/mcp-tools/resolveUsername.ts similarity index 84% rename from src/lib/mcp/telegram/tools/resolveUsername.ts rename to src/lib/telegram/mcp-tools/resolveUsername.ts index 94d323d8b..eda047c60 100644 --- a/src/lib/mcp/telegram/tools/resolveUsername.ts +++ b/src/lib/telegram/mcp-tools/resolveUsername.ts @@ -5,10 +5,10 @@ * Falls back to cached chat lookup if the API call fails. */ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { resolveUsername as resolveUsernameApi } from "../api/resolveUsername"; export const tool: MCPTool = { @@ -28,7 +28,7 @@ export const tool: MCPTool = { export async function resolveUsername( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const raw = typeof args.username === "string" ? args.username : ""; @@ -44,9 +44,7 @@ export async function resolveUsername( if (!resolved) { const username = raw.startsWith("@") ? raw : `@${raw}`; return { - content: [ - { type: "text", text: `Username ${username} not found` }, - ], + content: [{ type: "text", text: `Username ${username} not found` }], isError: true, }; } @@ -64,7 +62,7 @@ export async function resolveUsername( return logAndFormatError( "resolve_username", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.SEARCH, + ErrorCategory.SEARCH ); } } diff --git a/src/lib/mcp/telegram/tools/saveDraft.ts b/src/lib/telegram/mcp-tools/saveDraft.ts similarity index 81% rename from src/lib/mcp/telegram/tools/saveDraft.ts rename to src/lib/telegram/mcp-tools/saveDraft.ts index 54f740445..2547449e6 100644 --- a/src/lib/mcp/telegram/tools/saveDraft.ts +++ b/src/lib/telegram/mcp-tools/saveDraft.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { saveDraft as saveDraftApi } from "../api/saveDraft"; export const tool: MCPTool = { @@ -19,7 +19,7 @@ export const tool: MCPTool = { export async function saveDraft( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -40,7 +40,7 @@ export async function saveDraft( return logAndFormatError( "save_draft", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.DRAFT, + ErrorCategory.DRAFT ); } } diff --git a/src/lib/mcp/telegram/tools/searchContacts.ts b/src/lib/telegram/mcp-tools/searchContacts.ts similarity index 85% rename from src/lib/mcp/telegram/tools/searchContacts.ts rename to src/lib/telegram/mcp-tools/searchContacts.ts index 5bd7c15f7..4c3464f4b 100644 --- a/src/lib/mcp/telegram/tools/searchContacts.ts +++ b/src/lib/telegram/mcp-tools/searchContacts.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { optNumber } from "../args"; import { searchContacts as searchContactsApi } from "../api/searchContacts"; @@ -19,16 +19,13 @@ export const tool: MCPTool = { export async function searchContacts( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const query = typeof args.query === "string" ? args.query : ""; const limit = optNumber(args, "limit", 20); - const { data: contacts, fromCache } = await searchContactsApi( - query, - limit, - ); + const { data: contacts, fromCache } = await searchContactsApi(query, limit); if (contacts.length === 0) { return { @@ -50,7 +47,7 @@ export async function searchContacts( return logAndFormatError( "search_contacts", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/searchMessages.ts b/src/lib/telegram/mcp-tools/searchMessages.ts similarity index 87% rename from src/lib/mcp/telegram/tools/searchMessages.ts rename to src/lib/telegram/mcp-tools/searchMessages.ts index 9c220e415..0990d0421 100644 --- a/src/lib/mcp/telegram/tools/searchMessages.ts +++ b/src/lib/telegram/mcp-tools/searchMessages.ts @@ -5,12 +5,12 @@ * Falls back to filtering cached messages if the API call fails. */ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { optNumber } from "../args"; -import { validateId } from "../../validation"; +import { validateId } from "../../mcp/validation"; import { searchMessages as searchMessagesApi } from "../api/searchMessages"; export const tool: MCPTool = { @@ -33,7 +33,7 @@ export const tool: MCPTool = { export async function searchMessages( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -47,7 +47,11 @@ export async function searchMessages( }; } - const { data: messages, fromCache } = await searchMessagesApi(chatId, query, limit); + const { data: messages, fromCache } = await searchMessagesApi( + chatId, + query, + limit + ); if (messages.length === 0) { return { @@ -76,7 +80,7 @@ export async function searchMessages( return logAndFormatError( "search_messages", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.SEARCH, + ErrorCategory.SEARCH ); } } diff --git a/src/lib/mcp/telegram/tools/searchPublicChats.ts b/src/lib/telegram/mcp-tools/searchPublicChats.ts similarity index 89% rename from src/lib/mcp/telegram/tools/searchPublicChats.ts rename to src/lib/telegram/mcp-tools/searchPublicChats.ts index b7a611577..23180dfa2 100644 --- a/src/lib/mcp/telegram/tools/searchPublicChats.ts +++ b/src/lib/telegram/mcp-tools/searchPublicChats.ts @@ -5,9 +5,9 @@ * Falls back to filtering cached chats if the API call fails. */ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { searchPublicChats as searchPublicChatsApi } from "../api/searchPublicChats"; export const tool: MCPTool = { @@ -25,7 +25,7 @@ export const tool: MCPTool = { export async function searchPublicChats( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const query = typeof args.query === "string" ? args.query : ""; @@ -64,7 +64,7 @@ export async function searchPublicChats( return logAndFormatError( "search_public_chats", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.SEARCH, + ErrorCategory.SEARCH ); } } diff --git a/src/lib/mcp/telegram/tools/sendMessage.ts b/src/lib/telegram/mcp-tools/sendMessage.ts similarity index 79% rename from src/lib/mcp/telegram/tools/sendMessage.ts rename to src/lib/telegram/mcp-tools/sendMessage.ts index 927f87a5f..12e83b052 100644 --- a/src/lib/mcp/telegram/tools/sendMessage.ts +++ b/src/lib/telegram/mcp-tools/sendMessage.ts @@ -2,13 +2,13 @@ * Send Message tool - Send a message to a specific chat */ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { sendMessage as sendMessageApiCall } from "../api/sendMessage"; import { toHumanReadableAction } from "../toolActionParser"; -import { validateId } from "../../validation"; +import { validateId } from "../../mcp/validation"; export const tool: MCPTool = { name: "send_message", @@ -29,7 +29,7 @@ export const tool: MCPTool = { export async function sendMessage( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -40,7 +40,10 @@ export async function sendMessage( isError: true, }; } - const { data: result, fromCache } = await sendMessageApiCall(chatId, message); + const { data: result, fromCache } = await sendMessageApiCall( + chatId, + message + ); if (!result) { return { content: [ @@ -49,12 +52,15 @@ export async function sendMessage( isError: true, }; } - return { content: [{ type: "text", text: "Message sent successfully." }], fromCache }; + return { + content: [{ type: "text", text: "Message sent successfully." }], + fromCache, + }; } catch (error) { return logAndFormatError( "send_message", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/sendReaction.ts b/src/lib/telegram/mcp-tools/sendReaction.ts similarity index 82% rename from src/lib/mcp/telegram/tools/sendReaction.ts rename to src/lib/telegram/mcp-tools/sendReaction.ts index 2f4590f73..803c5d72f 100644 --- a/src/lib/mcp/telegram/tools/sendReaction.ts +++ b/src/lib/telegram/mcp-tools/sendReaction.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId, validatePositiveInt } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId, validatePositiveInt } from "../../mcp/validation"; import { sendReaction as sendReactionApi } from "../api/sendReaction"; export const tool: MCPTool = { @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function sendReaction( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -43,7 +43,7 @@ export async function sendReaction( return logAndFormatError( "send_reaction", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/setBotCommands.ts b/src/lib/telegram/mcp-tools/setBotCommands.ts similarity index 82% rename from src/lib/mcp/telegram/tools/setBotCommands.ts rename to src/lib/telegram/mcp-tools/setBotCommands.ts index 25ccb28a3..848e70c95 100644 --- a/src/lib/mcp/telegram/tools/setBotCommands.ts +++ b/src/lib/telegram/mcp-tools/setBotCommands.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import type { BotCommandInput } from "../api/apiResultTypes"; import { setBotCommands as setBotCommandsApi } from "../api/setBotCommands"; @@ -19,13 +19,13 @@ export const tool: MCPTool = { export async function setBotCommands( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const cmds = Array.isArray(args.commands) ? args.commands : []; const { data: count, fromCache } = await setBotCommandsApi( - cmds as BotCommandInput[], + cmds as BotCommandInput[] ); return { @@ -41,7 +41,7 @@ export async function setBotCommands( return logAndFormatError( "set_bot_commands", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.PROFILE, + ErrorCategory.PROFILE ); } } diff --git a/src/lib/mcp/telegram/tools/setPrivacySettings.ts b/src/lib/telegram/mcp-tools/setPrivacySettings.ts similarity index 85% rename from src/lib/mcp/telegram/tools/setPrivacySettings.ts rename to src/lib/telegram/mcp-tools/setPrivacySettings.ts index fb615a575..83c53d52e 100644 --- a/src/lib/mcp/telegram/tools/setPrivacySettings.ts +++ b/src/lib/telegram/mcp-tools/setPrivacySettings.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { setPrivacySettings as setPrivacySettingsApi } from "../api/setPrivacySettings"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function setPrivacySettings( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const keyStr = typeof args.setting === "string" ? args.setting : ""; @@ -39,7 +39,7 @@ export async function setPrivacySettings( return logAndFormatError( "set_privacy_settings", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.PROFILE, + ErrorCategory.PROFILE ); } } diff --git a/src/lib/mcp/telegram/tools/setProfilePhoto.ts b/src/lib/telegram/mcp-tools/setProfilePhoto.ts similarity index 82% rename from src/lib/mcp/telegram/tools/setProfilePhoto.ts rename to src/lib/telegram/mcp-tools/setProfilePhoto.ts index b93e9fa75..eeba832ad 100644 --- a/src/lib/mcp/telegram/tools/setProfilePhoto.ts +++ b/src/lib/telegram/mcp-tools/setProfilePhoto.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { setProfilePhoto as setProfilePhotoApi } from "../api/setProfilePhoto"; export const tool: MCPTool = { @@ -17,7 +17,7 @@ export const tool: MCPTool = { export async function setProfilePhoto( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const filePath = typeof args.file_path === "string" ? args.file_path : ""; @@ -35,7 +35,7 @@ export async function setProfilePhoto( return logAndFormatError( "set_profile_photo", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.PROFILE, + ErrorCategory.PROFILE ); } } diff --git a/src/lib/mcp/telegram/tools/subscribePublicChannel.ts b/src/lib/telegram/mcp-tools/subscribePublicChannel.ts similarity index 85% rename from src/lib/mcp/telegram/tools/subscribePublicChannel.ts rename to src/lib/telegram/mcp-tools/subscribePublicChannel.ts index 352eb98bb..98933d94a 100644 --- a/src/lib/mcp/telegram/tools/subscribePublicChannel.ts +++ b/src/lib/telegram/mcp-tools/subscribePublicChannel.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { subscribePublicChannel as subscribePublicChannelApi } from "../api/subscribePublicChannel"; export const tool: MCPTool = { @@ -17,7 +17,7 @@ export const tool: MCPTool = { export async function subscribePublicChannel( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const username = typeof args.username === "string" ? args.username : ""; @@ -36,7 +36,7 @@ export async function subscribePublicChannel( return logAndFormatError( "subscribe_public_channel", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.GROUP, + ErrorCategory.GROUP ); } } diff --git a/src/lib/mcp/telegram/tools/unarchiveChat.ts b/src/lib/telegram/mcp-tools/unarchiveChat.ts similarity index 77% rename from src/lib/mcp/telegram/tools/unarchiveChat.ts rename to src/lib/telegram/mcp-tools/unarchiveChat.ts index e7516625d..2b4d5977c 100644 --- a/src/lib/mcp/telegram/tools/unarchiveChat.ts +++ b/src/lib/telegram/mcp-tools/unarchiveChat.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { unarchiveChat as unarchiveChatApi } from "../api/unarchiveChat"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function unarchiveChat( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -31,7 +31,7 @@ export async function unarchiveChat( return logAndFormatError( "unarchive_chat", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CHAT, + ErrorCategory.CHAT ); } } diff --git a/src/lib/mcp/telegram/tools/unbanUser.ts b/src/lib/telegram/mcp-tools/unbanUser.ts similarity index 82% rename from src/lib/mcp/telegram/tools/unbanUser.ts rename to src/lib/telegram/mcp-tools/unbanUser.ts index 15366f34d..4175ba7d6 100644 --- a/src/lib/mcp/telegram/tools/unbanUser.ts +++ b/src/lib/telegram/mcp-tools/unbanUser.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { unbanUser as unbanUserApi } from "../api/unbanUser"; import { getChatById } from "../api/helpers"; @@ -20,7 +20,7 @@ export const tool: MCPTool = { export async function unbanUser( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -41,7 +41,7 @@ export async function unbanUser( return logAndFormatError( "unban_user", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.ADMIN, + ErrorCategory.ADMIN ); } } diff --git a/src/lib/mcp/telegram/tools/unblockUser.ts b/src/lib/telegram/mcp-tools/unblockUser.ts similarity index 76% rename from src/lib/mcp/telegram/tools/unblockUser.ts rename to src/lib/telegram/mcp-tools/unblockUser.ts index d4f1e6cde..43280eb6d 100644 --- a/src/lib/mcp/telegram/tools/unblockUser.ts +++ b/src/lib/telegram/mcp-tools/unblockUser.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { unblockUser as unblockUserApi } from "../api/unblockUser"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function unblockUser( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const userId = validateId(args.user_id, "user_id"); @@ -30,7 +30,7 @@ export async function unblockUser( return logAndFormatError( "unblock_user", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CONTACT, + ErrorCategory.CONTACT ); } } diff --git a/src/lib/mcp/telegram/tools/unmuteChat.ts b/src/lib/telegram/mcp-tools/unmuteChat.ts similarity index 77% rename from src/lib/mcp/telegram/tools/unmuteChat.ts rename to src/lib/telegram/mcp-tools/unmuteChat.ts index fb1bc70dc..1af9e3ee8 100644 --- a/src/lib/mcp/telegram/tools/unmuteChat.ts +++ b/src/lib/telegram/mcp-tools/unmuteChat.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId } from "../../mcp/validation"; import { unmuteChat as unmuteChatApi } from "../api/unmuteChat"; export const tool: MCPTool = { @@ -18,7 +18,7 @@ export const tool: MCPTool = { export async function unmuteChat( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -31,7 +31,7 @@ export async function unmuteChat( return logAndFormatError( "unmute_chat", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.CHAT, + ErrorCategory.CHAT ); } } diff --git a/src/lib/mcp/telegram/tools/unpinMessage.ts b/src/lib/telegram/mcp-tools/unpinMessage.ts similarity index 80% rename from src/lib/mcp/telegram/tools/unpinMessage.ts rename to src/lib/telegram/mcp-tools/unpinMessage.ts index 960e58e95..efccda9d3 100644 --- a/src/lib/mcp/telegram/tools/unpinMessage.ts +++ b/src/lib/telegram/mcp-tools/unpinMessage.ts @@ -1,7 +1,7 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; -import { validateId, validatePositiveInt } from "../../validation"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; +import { validateId, validatePositiveInt } from "../../mcp/validation"; import { unpinMessage as unpinMessageApi } from "../api/unpinMessage"; export const tool: MCPTool = { @@ -19,7 +19,7 @@ export const tool: MCPTool = { export async function unpinMessage( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const chatId = validateId(args.chat_id, "chat_id"); @@ -40,7 +40,7 @@ export async function unpinMessage( return logAndFormatError( "unpin_message", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.MSG, + ErrorCategory.MSG ); } } diff --git a/src/lib/mcp/telegram/tools/updateProfile.ts b/src/lib/telegram/mcp-tools/updateProfile.ts similarity index 85% rename from src/lib/mcp/telegram/tools/updateProfile.ts rename to src/lib/telegram/mcp-tools/updateProfile.ts index 7b2d774a8..31343e9ac 100644 --- a/src/lib/mcp/telegram/tools/updateProfile.ts +++ b/src/lib/telegram/mcp-tools/updateProfile.ts @@ -1,6 +1,6 @@ -import type { MCPTool, MCPToolResult } from "../../types"; +import type { MCPTool, MCPToolResult } from "../../mcp/types"; import type { TelegramMCPContext } from "../types"; -import { ErrorCategory, logAndFormatError } from "../../errorHandler"; +import { ErrorCategory, logAndFormatError } from "../../mcp/errorHandler"; import { optString } from "../args"; import { updateProfile as updateProfileApi } from "../api/updateProfile"; @@ -19,7 +19,7 @@ export const tool: MCPTool = { export async function updateProfile( args: Record, - _context: TelegramMCPContext, + _context: TelegramMCPContext ): Promise { try { const firstName = optString(args, "first_name"); @@ -42,7 +42,7 @@ export async function updateProfile( return logAndFormatError( "update_profile", error instanceof Error ? error : new Error(String(error)), - ErrorCategory.PROFILE, + ErrorCategory.PROFILE ); } } diff --git a/src/lib/mcp/telegram/server.test.ts b/src/lib/telegram/server.test.ts similarity index 88% rename from src/lib/mcp/telegram/server.test.ts rename to src/lib/telegram/server.test.ts index a228454ab..827914be1 100644 --- a/src/lib/mcp/telegram/server.test.ts +++ b/src/lib/telegram/server.test.ts @@ -5,7 +5,7 @@ */ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; -import type { MCPToolResult } from "../types"; +import type { MCPToolResult } from "../mcp/types"; // Use vi.hoisted so mock variables are available when vi.mock factories run const { @@ -21,12 +21,12 @@ const { })); // Mock the transport module — must use hoisted variables -vi.mock("../transport", () => ({ +vi.mock("../mcp/transport", () => ({ SocketIOMCPTransportImpl: vi.fn(), })); // Mock the store -vi.mock("../../../store", () => ({ +vi.mock("../../store", () => ({ store: { getState: vi.fn(() => ({ user: { user: { _id: "u1" } }, @@ -70,7 +70,7 @@ vi.mock("../../../store", () => ({ }, })); -vi.mock("../../../store/telegramSelectors", () => ({ +vi.mock("../../store/telegramSelectors", () => ({ selectTelegramUserState: vi.fn((state: any) => { const userId = state?.user?.user?._id ?? ""; return state?.telegram?.byUser?.[userId] ?? {}; @@ -80,7 +80,7 @@ vi.mock("../../../store/telegramSelectors", () => ({ })); // Mock the skills module -vi.mock("../skills", () => ({ +vi.mock("../mcp/skills", () => ({ useExtraToolDefinition: { name: "use_extra_tool", description: "meta", @@ -93,7 +93,7 @@ vi.mock("../skills", () => ({ })); // Mock rateLimiter -vi.mock("../rateLimiter", () => ({ +vi.mock("../mcp/rateLimiter", () => ({ enforceRateLimit: vi.fn().mockResolvedValue(undefined), resetRequestCallCount: vi.fn(), isStateOnlyTool: vi.fn(() => false), @@ -102,7 +102,7 @@ vi.mock("../rateLimiter", () => ({ })); // Mock logger -vi.mock("../logger", () => ({ +vi.mock("../mcp/logger", () => ({ mcpLog: vi.fn(), mcpWarn: vi.fn(), })); @@ -128,7 +128,7 @@ vi.mock("./api/getChats", () => ({ }, ], fromCache: true, - }), + }) ), })); @@ -137,7 +137,7 @@ vi.mock("./api/sendMessage", () => ({ Promise.resolve({ data: { id: "msg1", message: "Hello", chatId: "1", date: 1234567890 }, fromCache: false, - }), + }) ), })); @@ -152,7 +152,7 @@ vi.mock("./api/getCurrentUser", () => ({ isBot: false, }, fromCache: true, - }), + }) ), })); @@ -176,7 +176,7 @@ vi.mock("./api/getMessages", () => ({ }, ], fromCache: true, - }), + }) ), })); @@ -198,14 +198,14 @@ vi.mock("./api/helpers", async (importOriginal) => { // Helper: extract emitted data for a given event name function getEmittedResult(eventName: string): MCPToolResult | undefined { const emitCall = mockTransportEmit.mock.calls.find( - (call: any[]) => call[0] === eventName, + (call: any[]) => call[0] === eventName ); return emitCall?.[1]?.result; } function getEmittedPayload(eventName: string): any { const emitCall = mockTransportEmit.mock.calls.find( - (call: any[]) => call[0] === eventName, + (call: any[]) => call[0] === eventName ); return emitCall?.[1]; } @@ -218,8 +218,10 @@ describe("TelegramMCPServer", () => { vi.clearAllMocks(); // Re-apply mock implementations (mockReset: true in config clears them between tests) - const { SocketIOMCPTransportImpl } = await import("../transport"); - vi.mocked(SocketIOMCPTransportImpl).mockImplementation(function (this: any) { + const { SocketIOMCPTransportImpl } = await import("../mcp/transport"); + vi.mocked(SocketIOMCPTransportImpl).mockImplementation(function ( + this: any + ) { this.on = mockTransportOn; this.off = mockTransportOff; this.emit = mockTransportEmit; @@ -228,12 +230,12 @@ describe("TelegramMCPServer", () => { return this; } as any); - const rateLimiter = await import("../rateLimiter"); + const rateLimiter = await import("../mcp/rateLimiter"); vi.mocked(rateLimiter.enforceRateLimit).mockResolvedValue(undefined); vi.mocked(rateLimiter.resetRequestCallCount).mockImplementation(() => {}); vi.mocked(rateLimiter.isStateOnlyTool).mockReturnValue(false); - const skills = await import("../skills"); + const skills = await import("../mcp/skills"); vi.mocked(skills.executeExtraToolIfExists).mockReturnValue(null as any); vi.mocked(skills.getAllExtraTools).mockReturnValue([]); vi.mocked(skills.isExtraToolByName).mockReturnValue(false); @@ -242,39 +244,78 @@ describe("TelegramMCPServer", () => { const getChatsApi = await import("./api/getChats"); vi.mocked(getChatsApi.getChats).mockResolvedValue({ data: [ - { id: "1", title: "Chat One", type: "private", unreadCount: 0, isPinned: false }, - { id: "2", title: "Group Chat", type: "group", unreadCount: 5, isPinned: true }, + { + id: "1", + title: "Chat One", + type: "private", + unreadCount: 0, + isPinned: false, + }, + { + id: "2", + title: "Group Chat", + type: "group", + unreadCount: 5, + isPinned: true, + }, ], fromCache: true, }); const sendMsgApi = await import("./api/sendMessage"); vi.mocked(sendMsgApi.sendMessage).mockResolvedValue({ - data: { id: "msg1", message: "Hello", chatId: "1", date: 1234567890 } as any, + data: { + id: "msg1", + message: "Hello", + chatId: "1", + date: 1234567890, + } as any, fromCache: false, }); const getUserApi = await import("./api/getCurrentUser"); vi.mocked(getUserApi.getCurrentUser).mockResolvedValue({ - data: { id: "1", firstName: "Alice", lastName: "Smith", username: "alice", isBot: false } as any, + data: { + id: "1", + firstName: "Alice", + lastName: "Smith", + username: "alice", + isBot: false, + } as any, fromCache: true, }); const getMsgsApi = await import("./api/getMessages"); vi.mocked(getMsgsApi.getMessages).mockResolvedValue({ data: [ - { id: "m1", message: "First message", chatId: "1", date: 1234567890, fromId: "100" } as any, - { id: "m2", message: "Second message", chatId: "1", date: 1234567891, fromId: "200" } as any, + { + id: "m1", + message: "First message", + chatId: "1", + date: 1234567890, + fromId: "100", + } as any, + { + id: "m2", + message: "Second message", + chatId: "1", + date: 1234567891, + fromId: "200", + } as any, ], fromCache: true, }); const helpers = await import("./api/helpers"); vi.mocked(helpers.getChatById).mockReturnValue({ - id: "1", title: "Chat One", type: "private", unreadCount: 0, isPinned: false, + id: "1", + title: "Chat One", + type: "private", + unreadCount: 0, + isPinned: false, }); - const store = await import("../../../store"); + const store = await import("../../store"); vi.mocked(store.store.getState).mockReturnValue({ user: { user: { _id: "u1" } }, telegram: { @@ -302,11 +343,9 @@ describe("TelegramMCPServer", () => { // Extract the registered event handlers from transport.on calls const onCalls = mockTransportOn.mock.calls; - const toolCallEntry = onCalls.find( - (call: any[]) => call[0] === "toolCall", - ); + const toolCallEntry = onCalls.find((call: any[]) => call[0] === "toolCall"); const listToolsEntry = onCalls.find( - (call: any[]) => call[0] === "listTools", + (call: any[]) => call[0] === "listTools" ); toolCallHandler = toolCallEntry![1]; @@ -364,7 +403,7 @@ describe("TelegramMCPServer", () => { await vi.waitFor(() => { expect(mockTransportEmit).toHaveBeenCalledWith( "toolResult", - expect.objectContaining({ requestId: "req-1" }), + expect.objectContaining({ requestId: "req-1" }) ); }); @@ -512,9 +551,9 @@ describe("TelegramMCPServer", () => { it("should handle rate limit errors", async () => { // Mock enforceRateLimit to reject for this call - const rateLimiter = await import("../rateLimiter"); + const rateLimiter = await import("../mcp/rateLimiter"); vi.mocked(rateLimiter.enforceRateLimit).mockRejectedValueOnce( - new Error("Rate limit exceeded"), + new Error("Rate limit exceeded") ); await toolCallHandler({ @@ -541,7 +580,7 @@ describe("TelegramMCPServer", () => { // Make the send_message tool handler throw const sendMessageApi = await import("./api/sendMessage"); vi.mocked(sendMessageApi.sendMessage).mockRejectedValueOnce( - new Error("Network error: Connection timeout"), + new Error("Network error: Connection timeout") ); await toolCallHandler({ @@ -566,11 +605,11 @@ describe("TelegramMCPServer", () => { it("should register event handlers on construction", () => { expect(mockTransportOn).toHaveBeenCalledWith( "toolCall", - expect.any(Function), + expect.any(Function) ); expect(mockTransportOn).toHaveBeenCalledWith( "listTools", - expect.any(Function), + expect.any(Function) ); }); @@ -585,7 +624,7 @@ describe("TelegramMCPServer", () => { await vi.waitFor(() => { expect(mockTransportEmit).toHaveBeenCalledWith( "toolResult", - expect.objectContaining({ requestId }), + expect.objectContaining({ requestId }) ); }); }); @@ -597,7 +636,7 @@ describe("TelegramMCPServer", () => { expect(mockTransportEmit).toHaveBeenCalledWith( "listToolsResponse", - expect.objectContaining({ requestId }), + expect.objectContaining({ requestId }) ); }); }); diff --git a/src/lib/mcp/telegram/server.ts b/src/lib/telegram/server.ts similarity index 89% rename from src/lib/mcp/telegram/server.ts rename to src/lib/telegram/server.ts index 417bc36f1..e3b874183 100644 --- a/src/lib/mcp/telegram/server.ts +++ b/src/lib/telegram/server.ts @@ -4,38 +4,38 @@ */ import type { Socket } from "socket.io-client"; -import type { TelegramState } from "../../../store/telegram/types"; +import type { TelegramState } from "../../store/telegram/types"; import type { MCPServerConfig, MCPTool, MCPToolCall, MCPToolResult, -} from "../types"; +} from "../mcp/types"; -import { store } from "../../../store"; -import { selectTelegramUserState } from "../../../store/telegramSelectors"; -import { ErrorCategory, logAndFormatError } from "../errorHandler"; -import { ValidationError } from "../validation"; -import { SocketIOMCPTransportImpl } from "../transport"; -import { mcpLog } from "../logger"; +import { store } from "../../store"; +import { selectTelegramUserState } from "../../store/telegramSelectors"; +import { ErrorCategory, logAndFormatError } from "../mcp/errorHandler"; +import { ValidationError } from "../mcp/validation"; +import { SocketIOMCPTransportImpl } from "../mcp/transport"; +import { mcpLog } from "../mcp/logger"; import { enforceRateLimit, resetRequestCallCount, isStateOnlyTool, -} from "../rateLimiter"; +} from "../mcp/rateLimiter"; import { useExtraToolDefinition, executeUseExtraTool, executeExtraToolIfExists, getAllExtraTools, isExtraToolByName, -} from "../skills"; +} from "../mcp/skills"; import { type TelegramMCPToolHandler, type TelegramMCPToolName, TELEGRAM_MCP_TOOL_NAMES, } from "./types"; -import * as tools from "./tools"; +import * as tools from "./mcp-tools"; export class TelegramMCPServer { private transport: SocketIOMCPTransportImpl; @@ -55,7 +55,7 @@ export class TelegramMCPServer { private setupHandlers(): void { this.transport.on("toolCall", (data: unknown) => { void this.handleToolCallRequest( - data as { requestId: string; toolCall: MCPToolCall }, + data as { requestId: string; toolCall: MCPToolCall } ); }); @@ -87,26 +87,24 @@ export class TelegramMCPServer { } catch (error) { const errorResult = logAndFormatError( "handleToolCall", - error instanceof Error ? error : new Error(String(error)), + error instanceof Error ? error : new Error(String(error)) ); this.transport.emit("toolResult", { requestId, result: errorResult }); } } private listTools(): MCPTool[] { - const baseTelegramTools = Object.values(tools).filter( - (t): t is MCPTool => { - return ( - t !== undefined && - typeof t === "object" && - "name" in t && - "description" in t && - "inputSchema" in t && - typeof (t as MCPTool).name === "string" && - typeof (t as MCPTool).description === "string" - ); - }, - ); + const baseTelegramTools = Object.values(tools).filter((t): t is MCPTool => { + return ( + t !== undefined && + typeof t === "object" && + "name" in t && + "description" in t && + "inputSchema" in t && + typeof (t as MCPTool).name === "string" && + typeof (t as MCPTool).description === "string" + ); + }); // Add the use_extra_tool meta-tool + all extra tool definitions const extraTools = getAllExtraTools(); @@ -182,8 +180,9 @@ export class TelegramMCPServer { }; } - const telegramState: TelegramState = - selectTelegramUserState(store.getState()); + const telegramState: TelegramState = selectTelegramUserState( + store.getState() + ); try { const result = await toolHandler(args, { @@ -201,7 +200,7 @@ export class TelegramMCPServer { } return logAndFormatError( name, - error instanceof Error ? error : new Error(String(error)), + error instanceof Error ? error : new Error(String(error)) ); } } diff --git a/src/services/telegram/entityBuilders.ts b/src/lib/telegram/services/entityBuilders.ts similarity index 96% rename from src/services/telegram/entityBuilders.ts rename to src/lib/telegram/services/entityBuilders.ts index f0700dbb2..e55b95334 100644 --- a/src/services/telegram/entityBuilders.ts +++ b/src/lib/telegram/services/entityBuilders.ts @@ -6,7 +6,7 @@ import type { TelegramChat, TelegramMessage, TelegramUser, -} from "../../store/telegram/types"; +} from "../../../store/telegram/types"; // --------------------------------------------------------------------------- // Peer ID helpers @@ -57,7 +57,7 @@ export function buildChat( dialog: any, // eslint-disable-next-line @typescript-eslint/no-explicit-any entity: any, - lastMsg?: TelegramMessage, + lastMsg?: TelegramMessage ): TelegramChat { const id = buildPeerId(dialog.peer ?? entity); const type = getChatType(entity); @@ -73,7 +73,8 @@ export function buildChat( if (type === "private") { const firstName: string = entity?.firstName ?? ""; const lastName: string = entity?.lastName ?? ""; - chat.title = [firstName, lastName].filter(Boolean).join(" ") || `User ${id}`; + chat.title = + [firstName, lastName].filter(Boolean).join(" ") || `User ${id}`; } else { chat.title = entity?.title ?? `Chat ${id}`; } @@ -118,7 +119,10 @@ export function buildChat( * Compatible with both Api.Message and the raw objects from GetDialogs/GetHistory. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any -export function buildMessage(msg: any, fallbackChatId?: string): TelegramMessage | null { +export function buildMessage( + msg: any, + fallbackChatId?: string +): TelegramMessage | null { if (!msg || typeof msg !== "object") return null; const id = msg.id; @@ -157,7 +161,8 @@ export function buildMessage(msg: any, fallbackChatId?: string): TelegramMessage // Media if (msg.media && typeof msg.media === "object") { - const className = (msg.media.constructor as { className?: string })?.className; + const className = (msg.media.constructor as { className?: string }) + ?.className; telegramMsg.media = { type: className ?? "unknown" }; } diff --git a/src/services/telegram/index.ts b/src/lib/telegram/services/index.ts similarity index 100% rename from src/services/telegram/index.ts rename to src/lib/telegram/services/index.ts diff --git a/src/services/telegram/schedulers.ts b/src/lib/telegram/services/schedulers.ts similarity index 100% rename from src/services/telegram/schedulers.ts rename to src/lib/telegram/services/schedulers.ts diff --git a/src/services/telegram/syncService.ts b/src/lib/telegram/services/syncService.ts similarity index 95% rename from src/services/telegram/syncService.ts rename to src/lib/telegram/services/syncService.ts index 47933127c..63e35cbb1 100644 --- a/src/services/telegram/syncService.ts +++ b/src/lib/telegram/services/syncService.ts @@ -10,9 +10,9 @@ import { Api } from "telegram/tl"; import { Raw } from "telegram/events"; import bigInt from "big-integer"; -import { mtprotoService } from "../mtprotoService"; -import { updateManager } from "../updateManager"; -import { store } from "../../store"; +import { mtprotoService } from "../../../services/mtprotoService"; +import { updateManager } from "../../../services/updateManager"; +import { store } from "../../../store"; import { setSyncStatus, replaceChats, @@ -22,8 +22,8 @@ import { addChatMessagesById, setCommonBoxState, setChannelPts, -} from "../../store/telegram"; -import type { TelegramChat, TelegramUser } from "../../store/telegram/types"; +} from "../../../store/telegram"; +import type { TelegramChat, TelegramUser } from "../../../store/telegram/types"; import { buildChat, buildMessage, @@ -96,7 +96,7 @@ class TelegramSyncService { if (this.isSyncing) { console.warn( LOG_PREFIX, - "Safety timeout reached — releasing sync lock", + "Safety timeout reached — releasing sync lock" ); this.isSyncing = false; store.dispatch(setSyncStatus({ userId, isSyncing: false })); @@ -118,16 +118,16 @@ class TelegramSyncService { this.isSynced = true; clearTimeout(this.safetyTimeout); store.dispatch( - setSyncStatus({ userId, isSyncing: false, isSynced: true }), + setSyncStatus({ userId, isSyncing: false, isSynced: true }) ); console.log(LOG_PREFIX, "Initial sync complete — UI ready"); // Background tasks (non-blocking) this.loadAllChats("archived").catch((e) => - console.warn(LOG_PREFIX, "Archived chat load failed:", e), + console.warn(LOG_PREFIX, "Archived chat load failed:", e) ); this.preloadTopChatMessages().catch((e) => - console.warn(LOG_PREFIX, "Top chat preload failed:", e), + console.warn(LOG_PREFIX, "Top chat preload failed:", e) ); }); } catch (error) { @@ -173,7 +173,7 @@ class TelegramSyncService { // Fetch current update state from Telegram const state = await mtprotoService.invoke( - new Api.updates.GetState(), + new Api.updates.GetState() ); const commonBoxState = { @@ -202,7 +202,7 @@ class TelegramSyncService { console.log( LOG_PREFIX, - "Update manager initialized, event handler registered", + "Update manager initialized, event handler registered" ); } @@ -219,7 +219,7 @@ class TelegramSyncService { */ private async loadAllChats( listType: "active" | "archived", - whenFirstBatchDone?: () => Promise, + whenFirstBatchDone?: () => Promise ): Promise { const userId = this.userId!; const isArchived = listType === "archived"; @@ -236,7 +236,7 @@ class TelegramSyncService { if (!isArchived) { try { const pinned = await mtprotoService.invoke( - new Api.messages.GetPinnedDialogs({ folderId: 0 }), + new Api.messages.GetPinnedDialogs({ folderId: 0 }) ); if (pinned?.dialogs?.length) { this.processDialogsResult(pinned, userId, true); @@ -257,7 +257,7 @@ class TelegramSyncService { limit: CHAT_LIST_LOAD_SLICE, folderId: isArchived ? 1 : 0, hash: bigInt(0), - }), + }) ); // Handle different response types @@ -266,7 +266,7 @@ class TelegramSyncService { if (dialogs.length === 0) { console.log( LOG_PREFIX, - `${listType} chats fully loaded (${iterations} batches)`, + `${listType} chats fully loaded (${iterations} batches)` ); break; } @@ -291,7 +291,7 @@ class TelegramSyncService { if (dialogs.length < CHAT_LIST_LOAD_SLICE) { console.log( LOG_PREFIX, - `${listType} chats fully loaded (last batch < slice)`, + `${listType} chats fully loaded (last batch < slice)` ); break; } @@ -351,7 +351,7 @@ class TelegramSyncService { // eslint-disable-next-line @typescript-eslint/no-explicit-any result: any, userId: string, - isFirstBatch: boolean, + isFirstBatch: boolean ): string[] { // eslint-disable-next-line @typescript-eslint/no-explicit-any const dialogs: any[] = result.dialogs ?? []; @@ -447,7 +447,7 @@ class TelegramSyncService { try { console.log( LOG_PREFIX, - `Loading ${slice} messages for chat ${selectedChatId}`, + `Loading ${slice} messages for chat ${selectedChatId}` ); const result = await mtprotoService.invoke( @@ -456,7 +456,7 @@ class TelegramSyncService { offsetId: 0, addOffset: 0, limit: slice, - }), + }) ); // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -467,19 +467,19 @@ class TelegramSyncService { if (messages.length > 0) { store.dispatch( - addChatMessagesById({ userId, chatId: selectedChatId, messages }), + addChatMessagesById({ userId, chatId: selectedChatId, messages }) ); } console.log( LOG_PREFIX, - `Loaded ${messages.length} messages for chat ${selectedChatId}`, + `Loaded ${messages.length} messages for chat ${selectedChatId}` ); } catch (error) { console.warn( LOG_PREFIX, `Failed to load messages for chat ${selectedChatId}:`, - error, + error ); } } @@ -523,7 +523,7 @@ class TelegramSyncService { offsetId: 0, addOffset: 0, limit: slice, - }), + }) ); // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -541,7 +541,7 @@ class TelegramSyncService { console.warn( LOG_PREFIX, `Failed to preload messages for chat ${chatId}:`, - error, + error ); // Continue with next chat } diff --git a/src/services/telegram/updateHandler.ts b/src/lib/telegram/services/updateHandler.ts similarity index 95% rename from src/services/telegram/updateHandler.ts rename to src/lib/telegram/services/updateHandler.ts index 21adc5ec9..85c945b83 100644 --- a/src/services/telegram/updateHandler.ts +++ b/src/lib/telegram/services/updateHandler.ts @@ -8,13 +8,13 @@ */ import { Api } from "telegram/tl"; -import { store } from "../../store"; +import { store } from "../../../store"; import { addMessage, updateMessage, deleteChatMessages, updateChat, -} from "../../store/telegram"; +} from "../../../store/telegram"; import { buildMessage, buildPeerId } from "./entityBuilders"; const LOG_PREFIX = "[TelegramSync]"; @@ -27,7 +27,7 @@ export function handleUpdate( // eslint-disable-next-line @typescript-eslint/no-explicit-any update: any, userId: string, - _source: "realtime" | "difference" = "realtime", + _source: "realtime" | "difference" = "realtime" ): void { const dispatch = store.dispatch; @@ -38,7 +38,7 @@ export function handleUpdate( console.log( LOG_PREFIX, "Force sync requested", - update.channelId ? `for channel ${update.channelId}` : "(full)", + update.channelId ? `for channel ${update.channelId}` : "(full)" ); return; } @@ -61,7 +61,7 @@ export function handleUpdate( lastMessage: msg, lastMessageDate: msg.date, }, - }), + }) ); } return; @@ -82,7 +82,7 @@ export function handleUpdate( chatId: msg.chatId, messageId: msg.id, updates: msg, - }), + }) ); } return; @@ -102,7 +102,9 @@ export function handleUpdate( const chatMsgs = userState.messages[chatId]; const matching = messageIds.filter((id) => chatMsgs[id]); if (matching.length > 0) { - dispatch(deleteChatMessages({ userId, chatId, messageIds: matching })); + dispatch( + deleteChatMessages({ userId, chatId, messageIds: matching }) + ); } } } @@ -127,7 +129,7 @@ export function handleUpdate( userId, id: chatId, updates: { unreadCount: update.stillUnreadCount }, - }), + }) ); } return; @@ -146,7 +148,7 @@ export function handleUpdate( userId, id: chatId, updates: { unreadCount: update.stillUnreadCount }, - }), + }) ); return; } @@ -182,7 +184,7 @@ export function handleUpdate( lastMessage: msg, lastMessageDate: msg.date, }, - }), + }) ); } return; diff --git a/src/lib/mcp/telegram/state/chatState.ts b/src/lib/telegram/state/chatState.ts similarity index 93% rename from src/lib/mcp/telegram/state/chatState.ts rename to src/lib/telegram/state/chatState.ts index 61c969be2..28cccdd64 100644 --- a/src/lib/mcp/telegram/state/chatState.ts +++ b/src/lib/telegram/state/chatState.ts @@ -5,9 +5,9 @@ * to keep the Redux store in sync. */ -import { store } from "../../../../store"; -import { addChats, addChat } from "../../../../store/telegram"; -import type { TelegramChat } from "../../../../store/telegram/types"; +import { store } from "../../../store"; +import { addChats, addChat } from "../../../store/telegram"; +import type { TelegramChat } from "../../../store/telegram/types"; import { getCurrentUserId } from "./helpers"; /** @@ -82,7 +82,7 @@ export function updateChatsFromResults( name: string; type: string; username?: string; - }>, + }> ): void { const userId = getCurrentUserId(); if (!userId || results.length === 0) return; diff --git a/src/lib/mcp/telegram/state/helpers.ts b/src/lib/telegram/state/helpers.ts similarity index 87% rename from src/lib/mcp/telegram/state/helpers.ts rename to src/lib/telegram/state/helpers.ts index b7cf80044..0c763fa15 100644 --- a/src/lib/mcp/telegram/state/helpers.ts +++ b/src/lib/telegram/state/helpers.ts @@ -2,7 +2,7 @@ * Shared helpers for the Telegram state update layer. */ -import { store } from "../../../../store"; +import { store } from "../../../store"; /** * Get the current app user ID from Redux (used as the key in telegram.byUser). diff --git a/src/lib/mcp/telegram/state/index.ts b/src/lib/telegram/state/index.ts similarity index 100% rename from src/lib/mcp/telegram/state/index.ts rename to src/lib/telegram/state/index.ts diff --git a/src/lib/mcp/telegram/state/messageState.ts b/src/lib/telegram/state/messageState.ts similarity index 73% rename from src/lib/mcp/telegram/state/messageState.ts rename to src/lib/telegram/state/messageState.ts index 92b14756a..2af8fb6fa 100644 --- a/src/lib/mcp/telegram/state/messageState.ts +++ b/src/lib/telegram/state/messageState.ts @@ -5,12 +5,9 @@ * to keep the Redux store in sync. */ -import { store } from "../../../../store"; -import { - addChatMessagesById, - updateMessage, -} from "../../../../store/telegram"; -import type { TelegramMessage } from "../../../../store/telegram/types"; +import { store } from "../../../store"; +import { addChatMessagesById, updateMessage } from "../../../store/telegram"; +import type { TelegramMessage } from "../../../store/telegram/types"; import { getCurrentUserId } from "./helpers"; /** @@ -18,7 +15,7 @@ import { getCurrentUserId } from "./helpers"; */ export function updateMessagesInState( chatId: string, - messages: TelegramMessage[], + messages: TelegramMessage[] ): void { const userId = getCurrentUserId(); if (!userId || messages.length === 0) return; @@ -31,11 +28,11 @@ export function updateMessagesInState( export function updateMessageReactionsInState( chatId: string, messageId: string, - reactions: Array<{ emoticon: string; count: number }>, + reactions: Array<{ emoticon: string; count: number }> ): void { const userId = getCurrentUserId(); if (!userId) return; store.dispatch( - updateMessage({ userId, chatId, messageId, updates: { reactions } }), + updateMessage({ userId, chatId, messageId, updates: { reactions } }) ); } diff --git a/src/lib/mcp/telegram/state/userState.ts b/src/lib/telegram/state/userState.ts similarity index 88% rename from src/lib/mcp/telegram/state/userState.ts rename to src/lib/telegram/state/userState.ts index 9a6ea8176..16351c8b1 100644 --- a/src/lib/mcp/telegram/state/userState.ts +++ b/src/lib/telegram/state/userState.ts @@ -5,9 +5,9 @@ * to keep the Redux store in sync. */ -import { store } from "../../../../store"; -import { setCurrentUser, addUsers } from "../../../../store/telegram"; -import type { TelegramUser } from "../../../../store/telegram/types"; +import { store } from "../../../store"; +import { setCurrentUser, addUsers } from "../../../store/telegram"; +import type { TelegramUser } from "../../../store/telegram/types"; import type { ApiUser } from "../api/apiResultTypes"; import { getCurrentUserId } from "./helpers"; diff --git a/src/lib/mcp/telegram/toolActionParser.ts b/src/lib/telegram/toolActionParser.ts similarity index 100% rename from src/lib/mcp/telegram/toolActionParser.ts rename to src/lib/telegram/toolActionParser.ts diff --git a/src/lib/mcp/telegram/types.ts b/src/lib/telegram/types.ts similarity index 90% rename from src/lib/mcp/telegram/types.ts rename to src/lib/telegram/types.ts index 1e164e474..e0b2fc45c 100644 --- a/src/lib/mcp/telegram/types.ts +++ b/src/lib/telegram/types.ts @@ -2,9 +2,9 @@ * Telegram MCP server types */ -import type { SocketIOMCPTransportImpl } from "../transport"; -import type { MCPToolResult } from "../types"; -import type { TelegramState } from "../../../store/telegram/types"; +import type { SocketIOMCPTransportImpl } from "../mcp/transport"; +import type { MCPToolResult } from "../mcp/types"; +import type { TelegramState } from "../../store/telegram/types"; export interface TelegramMCPContext { telegramState: TelegramState; @@ -13,7 +13,7 @@ export interface TelegramMCPContext { export type TelegramMCPToolHandler = ( args: Record, - context: TelegramMCPContext, + context: TelegramMCPContext ) => Promise; export const TELEGRAM_MCP_TOOL_NAMES = [ diff --git a/src/providers/SocketProvider.tsx b/src/providers/SocketProvider.tsx index 5884e0c9e..210ae3350 100644 --- a/src/providers/SocketProvider.tsx +++ b/src/providers/SocketProvider.tsx @@ -8,7 +8,7 @@ import { getTelegramMCPServer, updateTelegramMCPServerSocket, cleanupTelegramMCPServer, -} from "../lib/mcp/telegram"; +} from "../lib/telegram"; import { isTauri, setupTauriSocketListeners, diff --git a/src/providers/TelegramProvider.tsx b/src/providers/TelegramProvider.tsx index 5be0dacca..a98f620a5 100644 --- a/src/providers/TelegramProvider.tsx +++ b/src/providers/TelegramProvider.tsx @@ -16,7 +16,7 @@ import { } from "../store/telegramSelectors"; import { initializeTelegram, connectTelegram } from "../store/telegram"; import { mtprotoService } from "../services/mtprotoService"; -import { telegramSyncService } from "../services/telegram"; +import { telegramSyncService } from "../lib/telegram/services"; interface TelegramContextType { isAuthenticated: boolean; diff --git a/yarn.lock b/yarn.lock index 6abcf1403..f7c579f9a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -681,6 +681,13 @@ "@types/deep-eql" "*" assertion-error "^2.0.1" +"@types/debug@^4.1.12": + version "4.1.12" + resolved "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz" + integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== + dependencies: + "@types/ms" "*" + "@types/deep-eql@*": version "4.0.2" resolved "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz" @@ -696,6 +703,11 @@ resolved "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz" integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== +"@types/ms@*": + version "2.1.0" + resolved "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz" + integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== + "@types/node@^20.0.0 || ^22.0.0 || >=24.0.0", "@types/node@^20.19.0 || >=22.12.0", "@types/node@^25.0.10": version "25.0.10" resolved "https://registry.npmjs.org/@types/node/-/node-25.0.10.tgz" @@ -1246,7 +1258,7 @@ debug@^2.2.0: dependencies: ms "2.0.0" -debug@^4.1.0, debug@^4.3.1, debug@~4.4.1: +debug@^4.1.0, debug@^4.3.1, debug@^4.4.3, debug@~4.4.1: version "4.4.3" resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz" integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==