bale-bot-ts
Version:
A TypeScript SDK for Bale.ai bots
550 lines (549 loc) • 25.9 kB
JavaScript
"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;