UNPKG

bale-bot-ts

Version:

A TypeScript SDK for Bale.ai bots

550 lines (549 loc) 25.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaleBotClient = void 0; const axios_1 = __importDefault(require("axios")); const form_data_1 = __importDefault(require("form-data")); // Import FormData for Node.js multipart/form-data const events_1 = __importDefault(require("events")); // --- Main BaleBotClient Class --- class BaleBotClient extends events_1.default { /** * Creates a new BaleBotClient instance. * @param token - The unique authentication token for your bot. */ constructor(token) { super(); this.token = token; this.baseURL = 'https://tapi.bale.ai/'; // Base URL for Bale Bot API this.pollingInterval = null; this.lastUpdateId = 0; if (!token) { throw new Error('Bale Bot Token is required.'); } this.api = axios_1.default.create({ baseURL: `${this.baseURL}bot${this.token}/`, headers: { 'Content-Type': 'application/json', // Default content type }, }); } async sendRequest(method, data, isFileRequest = false) { var _a, _b, _c; try { let response; if (isFileRequest && data) { const formData = new form_data_1.default(); for (const key in data) { if (Object.prototype.hasOwnProperty.call(data, key)) { // If the value is a file (Buffer or ReadableStream) if (data[key] instanceof Buffer || (data[key] && typeof data[key].pipe === 'function')) { // Append file with a generic filename using the third argument as options for form-data formData.append(key, data[key], { filename: key }); } else if (typeof data[key] === 'object' && data[key] !== null) { // For objects or arrays, stringify them formData.append(key, JSON.stringify(data[key])); } else { // For primitive types formData.append(key, data[key]); } } } response = await this.api.post(method, formData, { headers: { // Ensure form-data generates the correct boundary ...formData.getHeaders() } }); } else { // For non-file requests, default to JSON POST response = await this.api.post(method, data); } if (!response.data.ok) { throw new Error(`Bale API Error: ${response.data.description || 'Unknown error'} (Code: ${response.data.error_code})`); } return response.data; } catch (error) { console.error(`Error in ${method}:`, ((_a = error.response) === null || _a === void 0 ? void 0 : _a.data) || error.message); throw new Error(`Failed to call ${method}: ${((_c = (_b = error.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.description) || error.message}`); } } startPolling(interval = 3000) { if (this.pollingInterval) return; // جلوگیری از شروع مجدد this.pollingInterval = setInterval(async () => { try { const response = await this.api.get(`getUpdates`, { params: { offset: this.lastUpdateId + 1, timeout: 0, }, }); if (response.data.ok && Array.isArray(response.data.result)) { for (const update of response.data.result) { this.lastUpdateId = update.update_id; if (update.message) { this.emit('message', update.message); } } } } catch (error) { console.error('[Polling error]', error.message); } }, interval); } stopPolling() { if (this.pollingInterval) { clearInterval(this.pollingInterval); this.pollingInterval = null; } } // --- متدهای موجود (Available Methods) --- /** * A simple method for testing your bot's authentication token. * @returns Basic information about the bot in the form of a User object. */ async getMe() { return this.sendRequest('getMe'); } /** * Use this method to log out from the cloud Bot API server before launching the bot in a test environment. * @returns True on success. */ async logout() { return this.sendRequest('logout'); } /** * Use this method to close the bot instance before moving it from a local server or test environment to the production server. * @returns True on success. */ async close() { return this.sendRequest('close'); } /** * Use this method to send text messages. * @param options - Options for sending the message. * @returns The sent Message object on success. */ async sendMessage(options) { return this.sendRequest('sendMessage', options); } /** * Use this method to forward messages of any kind. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param from_chat_id - Unique identifier for the chat where the original message was sent. * @param message_id - Unique message identifier in the original chat. * @returns The forwarded Message on success. */ async forwardMessage(chat_id, from_chat_id, message_id) { return this.sendRequest('forwardMessage', { chat_id, from_chat_id, message_id }); } /** * Use this method to copy messages of any kind. Service messages and invoice messages can't be copied. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param from_chat_id - Unique identifier for the chat where the original message was sent. * @param message_id - Unique message identifier in the original chat. * @returns The MessageId of the sent message on success. */ async copyMessage(chat_id, from_chat_id, message_id) { return this.sendRequest('copyMessage', { chat_id, from_chat_id, message_id }); } /** * Use this method to send photos. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param photo - Photo to send. Pass a file_id, HTTP URL, or upload a new photo using multipart/form-data. * @param caption - Photo caption (0-1024 characters). * @param reply_to_message_id - If the message is a reply, ID of the original message. * @param reply_markup - Additional interface options. * @returns The sent Message on success. */ async sendPhoto(chat_id, photo, caption, reply_to_message_id, reply_markup) { const data = { chat_id, photo }; if (caption) data.caption = caption; if (reply_to_message_id) data.reply_to_message_id = reply_to_message_id; if (reply_markup) data.reply_markup = reply_markup; return this.sendRequest('sendPhoto', data, typeof photo !== 'string'); } /** * Use this method to send audio files, if you want Bale clients to display them in the music player. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param audio - Audio file to send. Pass a file_id, HTTP URL, or upload a new audio file using multipart/form-data. * @param caption - Audio caption (0-1024 characters). * @param reply_to_message_id - If the message is a reply, ID of the original message. * @param reply_markup - Additional interface options. * @returns The sent Message on success. */ async sendAudio(chat_id, audio, caption, reply_to_message_id, reply_markup) { const data = { chat_id, audio }; if (caption) data.caption = caption; if (reply_to_message_id) data.reply_to_message_id = reply_to_message_id; if (reply_markup) data.reply_markup = reply_markup; return this.sendRequest('sendAudio', data, typeof audio !== 'string'); } /** * Use this method to send general files. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param document - File to send. Pass a file_id, HTTP URL, or upload a new file using multipart/form-data. * @param caption - Document caption (0-1024 characters). * @param reply_to_message_id - If the message is a reply, ID of the original message. * @param reply_markup - Additional interface options. * @returns The sent Message on success. */ async sendDocument(chat_id, document, caption, reply_to_message_id, reply_markup) { const data = { chat_id, document }; if (caption) data.caption = caption; if (reply_to_message_id) data.reply_to_message_id = reply_to_message_id; if (reply_markup) data.reply_markup = reply_markup; return this.sendRequest('sendDocument', data, typeof document !== 'string'); } /** * Use this method to send video files. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param video - Video to send. Pass a file_id, HTTP URL, or upload a new video file using multipart/form-data. * @param caption - Video caption (0-1024 characters). * @param reply_to_message_id - If the message is a reply, ID of the original message. * @param reply_markup - Additional interface options. * @returns The sent Message on success. */ async sendVideo(chat_id, video, caption, reply_to_message_id, reply_markup) { const data = { chat_id, video }; if (caption) data.caption = caption; if (reply_to_message_id) data.reply_to_message_id = reply_to_message_id; if (reply_markup) data.reply_markup = reply_markup; return this.sendRequest('sendVideo', data, typeof video !== 'string'); } /** * Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param animation - Animation to send. Pass a file_id, HTTP URL, or upload a new animation file using multipart/form-data. * @param reply_to_message_id - If the message is a reply, ID of the original message. * @param reply_markup - Additional interface options. * @returns The sent Message on success. */ async sendAnimation(chat_id, animation, reply_to_message_id, reply_markup) { const data = { chat_id, animation }; if (reply_to_message_id) data.reply_to_message_id = reply_to_message_id; if (reply_markup) data.reply_markup = reply_markup; return this.sendRequest('sendAnimation', data, typeof animation !== 'string'); } /** * Use this method to send audio files, if you want Bale clients to display the file as a playable voice message. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param voice - Audio file to send. Pass a file_id, HTTP URL, or upload a new voice file using multipart/form-data. * @param caption - Voice message caption (0-1024 characters). * @param reply_to_message_id - If the message is a reply, ID of the original message. * @param reply_markup - Additional interface options. * @returns The sent Message on success. */ async sendVoice(chat_id, voice, caption, reply_to_message_id, reply_markup) { const data = { chat_id, voice }; if (caption) data.caption = caption; if (reply_to_message_id) data.reply_to_message_id = reply_to_message_id; if (reply_markup) data.reply_markup = reply_markup; return this.sendRequest('sendVoice', data, typeof voice !== 'string'); } /** * Use this method to send a group of photos, videos, documents or audios as an album. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param media - A JSON-serialized array describing messages to be sent. * @param reply_to_message_id - If the message is a reply, ID of the original message. * @returns An array of sent Messages on success. */ async sendMediaGroup(chat_id, media, reply_to_message_id) { const data = { chat_id, media: JSON.stringify(media) }; if (reply_to_message_id) data.reply_to_message_id = reply_to_message_id; // Check if any media item requires multipart/form-data const requiresMultipart = media.some(item => item.media.startsWith('attach://')); return this.sendRequest('sendMediaGroup', data, requiresMultipart); } /** * Use this method to send point on the map. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param latitude - Latitude of the location. * @param longitude - Longitude of the location. * @param horizontal_accuracy - The radius of uncertainty for the location, measured in meters. 0-1500. * @param reply_to_message_id - If the message is a reply, ID of the original message. * @param reply_markup - Additional interface options. * @returns The sent Message on success. */ async sendLocation(chat_id, latitude, longitude, horizontal_accuracy, reply_to_message_id, reply_markup) { const data = { chat_id, latitude, longitude }; if (horizontal_accuracy) data.horizontal_accuracy = horizontal_accuracy; if (reply_to_message_id) data.reply_to_message_id = reply_to_message_id; if (reply_markup) data.reply_markup = reply_markup; return this.sendRequest('sendLocation', data); } /** * Use this method to send phone contacts. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param phone_number - Contact's phone number. * @param first_name - Contact's first name. * @param last_name - Contact's last name. * @param reply_to_message_id - If the message is a reply, ID of the original message. * @param reply_markup - Additional interface options. * @returns The sent Message on success. */ async sendContact(chat_id, phone_number, first_name, last_name, reply_to_message_id, reply_markup) { const data = { chat_id, phone_number, first_name }; if (last_name) data.last_name = last_name; if (reply_to_message_id) data.reply_to_message_id = reply_to_message_id; if (reply_markup) data.reply_markup = reply_markup; return this.sendRequest('sendContact', data); } /** * Use this method to get basic info about a file and prepare it for downloading. * @param file_id - File identifier to get info about. * @returns A File object on success. */ async getFile(file_id) { return this.sendRequest('getFile', { file_id }); } /** * Use this method to receive incoming updates using long polling. * @param options - Options for getting updates. * @returns An Array of Update objects on success. */ async getUpdates(options) { return this.sendRequest('getUpdates', options); } /** * Use this method to specify a URL and receive incoming updates via an outgoing webhook. * @param options - Options for setting the webhook. * @returns True on success. */ async setWebhook(options) { return this.sendRequest('setWebhook', options); } /** * Use this method to get current webhook status. * @returns A WebhookInfo object on success. */ async getWebhookInfo() { return this.sendRequest('getWebhookInfo'); } /** * Use this method to get up-to-date information about the chat. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @returns A Chat object on success. */ async getChat(chat_id) { return this.sendRequest('getChat', { chat_id }); } /** * Use this method to get the number of members in a chat. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @returns An Integer representing the number of chat members. */ async getChatMembersCount(chat_id) { return this.sendRequest('getChatMembersCount', { chat_id }); } /** * Use this method to pin a message in a group or a channel. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param message_id - Identifier of the message to pin. * @returns True on success. */ async pinChatMessage(chat_id, message_id) { return this.sendRequest('pinChatMessage', { chat_id, message_id }); } /** * Use this method to unpin a message in a group or a channel. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param message_id - Identifier of the message to unpin. * @returns True on success. */ async unpinChatMessage(chat_id, message_id) { return this.sendRequest('unpinChatMessage', { chat_id, message_id }); } /** * Use this method to unpin all pinned messages in a chat. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @returns True on success. */ async unpinAllChatMessages(chat_id) { return this.sendRequest('unpinAllChatMessages', { chat_id }); } /** * Use this method to change the title of a chat. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param title - New chat title. * @returns True on success. */ async setChatTitle(chat_id, title) { return this.sendRequest('setChatTitle', { chat_id, title }); } /** * Use this method to change the description of a group or a channel. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param description - New chat description. * @returns True on success. */ async setChatDescription(chat_id, description) { return this.sendRequest('setChatDescription', { chat_id, description }); } /** * Use this method to delete a chat photo. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @returns True on success. */ async deleteChatPhoto(chat_id) { return this.sendRequest('deleteChatPhoto', { chat_id }); } /** * Use this method to create a new invite link for a chat. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @returns The new invite link on success. */ async createChatInviteLink(chat_id) { return this.sendRequest('createChatInviteLink', { chat_id }); } /** * Use this method to revoke an invite link for a group. After revocation, a new link is generated and returned. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param invite_link - The invite link to revoke. * @returns The new invite link on success. */ async revokeChatInviteLink(chat_id, invite_link) { return this.sendRequest('revokeChatInviteLink', { chat_id, invite_link }); } /** * Use this method for the bot to create a new invite link for a chat. If already created, it will be revoked and a new one will be created. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @returns The new invite link on success. */ async exportChatInviteLink(chat_id) { return this.sendRequest('exportChatInviteLink', { chat_id }); } /** * Use this method to edit text messages. * @param text - New text of the message (1-4096 characters). * @param chat_id - Required if inline_message_id is not specified. Unique identifier for the target chat or username of the target channel. * @param message_id - Required if inline_message_id is not specified. Identifier of the message to edit. * @param reply_markup - A JSON-serialized object for an inline keyboard. * @returns The edited Message object on success. */ async editMessageText(text, chat_id, message_id, reply_markup) { const data = { text }; if (chat_id) data.chat_id = chat_id; if (message_id) data.message_id = message_id; if (reply_markup) data.reply_markup = reply_markup; return this.sendRequest('editMessageText', data); } /** * Use this method to delete a message, including service messages. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param message_id - Identifier of the message to delete. * @returns True on success. */ async deleteMessage(chat_id, message_id) { return this.sendRequest('deleteMessage', { chat_id, message_id }); } /** * Use this method to upload a file for future use in newStickerSet and addStickerToSet methods. * @param user_id - User identifier of sticker file owner. * @param sticker - A file of .WEBP, .PNG, .TGS, or .WEBM format. * @returns The uploaded File object on success. */ async uploadStickerFile(user_id, sticker) { return this.sendRequest('uploadStickerFile', { user_id, sticker }, true); } /** * Use this method to create a new sticker set owned by a user. * @param user_id - User identifier of created sticker set owner. * @param name - Short name of the sticker set. * @param title - Sticker set title. * @param stickers - A JSON-serialized list of 1-50 initial stickers to be added to the sticker set. * @returns True on success. */ async createNewStickerSet(user_id, name, title, stickers) { return this.sendRequest('createNewStickerSet', { user_id, name, title, stickers: JSON.stringify(stickers) }); } /** * Use this method to add a new sticker to a set created by the bot. * @param user_id - User identifier of sticker set owner. * @param name - Sticker set name. * @param sticker - A JSON-serialized object with information about the added sticker. * @returns True on success. */ async addStickerToSet(user_id, name, sticker) { return this.sendRequest('addStickerToSet', { user_id, name, sticker: JSON.stringify(sticker) }); } /** * Use this method to send invoices. * @param chat_id - Unique identifier for the target chat or username of the target channel. * @param title - Product name (1-32 characters). * @param description - Product description (1-255 characters). * @param payload - Bot-defined invoice payload (1-128 bytes). * @param provider_token - Payment provider token (card number or wallet token). * @param prices - A JSON-serialized list of items and their prices. * @param photo_url - URL of the product photo. * @param reply_to_message_id - If the message is a reply, ID of the original message. * @returns The sent Message on success. */ async sendInvoice(chat_id, title, description, payload, provider_token, prices, photo_url, reply_to_message_id) { const data = { chat_id, title, description, payload, provider_token, prices: JSON.stringify(prices) }; if (photo_url) data.photo_url = photo_url; if (reply_to_message_id) data.reply_to_message_id = reply_to_message_id; return this.sendRequest('sendInvoice', data); } /** * Use this method to respond to a pre-checkout query. * @param pre_checkout_query_id - Unique identifier for the pre-checkout query to be answered. * @param ok - True if everything is alright, False otherwise. * @param error_message - Required if ok is False. Error message to be displayed to the user. * @returns True on success. */ async answerPreCheckoutQuery(pre_checkout_query_id, ok, error_message) { const data = { pre_checkout_query_id, ok }; if (error_message) data.error_message = error_message; return this.sendRequest('answerPreCheckoutQuery', data); } /** * Use this method to inquire about the status of a specific transaction by sending its unique ID. * Note: This method is NOT present in standard Telegram bot libraries and requires direct HTTP request. * @param transaction_id - Unique ID of the transaction to inquire. * @returns A Transaction object on success. */ async inquireTransaction(transaction_id) { return this.sendRequest('inquireTransaction', { transaction_id }); } } exports.BaleBotClient = BaleBotClient;