From 51f7d05a82f1c58a06774ffef4e0e6436271430d Mon Sep 17 00:00:00 2001 From: naseif Date: Mon, 14 Mar 2022 00:28:58 +0000 Subject: [PATCH 1/4] exp(API): Added new events for tests --- src/structure/TelegramAPI.ts | 26 +++++++++++++++++++++++--- src/structure/types.ts | 11 +++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/structure/TelegramAPI.ts b/src/structure/TelegramAPI.ts index 1cf205e..24f6dad 100644 --- a/src/structure/TelegramAPI.ts +++ b/src/structure/TelegramAPI.ts @@ -256,9 +256,29 @@ export class TelegramAPI { let chatJoinReq = update.chat_join_request; if (message) { - this.emitter.emit("message", message); - if (this.onMessageCallback !== undefined) { - this.onMessageCallback(message); + if (message.audio) { + this.emitter.emit("audio", message.audio); + return; + } else if (message.video) { + this.emitter.emit("video", message.video); + return; + } else if (message.photo) { + this.emitter.emit("photo", message.photo); + return; + } else if (message.document) { + this.emitter.emit("document", message.document); + return; + } else if (message.new_chat_members) { + this.emitter.emit("new_chat_members", message.new_chat_members); + return; + } else if (message.left_chat_member) { + this.emitter.emit("left_chat_member", message.left_chat_member); + return; + } else { + this.emitter.emit("message", message); + if (this.onMessageCallback !== undefined) { + this.onMessageCallback(message); + } } } else if (editedMessage) { this.emitter.emit("edited_message", editedMessage); diff --git a/src/structure/types.ts b/src/structure/types.ts index d760069..ba5354b 100644 --- a/src/structure/types.ts +++ b/src/structure/types.ts @@ -8,6 +8,11 @@ import { IChosenInlineResult, ICallbackQuery, IChatJoinRequest, + IAudio, + IDocument, + IPhotoSize, + IUser, + IVideo, } from "../types"; export type TMessageCallback = (message: IMessage) => void; @@ -60,6 +65,12 @@ export interface IMessageId { export interface TelegramEvents { message: [message: IMessage]; + audio: [audio: IAudio]; + video: [video: IVideo] + photo: [photo: IPhotoSize[]] + document: [document: IDocument] + new_chat_members: [member: IUser[]] + left_chat_member: [member: IUser] edited_message: [message: IMessage]; edited_channel_post: [message: IMessage]; channel_post: [message: IMessage]; From 91c7c89720f451131b50577fb318e949f10aa246 Mon Sep 17 00:00:00 2001 From: naseif Date: Tue, 15 Mar 2022 21:53:30 +0100 Subject: [PATCH 2/4] feat(API): implemented type checking and error handling for the API methods --- src/helpers/ErrorsController.ts | 29 ++ src/structure/TelegramAPI.ts | 459 ++++++++++++++++++++++++-------- 2 files changed, 384 insertions(+), 104 deletions(-) create mode 100644 src/helpers/ErrorsController.ts diff --git a/src/helpers/ErrorsController.ts b/src/helpers/ErrorsController.ts new file mode 100644 index 0000000..9855ccd --- /dev/null +++ b/src/helpers/ErrorsController.ts @@ -0,0 +1,29 @@ +export enum Errors { + CLASS_INITIALIZATION_ERROR = "InitializationError", + INVALID_TYPE = "Invalid Type", + MISSING_PARAMS = "Missing Parameters", +} + +export class ErrosController extends Error { + /** + * The error message + */ + + message: string; + + /** + * the error code for this error message + */ + + errorCode: Errors; + + constructor( + message: string, + code: Errors = Errors.CLASS_INITIALIZATION_ERROR + ) { + super(); + this.message = `${code} - ${message}`; + this.errorCode = code; + Error.captureStackTrace(this); + } +} diff --git a/src/structure/TelegramAPI.ts b/src/structure/TelegramAPI.ts index 24f6dad..61da3c8 100644 --- a/src/structure/TelegramAPI.ts +++ b/src/structure/TelegramAPI.ts @@ -2,7 +2,20 @@ import EventEmitter from "eventemitter3"; import needle, { NeedleHttpVerbs, NeedleOptions } from "needle"; import mime from "mime-types"; import { URLSearchParams } from "node:url"; -import { IBotCommandScopeBase, IBotCommandScopeChat, IBotCommandScopeChatAdministrators, IBotCommandScopeChatMember, IChat, IChatInviteLink, IChatMember, IChatPermissions, IMessage, IUpdate, IUpdateOptions, IUser } from "../types"; +import { + IBotCommandScopeBase, + IBotCommandScopeChat, + IBotCommandScopeChatAdministrators, + IBotCommandScopeChatMember, + IChat, + IChatInviteLink, + IChatMember, + IChatPermissions, + IMessage, + IUpdate, + IUpdateOptions, + IUser, +} from "../types"; import { sendMessageOptions, sendPollOptions, @@ -58,6 +71,7 @@ import { IInputMediaVideo, IUserProfilePhotos, } from "../types"; +import { Errors, ErrosController } from "../helpers/ErrorsController"; export class TelegramAPI { /** @@ -132,7 +146,11 @@ export class TelegramAPI { constructor(token: string) { this._token = token; - if (!token) throw new Error("Invalid token"); + if (!token) + throw new ErrosController( + "You must provide an API token", + Errors.CLASS_INITIALIZATION_ERROR + ); this.endpoint = `https://api.telegram.org/bot${this._token}/`; this.emitter = new EventEmitter(); } @@ -152,17 +170,15 @@ export class TelegramAPI { data: {}, options?: NeedleOptions ) { - try { - const req = await needle(apiMethod, url, data, options); - const res = await req.body; - return res; - } catch (error) { - this.emitter.emit("error", error); + const req = await needle(apiMethod, url, data, options); + const res = await req.body; + + if (!res.ok) { + this.emitter.emit("error", res); + return; } - // if (!res?.ok) { - // throw new Error(`API CALL FAILED: ${res.description}`); - // } + return res; } /** @@ -416,6 +432,18 @@ export class TelegramAPI { text: string, options?: sendMessageOptions ): Promise { + if (typeof chatId !== "string" && typeof chatId !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chatId}`, + Errors.INVALID_TYPE + ); + + if (!chatId || !text) + throw new ErrosController( + "The parameters 'chatId' and 'text' are required", + Errors.MISSING_PARAMS + ); + let params = { chat_id: chatId, text: text, @@ -453,6 +481,24 @@ export class TelegramAPI { answer_options: string[], options?: sendPollOptions ): Promise { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + + if (!chat_id || !question || !answer_options) + throw new ErrosController( + "The parameters 'chat_id', 'question' and 'answer_options' are required", + Errors.MISSING_PARAMS + ); + + if (typeof answer_options !== "object") + throw new ErrosController( + "The parameter 'answer_options' must be an array of strings!", + Errors.INVALID_TYPE + ); + let params = { chat_id: chat_id, question: question, @@ -487,6 +533,18 @@ export class TelegramAPI { message_id: number, options?: forwardMessageOptions ): Promise { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + + if (!chat_id || !from_chat_id || !message_id) + throw new ErrosController( + "The parameters 'chat_id', 'from_chat_id' and 'message_id' are required", + Errors.MISSING_PARAMS + ); + let params = { chat_id: chat_id, from_chat_id: from_chat_id, @@ -522,6 +580,18 @@ export class TelegramAPI { message_id: number, options?: copyMessageOptions ): Promise { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + + if (!chat_id || !from_chat_id || !message_id) + throw new ErrosController( + "The parameters 'chat_id', 'from_chat_id' and 'message_id' are required", + Errors.MISSING_PARAMS + ); + let params = { chat_id: chat_id, from_chat_id: from_chat_id, @@ -560,6 +630,24 @@ export class TelegramAPI { photo: string | LocalFile, options?: sendPhotoOptions ): Promise { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + + if (typeof photo !== "string" && typeof photo !== "object") + throw new ErrosController( + "A photo can either be an HTTP URL or an object e.g: {file:'local path to photo'}", + Errors.INVALID_TYPE + ); + + if (!chat_id || !photo) + throw new ErrosController( + "The parameters 'chat_id' and 'photo' are required", + Errors.MISSING_PARAMS + ); + let params = {}; if (typeof photo !== "string" && photo.file) { @@ -615,6 +703,24 @@ export class TelegramAPI { audio: string | LocalFile, options?: sendAudioOptions ): Promise { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + + if (typeof audio !== "string" && typeof audio !== "object") + throw new ErrosController( + "An audio can either be an HTTP URL or an object e.g: {file:'local path to audio'}", + Errors.INVALID_TYPE + ); + + if (!chat_id || !audio) + throw new ErrosController( + "The parameters 'chat_id' and 'audio' are required", + Errors.MISSING_PARAMS + ); + let params = {}; if (typeof audio !== "string" && audio.file) { @@ -670,6 +776,24 @@ export class TelegramAPI { video: string | LocalFile, options?: sendVideoOptions ): Promise { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + + if (typeof video !== "string" && typeof video !== "object") + throw new ErrosController( + "A video can either be an HTTP URL or an object e.g: {file:'local path to video'}", + Errors.INVALID_TYPE + ); + + if (!chat_id || !video) + throw new ErrosController( + "The parameters 'chat_id' and 'video' are required", + Errors.MISSING_PARAMS + ); + let params = {}; if (typeof video !== "string" && video.file) { @@ -726,6 +850,23 @@ export class TelegramAPI { document: string | LocalFile, options?: sendDocumentOptions ): Promise { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + + if (typeof document !== "string" && typeof document !== "object") + throw new ErrosController( + "A document can either be an HTTP URL or an object e.g: {file:'local path to document'}", + Errors.INVALID_TYPE + ); + + if (!chat_id || !document) + throw new ErrosController( + "The parameters 'chat_id' and 'document' are required", + Errors.MISSING_PARAMS + ); let params = {}; if (typeof document !== "string" && document.file) { @@ -782,6 +923,23 @@ export class TelegramAPI { animation: string | LocalFile, options?: sendAnimationOptions ): Promise { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + + if (typeof animation !== "string" && typeof animation !== "object") + throw new ErrosController( + "An animation can either be an HTTP URL or an object e.g: {file:'local path to animation'}", + Errors.INVALID_TYPE + ); + + if (!chat_id || !animation) + throw new ErrosController( + "The parameters 'chat_id' and 'animation' are required", + Errors.MISSING_PARAMS + ); let params = {}; if (typeof animation !== "string" && animation.file) { @@ -838,6 +996,24 @@ export class TelegramAPI { voice: string | LocalFile, options?: sendVoiceOptions ): Promise { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + + if (typeof voice !== "string" && typeof voice !== "object") + throw new ErrosController( + "A voice can either be an HTTP URL or an object e.g: {file:'local path to voice'}", + Errors.INVALID_TYPE + ); + + if (!chat_id || !voice) + throw new ErrosController( + "The parameters 'chat_id' and 'voice' are required", + Errors.MISSING_PARAMS + ); + let params = {}; if (typeof voice !== "string" && voice.file) { @@ -891,6 +1067,23 @@ export class TelegramAPI { videoNote: string | LocalFile, options?: sendVideoNoteOptions ): Promise { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + + if (typeof videoNote !== "string" && typeof videoNote !== "object") + throw new ErrosController( + "A video note can either be an HTTP URL or an object e.g: {file:'local path to the video note'}", + Errors.INVALID_TYPE + ); + + if (!chat_id || !videoNote) + throw new ErrosController( + "The parameters 'chat_id' and 'videoNote' are required", + Errors.MISSING_PARAMS + ); let params = {}; if (typeof videoNote !== "string" && videoNote.file) { @@ -993,6 +1186,18 @@ export class TelegramAPI { longitude: number, options?: sendLocationOptions ): Promise { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + + if (!chat_id || !latitude || !longitude) + throw new ErrosController( + "The parameters 'chat_id', 'longitude' and 'latitude' are required", + Errors.MISSING_PARAMS + ); + let params = { chat_id: chat_id, latitude: latitude, @@ -1020,6 +1225,12 @@ export class TelegramAPI { longitude: number, options?: editMessageLiveLocationOptions ): Promise { + if (!latitude || !longitude) + throw new ErrosController( + "The parameters 'longitude' and 'latitude' are required", + Errors.MISSING_PARAMS + ); + let params = { latitude: latitude, longitude: longitude, @@ -1083,6 +1294,18 @@ export class TelegramAPI { address: string, options?: sendVenueOptions ): Promise { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + + if (!chat_id || !latitude || !longitude || title || address) + throw new ErrosController( + "The parameters 'chat_id', 'longitude', 'latitude', 'title' amd 'address' are required", + Errors.MISSING_PARAMS + ); + let params = { chat_id: chat_id, latitude: latitude, @@ -1118,6 +1341,17 @@ export class TelegramAPI { first_name: string, options?: sendContactOptions ): Promise { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + + if (!chat_id || !phone_number || !first_name) + throw new ErrosController( + "The parameters 'chat_id', 'phone_number' and 'first_name' are required", + Errors.MISSING_PARAMS + ); let params = { chat_id: chat_id, phone_number: phone_number, @@ -1143,6 +1377,12 @@ export class TelegramAPI { chat_id: string | number, options?: sendDiceOptions ): Promise { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + let params = { chat_id: chat_id, ...options, @@ -1163,6 +1403,18 @@ export class TelegramAPI { */ async sendChatAction(chat_id: number | string, action: ActionType) { + if (typeof chat_id !== "string" && typeof chat_id !== "number") + throw new ErrosController( + `chat id must be a string or a number, received: ${typeof chat_id}`, + Errors.INVALID_TYPE + ); + + if (!chat_id || !action) + throw new ErrosController( + "The parameters 'chat_id' and 'action' are required", + Errors.MISSING_PARAMS + ); + let params = { chat_id: chat_id, action: action, @@ -1186,6 +1438,12 @@ export class TelegramAPI { user_id: number, options?: getUserProfilePhotosOptions ): Promise { + if (typeof user_id !== "number") + throw new ErrosController( + `user_id must be a number!, recieved: ${typeof user_id}`, + Errors.INVALID_TYPE + ); + let params = { user_id: user_id, ...options, @@ -1230,6 +1488,12 @@ export class TelegramAPI { commands: IBotCommand[], options?: setMyCommandsOptions ): Promise { + if (!commands || typeof commands !== "object") + throw new ErrosController( + `The commands parameter must be an Array of IBotCommand!, recieved ${typeof commands}`, + Errors.INVALID_TYPE + ); + let params = {}; if (options && options.scope) { @@ -1297,22 +1561,27 @@ export class TelegramAPI { * @returns IBotCommand[] */ - async getMyCommands(scope: IBotCommandScopeBase - | IBotCommandScopeChat - | IBotCommandScopeChatAdministrators - | IBotCommandScopeChatMember, language_code?: string + async getMyCommands( + scope: + | IBotCommandScopeBase + | IBotCommandScopeChat + | IBotCommandScopeChatAdministrators + | IBotCommandScopeChatMember, + language_code?: string ) { + if (!scope || typeof scope !== "object") + throw new ErrosController( + "The scope parameter is required and is from type object!, recieved " + + typeof scope, + Errors.INVALID_TYPE + ); let params = { scope: JSON.stringify(scope), language_code: language_code, }; const send: IBotCommand[] = await ( - await this.sendRequest( - "post", - this.endpoint + "getMyCommands", - params - ) + await this.sendRequest("post", this.endpoint + "getMyCommands", params) ).result; return send; @@ -1521,7 +1790,10 @@ export class TelegramAPI { * @returns boolean */ - async setChatPermissions(chat_id: number | string, permissions: IChatPermissions) { + async setChatPermissions( + chat_id: number | string, + permissions: IChatPermissions + ) { let params = { chat_id: chat_id, permissions: JSON.stringify(permissions), @@ -1540,7 +1812,7 @@ export class TelegramAPI { /** * Use this method to generate a new primary invite link for a chat; any previously generated primary link is revoked. The bot must be an administrator in the chat for this to work and must have the appropriate administrator rights. Returns the new invite link as String on success. - * @param chat_id + * @param chat_id * @returns boolean */ @@ -1560,7 +1832,6 @@ export class TelegramAPI { return send; } - /** * Use this method to create an additional invite link for a chat. The bot must be an administrator in the chat for this to work and must have the appropriate administrator rights. The link can be revoked using the method revokeChatInviteLink. Returns the new invite link as ChatInviteLink object. * @param chat_id Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -1568,10 +1839,13 @@ export class TelegramAPI { * @returns IChatInviteLink */ - async createChatInviteLink(chat_id: string | number, options?: createChatInviteLinkOptions) { + async createChatInviteLink( + chat_id: string | number, + options?: createChatInviteLinkOptions + ) { let params = { chat_id: chat_id, - ...options + ...options, }; const send: IChatInviteLink = await ( @@ -1593,11 +1867,15 @@ export class TelegramAPI { * @returns IChatInviteLink */ - async editChatInviteLink(chat_id: number | string, invite_link: string, options?: editChatInviteLinkOptions) { + async editChatInviteLink( + chat_id: number | string, + invite_link: string, + options?: editChatInviteLinkOptions + ) { let params = { chat_id: chat_id, invite_link: invite_link, - ...options + ...options, }; const send: IChatInviteLink = await ( @@ -1683,7 +1961,6 @@ export class TelegramAPI { return send; } - /** * Use this method to set a new profile photo for the chat. Photos can't be changed for private chats. The bot must be an administrator in the chat for this to work and must have the appropriate administrator rights. Returns True on success. * @param chat_id Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -1694,15 +1971,11 @@ export class TelegramAPI { async setChatPhoto(chat_id: string | number, photo: LocalFile) { let params = { chat_id: chat_id, - photo: photo - } + photo: photo, + }; const send: boolean = await ( - await this.sendRequest( - "post", - this.endpoint + "setChatPhoto", - params - ) + await this.sendRequest("post", this.endpoint + "setChatPhoto", params) ).result; return send; @@ -1717,14 +1990,10 @@ export class TelegramAPI { async deleteChatPhoto(chat_id: string | number) { let params = { chat_id: chat_id, - } + }; const send: boolean = await ( - await this.sendRequest( - "post", - this.endpoint + "deleteChatPhoto", - params - ) + await this.sendRequest("post", this.endpoint + "deleteChatPhoto", params) ).result; return send; @@ -1740,21 +2009,16 @@ export class TelegramAPI { async setChatTitle(chat_id: string | number, title: string) { let params = { chat_id: chat_id, - title: title - } + title: title, + }; const send: boolean = await ( - await this.sendRequest( - "post", - this.endpoint + "setChatTitle", - params - ) + await this.sendRequest("post", this.endpoint + "setChatTitle", params) ).result; return send; } - /** * Use this method to change the description of a group, a supergroup or a channel. The bot must be an administrator in the chat for this to work and must have the appropriate administrator rights. Returns True on success. * @param chat_id Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -1765,8 +2029,8 @@ export class TelegramAPI { async setChatDescription(chat_id: string | number, description?: string) { let params = { chat_id: chat_id, - description: description - } + description: description, + }; const send: boolean = await ( await this.sendRequest( @@ -1787,25 +2051,24 @@ export class TelegramAPI { * @returns boolean */ - async pinChatMessage(chat_id: string | number, message_id: number, disable_notification?: boolean) { + async pinChatMessage( + chat_id: string | number, + message_id: number, + disable_notification?: boolean + ) { let params = { chat_id: chat_id, message_id: message_id, - disable_notification: disable_notification - } + disable_notification: disable_notification, + }; const send: boolean = await ( - await this.sendRequest( - "post", - this.endpoint + "pinChatMessage", - params - ) + await this.sendRequest("post", this.endpoint + "pinChatMessage", params) ).result; return send; } - /** * Use this method to remove a message from the list of pinned messages in a chat. If the chat is not a private chat, the bot must be an administrator in the chat for this to work and must have the 'can_pin_messages' administrator right in a supergroup or 'can_edit_messages' administrator right in a channel. Returns True on success. * @param chat_id Unique identifier for the target chat or username of the target channel (in the format @channelusername) @@ -1817,14 +2080,10 @@ export class TelegramAPI { let params = { chat_id: chat_id, message_id: message_id, - } + }; const send: boolean = await ( - await this.sendRequest( - "post", - this.endpoint + "unpinChatMessage", - params - ) + await this.sendRequest("post", this.endpoint + "unpinChatMessage", params) ).result; return send; @@ -1839,7 +2098,7 @@ export class TelegramAPI { async unpinAllChatMessages(chat_id: string | number) { let params = { chat_id: chat_id, - } + }; const send: boolean = await ( await this.sendRequest( @@ -1861,14 +2120,10 @@ export class TelegramAPI { async leaveChat(chat_id: string | number) { let params = { chat_id: chat_id, - } + }; const send: boolean = await ( - await this.sendRequest( - "post", - this.endpoint + "leaveChat", - params - ) + await this.sendRequest("post", this.endpoint + "leaveChat", params) ).result; return send; @@ -1883,14 +2138,10 @@ export class TelegramAPI { async getChat(chat_id: string | number) { let params = { chat_id: chat_id, - } + }; const send: IChat = await ( - await this.sendRequest( - "post", - this.endpoint + "getChat", - params - ) + await this.sendRequest("post", this.endpoint + "getChat", params) ).result; return send; @@ -1905,7 +2156,7 @@ export class TelegramAPI { async getChatAdministrators(chat_id: string | number) { let params = { chat_id: chat_id, - } + }; const send: IChatMember[] = await ( await this.sendRequest( @@ -1927,7 +2178,7 @@ export class TelegramAPI { async getChatMemberCount(chat_id: string | number) { let params = { chat_id: chat_id, - } + }; const send: number = await ( await this.sendRequest( @@ -1951,14 +2202,10 @@ export class TelegramAPI { let params = { chat_id: chat_id, user_id: user_id, - } + }; const send: IChatMember = await ( - await this.sendRequest( - "post", - this.endpoint + "getChatMember", - params - ) + await this.sendRequest("post", this.endpoint + "getChatMember", params) ).result; return send; @@ -1975,7 +2222,7 @@ export class TelegramAPI { let params = { chat_id: chat_id, sticker_set_name: sticker_set_name, - } + }; const send: boolean = await ( await this.sendRequest( @@ -1997,7 +2244,7 @@ export class TelegramAPI { async deleteChatStickerSet(chat_id: string | number) { let params = { chat_id: chat_id, - } + }; const send: boolean = await ( await this.sendRequest( @@ -2016,11 +2263,14 @@ export class TelegramAPI { * @param options answerCallbackQueryOptions */ - async answerCallbackQuery(callback_query_id: string, options?: answerCallbackQueryOptions) { + async answerCallbackQuery( + callback_query_id: string, + options?: answerCallbackQueryOptions + ) { let params = { callback_query_id: callback_query_id, - ...options - } + ...options, + }; const send: boolean = await ( await this.sendRequest( @@ -2040,18 +2290,17 @@ export class TelegramAPI { * @returns boolean | IMessage */ - async editMessageText(text: string, options?: editMessageTextOptions): Promise { + async editMessageText( + text: string, + options?: editMessageTextOptions + ): Promise { let params = { text: text, - ...options - } + ...options, + }; const send: IMessage | boolean = await ( - await this.sendRequest( - "post", - this.endpoint + "editMessageText", - params - ) + await this.sendRequest("post", this.endpoint + "editMessageText", params) ).result; return send; @@ -2064,11 +2313,14 @@ export class TelegramAPI { * @returns IMessage | boolean */ - async editMessageCaption(caption: string, options?: editMessageCaptionOptions) { + async editMessageCaption( + caption: string, + options?: editMessageCaptionOptions + ) { let params = { caption: caption, - ...options - } + ...options, + }; const send: IMessage | boolean = await ( await this.sendRequest( @@ -2080,5 +2332,4 @@ export class TelegramAPI { return send; } - } From 2876b1cf7cf7dfe183fb5ca433ea45329e21dfd4 Mon Sep 17 00:00:00 2001 From: naseif Date: Tue, 15 Mar 2022 22:37:34 +0100 Subject: [PATCH 3/4] feat(API): Added error handling for the event listeners --- src/helpers/ErrorsController.ts | 1 + src/structure/TelegramAPI.ts | 66 ++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/helpers/ErrorsController.ts b/src/helpers/ErrorsController.ts index 9855ccd..d598642 100644 --- a/src/helpers/ErrorsController.ts +++ b/src/helpers/ErrorsController.ts @@ -2,6 +2,7 @@ export enum Errors { CLASS_INITIALIZATION_ERROR = "InitializationError", INVALID_TYPE = "Invalid Type", MISSING_PARAMS = "Missing Parameters", + INVALID_EVENT = "Invalid Event", } export class ErrosController extends Error { diff --git a/src/structure/TelegramAPI.ts b/src/structure/TelegramAPI.ts index 61da3c8..03e4fe4 100644 --- a/src/structure/TelegramAPI.ts +++ b/src/structure/TelegramAPI.ts @@ -175,7 +175,6 @@ export class TelegramAPI { if (!res.ok) { this.emitter.emit("error", res); - return; } return res; @@ -192,6 +191,11 @@ export class TelegramAPI { event: E, listener: (...callbacks: TelegramEvents[E]) => void ) { + if (!event) + throw new ErrosController( + "You should provide a valid event", + Errors.INVALID_EVENT + ); //@ts-expect-error this.emitter.on(event, listener); } @@ -207,51 +211,111 @@ export class TelegramAPI { event: E, listener: (...callbacks: TelegramEvents[E]) => void ) { + if (!event) + throw new ErrosController( + "You should provide a valid event", + Errors.INVALID_EVENT + ); //@ts-expect-error this.emitter.once(event, listener); } onMessage(callback: TMessageCallback) { + if (typeof callback !== "function") + throw new ErrosController( + `The paramater callback must be from type 'function', recieved: ${typeof callback}`, + Errors.INVALID_TYPE + ); this.onMessageCallback = callback; } onEditedMessage(callback: TMessageCallback) { + if (typeof callback !== "function") + throw new ErrosController( + `The paramater callback must be from type 'function', recieved: ${typeof callback}`, + Errors.INVALID_TYPE + ); this.onEditedMessageCallback = callback; } onChannelPost(callback: TMessageCallback) { + if (typeof callback !== "function") + throw new ErrosController( + `The paramater callback must be from type 'function', recieved: ${typeof callback}`, + Errors.INVALID_TYPE + ); this.onChannelPostCallback = callback; } onEditedChannelPost(callback: TMessageCallback) { + if (typeof callback !== "function") + throw new ErrosController( + `The paramater callback must be from type 'function', recieved: ${typeof callback}`, + Errors.INVALID_TYPE + ); this.onEditedChannelPostCallback = callback; } onCallbackQuery(callback: TCallbackQueryCallback) { + if (typeof callback !== "function") + throw new ErrosController( + `The paramater callback must be from type 'function', recieved: ${typeof callback}`, + Errors.INVALID_TYPE + ); this.onCallbackQueryCallback = callback; } onInlineQuery(callback: TInlineQueryCallback) { + if (typeof callback !== "function") + throw new ErrosController( + `The paramater callback must be from type 'function', recieved: ${typeof callback}`, + Errors.INVALID_TYPE + ); this.onInlineQueryCallback = callback; } onChosenInlineResult(callback: TChosenInlineResultCallback) { + if (typeof callback !== "function") + throw new ErrosController( + `The paramater callback must be from type 'function', recieved: ${typeof callback}`, + Errors.INVALID_TYPE + ); this.onChosenInlineResultCallback = callback; } onShippingQuery(callback: TShippingQueryCallback) { + if (typeof callback !== "function") + throw new ErrosController( + `The paramater callback must be from type 'function', recieved: ${typeof callback}`, + Errors.INVALID_TYPE + ); this.onShippingQueryCallback = callback; } onPreCheckoutQuery(callback: TPreCheckoutQueryCallback) { + if (typeof callback !== "function") + throw new ErrosController( + `The paramater callback must be from type 'function', recieved: ${typeof callback}`, + Errors.INVALID_TYPE + ); this.onPreCheckoutQueryCallback = callback; } onPoll(callback: TPollCallback) { + if (typeof callback !== "function") + throw new ErrosController( + `The paramater callback must be from type 'function', recieved: ${typeof callback}`, + Errors.INVALID_TYPE + ); this.onPollCallback = callback; } onPollAnswer(callback: TPollAnswerCallback) { + if (typeof callback !== "function") + throw new ErrosController( + `The paramater callback must be from type 'function', recieved: ${typeof callback}`, + Errors.INVALID_TYPE + ); this.onPollAnswerCallback = callback; } From 83b7912d2bc9a4d3ac583dfe5f34fa893e6e0b3d Mon Sep 17 00:00:00 2001 From: naseif Date: Tue, 15 Mar 2022 22:41:24 +0100 Subject: [PATCH 4/4] fix(API): removed test code. No need to listen to the message types or at least I do not see a reason why it would be necessary. Could be added later --- src/structure/TelegramAPI.ts | 26 +++----------------------- src/structure/types.ts | 6 ------ 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/src/structure/TelegramAPI.ts b/src/structure/TelegramAPI.ts index 03e4fe4..2844d30 100644 --- a/src/structure/TelegramAPI.ts +++ b/src/structure/TelegramAPI.ts @@ -336,29 +336,9 @@ export class TelegramAPI { let chatJoinReq = update.chat_join_request; if (message) { - if (message.audio) { - this.emitter.emit("audio", message.audio); - return; - } else if (message.video) { - this.emitter.emit("video", message.video); - return; - } else if (message.photo) { - this.emitter.emit("photo", message.photo); - return; - } else if (message.document) { - this.emitter.emit("document", message.document); - return; - } else if (message.new_chat_members) { - this.emitter.emit("new_chat_members", message.new_chat_members); - return; - } else if (message.left_chat_member) { - this.emitter.emit("left_chat_member", message.left_chat_member); - return; - } else { - this.emitter.emit("message", message); - if (this.onMessageCallback !== undefined) { - this.onMessageCallback(message); - } + this.emitter.emit("message", message); + if (this.onMessageCallback !== undefined) { + this.onMessageCallback(message); } } else if (editedMessage) { this.emitter.emit("edited_message", editedMessage); diff --git a/src/structure/types.ts b/src/structure/types.ts index ba5354b..ee5dcc4 100644 --- a/src/structure/types.ts +++ b/src/structure/types.ts @@ -65,12 +65,6 @@ export interface IMessageId { export interface TelegramEvents { message: [message: IMessage]; - audio: [audio: IAudio]; - video: [video: IVideo] - photo: [photo: IPhotoSize[]] - document: [document: IDocument] - new_chat_members: [member: IUser[]] - left_chat_member: [member: IUser] edited_message: [message: IMessage]; edited_channel_post: [message: IMessage]; channel_post: [message: IMessage];