@codecast-duo/codecast-duo-telegrambot
CodeCast-Duo Telegram Bot API
Content
- Introduction
- Features
- Installation
- Telegram API - Usage Guide
- API Methods
- Predicates
- Examples
- Advanced Topics
- Polling Wait Manager
Introduction
Welcome to the Telegram Bot API from CodeCast-Duo. We developed this project as a straightforward, lightweight approach to working with the Telegram Bot API free from needless complication or additional dependencies.
The package's concept is simple: start from the Telegram Bot API documentation itself. Generated methods, types, and documentation-based definitions form the foundation of this project so that the library remains as near as feasible to the original Telegram Bot API.
Consequently, the package offers complete capability for engaging with Telegram bots in the same manner the official Telegram Bot documentation outlines. It keeps the project simple and understandable while giving you typed access to methods, update structures, and core bot interactions. The library uses only the zod package as an external dependent for validation and safer data handling; it is purposefully clean.
This documentation explains how the package works and how to use it effectively in real projects.
Features
- Offers generated methods, types, and structures that are derived from the Telegram Bot API documentation.
- Maintains the interaction model near the official Telegram Bot API, thereby simplifying the library's comprehension and functionality.
- Enables complete interaction with Telegram bots, including event-driven handling, updates, and requests.
- Provides a more dependable development experience by providing typed request and response objects.
- A clean event registration system is included to facilitate the organization of bot behavior.
- Relies solely on the
zodpackage as an external dependency to maintain its simplicity and lightweight nature
Compatibility
| Package Version | Telegram Bot API Version |
|---|---|
0.4.1 |
9.5 |
0.4.2 |
10.2 |
Installation
To install the package, simply run the following command in your project directory:
npm i @codecast-duo/codecast-duo-telegrambot
This command installs the CodeCast-Duo Telegram Bot package, adding it to your project's dependencies.
Telegram API - Usage Guide
Creating an Instance of TelegramAPI
To start using the Telegram API, you need to create an instance of the TelegramAPI class. This is done using the constructor, which takes an object of type TelegramOptions as its argument. This object contains several configurations that determine how your API instance will behave.
Example
const { Telegram, TelegramError } = require('@codecast-duo/codecast-duo-telegrambot');
// Create a new instance of the Telegram bot
const bot = new Telegram({
telegramToken: "TELEGRAM_TOKEN",
// Other TelegramOptions fields as needed
});
Configuring TelegramOptions
The TelegramOptions object contains various settings that are crucial for the operation of your Telegram bot. Here are the key options you need to configure:
TelegramOptions Table
| Option | Type | Description | Default Value |
|---|---|---|---|
| telegramToken | string | The unique token for your Telegram bot, provided by BotFather. | None (Mandatory) |
| telegramApi | string | Optional. The URL of the Telegram API. If not specified, the default URL is used. | 'https://api.telegram.org' |
| start | boolean | Optional. Determines whether the bot starts processing messages immediately after instantiation. If false use startUpdaters to start polling updates. |
true |
| optionUpdate | OptionsUpdate | Optional. Configuration for receiving updates, including offset, allowed updates, and limit on updates. | OptionsUpdate Sub-Table |
| optionPollingWaitManager | OptionsPollingWaitManage | Optional. Settings for managing the wait time between polling, including max wait time and timeout action. | OptionsPollingWaitManage Sub-Table |
OptionsUpdate Sub-Table
| Option | Type | Description | Default Value |
|---|---|---|---|
| offset | number | Optional. Identifier of the first update to be returned. | 0 |
| allowed_updates | Array<keyof UpdateTypes> | Optional. List of update fields name to be received. Specify an empty list to receive all update types except chat_member, message_reaction, and message_reaction_count (default). If not specified, the previous setting will be used. Please note that this parameter doesn't affect updates created before the call to the getUpdates, so unwanted updates may be received for a short period of time. | [] |
| limit | number | Optional. Limits the number of updates to be retrieved. | 100 |
OptionsPollingWaitManage Sub-Table
| Option | Type | Description | Default Value |
|---|---|---|---|
| maxWaitTime | number | Optional. The maximum waiting time (in milliseconds) allowed before considering the polling process as too long and taking action. | 60000 (60 seconds) |
| onWait | number | Optional. A callback function that gets executed when the waiting time exceeds maxWaitTime. It allows you to define custom actions or error handling when polling takes too long. |
Empty function (() => {}) |
Example
const options = {
telegramToken: 'YOUR_TELEGRAM_BOT_TOKEN',
telegramApi: 'https://api.telegram.org',
start: true,
optionUpdate: {
offset: 0,
allowed_updates: ['message', 'callback_query'],
limitUpdates: 100
},
optionPollingWaitManager: {
maxWaitTime: 3000,
onWaitTooLong: () => { /* Handle long wait times */ }
}
};
API Methods
sendMessage Method
sendMessage(params: TelegramTypes.MethodRequest<'sendMessage'>): Promise<TelegramTypes.Message>: This method is used to send a message to a specific chat through the Telegram Bot API. It acts as a convenience wrapper around Telegram'ssendMessagemethod and is useful when you want to quickly send text messages without calling the lower-level request method directly.
await bot.sendMessage({
chat_id: 123456789,
text: 'Hello from CodeCast-Duo Telegram Bot',
});
Parameters:
| Parameter | Type | Description |
|---|---|---|
params |
TelegramTypes.MethodRequest<'sendMessage'> |
The request payload for the Telegram Bot API 'sendMessage' method |
sendRequest Method
sendRequest<M extends MethodName>(method: M, params: MethodRequest<M>): Promise<MethodResult<M>>: This method is used to send a typed request to any Telegram Bot API method. It is particularly useful when there is no dedicated convenience method available in theTelegramclass, allowing you to access the full Telegram API while preserving type safety.
await bot.sendRequest('editMessageText', {
chat_id: 123456789,
message_id: 10,
text: 'Updated text',
});
Parameters:
| Parameter | Type | Description |
|---|---|---|
method |
M extends TelegramTypes.MethodName |
The name of the Telegram Bot API method you want to call |
params |
TelegramTypes.MethodRequest<M> |
The request payload for the selected Telegram Bot API method |
register Method
register<K extends UpdateKey, S extends UpdatePayload<K>>( key: K, match: Predicate<UpdatePayload<K>>, handler: Handler<UpdatePayload<K>> ): TelegramEventRegistry: This method is used to register a handler for a specific top-level Telegram update field. It allows you to define a predicate that decides whether a handler should run for a given update payload, making it useful for filtering and processing only the updates that match your bot logic.
bot.register(
'message',
(message) => message.text.startsWith('/start'),
async (message) => {
console.log(message.text);
},
);
Parameters:
| Parameter | Type | Description |
|---|---|---|
key |
string |
Any top-level key from TelegramTypes.Update except update_id, for example message, edited_message, callback_query, channel_post, poll |
match |
Predicate<UpdatePayload<K>> |
Predicate or type guard (payload, update) => boolean used to decide whether the handler should run |
handler |
Handler<UpdatePayload<K>> |
Handler (payload, update) => void | Promise<void> executed when the predicate matches |
startUpdater Method
startUpdater(): void: This method is used to start the polling process for updates. It initiates the bot's ability to listen for incoming updates from Telegram. This is particularly useful when your bot is set up to not start automatically, or if you've previously stopped the update polling and need to restart it.
stopUpdater Method
stopUpdater(): Promise<void>: The stopUpdaters method is used to stop the polling process. This is useful when you want to temporarily halt your bot from listening to incoming updates, without shutting down the entire bot. This can be handy during maintenance, updating bot logic, or handling unexpected behavior.
Predicates
The predicates object provides a set of helper methods for building reusable conditions when working with the register method. These helpers are useful for combining multiple conditions, negating conditions, checking alternative matches, and narrowing object properties such as text for safer TypeScript usage.
In future versions,
predicateswill be improved to make working with optional fields more convenient. Right now, simple checks such as verifying whether a message starts with/startmay require additional fallback logic like(message) => message.text?.startsWith('/start') || false.
predicates.and Method
predicates.and<T, A extends T>( ...predicates: Predicate<A>[] ): Predicate<T>: This method is used to combine multiple predicates into a single condition using logicalAND. It returnstrueonly when all provided predicates returntrue. This is particularly useful when you want to check several conditions before executing a handler, such as verifying that a message has text and that the text starts with a specific command.
bot.register(
'message',
predicates.and(
(message) => message.id == 123456789,
(message) => message.text?.startsWith('/start') || false,
),
async (message) => {
console.log(message.text);
},
);
Parameters:
| Parameter | Type | Description |
|---|---|---|
predicates |
Predicate<A>[] |
Additional predicates that must all return true |
predicates.or Method
predicates.or<T>(...predicates: Predicate<T>[]): Predicate<T>: This method is used to combine multiple predicates into a single condition using logicalOR. It returnstruewhen at least one of the provided predicates returnstrue. This is useful when your handler should run for several possible cases instead of only one strict condition.
bot.register(
'message',
predicates.or(
(message) => message.text === '/start',
(message) => message.text === '/help',
),
async (message) => {
console.log(message.text);
},
);
Parameters:
| Parameter | Type | Description |
|---|---|---|
predicates |
Predicate<T>[] |
A list of predicates where at least one must return true |
predicates.not Method
predicates.not<T>(predicate: Predicate<T>): Predicate<T>: This method is used to invert the result of a predicate. It returnstruewhen the provided predicate returnsfalse, andfalsewhen the provided predicate returnstrue. This is useful when you want to exclude a specific condition from your handler logic.
bot.register(
'message',
predicates.not((message) => message.text === '/start'),
async (message) => {
console.log(message.text);
},
);
Parameters:
| Parameter | Type | Description |
|---|---|---|
predicate |
Predicate<T> |
The predicate whose result should be inverted |
Examples
Here's a basic guide on how to use the CodeCast-Duo Telegram Bot API in your project:
// Import the required Telegram bot library
import {
Telegram,
TelegramError,
predicates,
} from '@codecast-duo/codecast-duo-telegrambot';
// Create a new instance of the Telegram bot
const bot = new Telegram({
telegramToken: 'TELEGRAM_TOKEN',
});
// Register a handler for text messages
bot.register(
'message',
(message) => !!message.text,
async (message) => {
// Define the structure of the inline keyboard markup
const inlineKeyboardMarkup = {
reply_markup: {
inline_keyboard: [
[{ text: 'Test1', callback_data: 'Callback data test1' }],
[{ text: 'Test2', callback_data: 'Callback data test2' }]
]
}
};
try {
// Send a message back to the chat with the inline keyboard
const sentMessage = await bot.sendMessage({
chat_id: message.chat.id,
text: message.text || 'if parameter empty',
...inlineKeyboardMarkup,
});
setTimeout(() => {
bot.sendRequest('editMessageText', {
text: 'Test',
chat_id: sentMessage.chat.id,
message_id: sentMessage.message_id,
reply_markup: {
inline_keyboard: [
[{ text: 'TestNew1', callback_data: 'Callback data testNew1' }],
[{ text: 'TestNew2', callback_data: 'Callback data testNew2' }]
]
}
}).catch((error: unknown) => {
// Handle errors specifically related to Telegram
if (error instanceof TelegramError) {
console.log(error.message);
} else {
// Handle any other generic errors
console.log('is default error');
}
});
}, 1000);
} catch (error: unknown) {
// Handle errors specifically related to Telegram
if (error instanceof TelegramError) {
console.log(error.message);
} else {
// Handle any other generic errors
console.log('is default error');
}
}
}
);
// Register a handler for callback queries (e.g., when an inline button is pressed)
bot.register(
'callback_query',
(callback) => !!callback.data,
async (callback) => {
// Respond to the callback query
await bot.sendMessage({
chat_id: callback.from.id,
text: callback.data || 'if callback.data empty',
});
console.log(callback.data);
}
);
// Register a handler for text commands (e.g., "/echo some text")
bot.register(
'message',
(message) => /^\/echo (.+)/.test(message.text || ''),
async (message) => {
// Log the text following the echo command
console.log(message.text);
}
);
// Register a handler using composed predicates
bot.register(
'message',
predicates.and(
(message) => message.text?.startsWith('/start') || false,
),
async (message) => {
await bot.sendMessage({
chat_id: message.chat.id,
text: 'Welcome!',
});
}
);
// Check the bot's information (e.g., username)
bot.getMe({}).then(user => {
// Log success if user data is retrieved
if (user) {
console.log('connected');
}
});
// Global error event listener
bot.on('error', (error) => {
// Log any errors encountered
console.error(error);
});
// Specific error event listener for network-related errors
bot.on('error-NetworkError', (error) => {
// Log network errors separately
console.error(error);
});
Advanced Topics
Error types
Below is a table describing the different types of errors (TelegramErrorTypes) that can occur when interacting with the Telegram API, along with a brief description of each error type:
| Error Type | Description |
|---|---|
| NetworkError | Occurs when there is a problem with the network connection, such as a failure to reach the Telegram servers. |
| ApiError | This error is thrown when there is an issue with the API request, such as invalid parameters or authentication issues. |
| TimeoutError | Occurs when a request to the Telegram API takes too long to respond, exceeding the predefined timeout limit. |
| InternalServerError | Indicates a problem on the Telegram server side, such as a server malfunction or maintenance. |
| ParsingError | This error is encountered when there is an issue in parsing the response from the Telegram API. |
| UnhandledPromiseRejection | Occurs when a Promise in the code is rejected but not properly handled with a catch block. |
| UnknownError | Used as a catch-all for any errors that do not fit into the other predefined categories. |
Error handling
In your Telegram bot implementation, you can set up error handling in two primary ways:
Catch All Errors: Use
bot.on('error', (error) => {});to handle all types of errors. This is a general error handler that will catch any error thrown by the bot, regardless of its type. It's useful for logging or handling errors in a generic way.bot.on('error', (error) => { console.error('An error occurred:', error); // Additional error handling logic can go here });Catch Specific Types of Errors: Use
bot.on('error-TelegramErrorTypes', (error) => {});to handle specific types of errors. This allows for more granular error handling based on the error type. For example, you can have different handlers forNetworkError,ApiError, etc.// Handling NetworkError specifically bot.on('error-NetworkError', (error) => { console.error('Network Error:', error); // Specific handling for network errors }); // Handling ApiError specifically bot.on('error-ApiError', (error) => { console.error('API Error:', error); // Specific handling for API errors }); // ... similarly for other error typesCatch from onMessage(), onUpdate(), onText (): In the context of Telegram bot development using the described library, methods like onMessage, onUpdate, and onText typically return a Promise. The resolution of these promises is usually void, meaning they do not return any value upon successful completion. However, in case of an error, these methods can throw an exception, which is caught in the catch block.
When you use these methods, it's a good practice to handle potential errors that might occur during their execution. This error handling is usually done by attaching a catch block to the promise. The error caught is typically an instance of the TelegramError class, which provides details about what went wrong.
Here's how you might structure your code to include error handling with these methods:
// Handling incoming text messages
bot.onMessage('text', (parameter, message) => {
// Logic to handle the message
// ...
}).catch(error => {
if (error instanceof TelegramError) {
console.error('TelegramError occurred:', error.message);
} else {
console.error('Unknown error occurred:', error);
}
});
Description TelegramError
The TelegramError class provides a structured way to handle errors encountered during Telegram bot operations. It encapsulates details about the error, including its type and, if available, a specific error code. This class can handle different types of errors, such as network issues or API-related problems, and can be instantiated with detailed information about the underlying error.
Properties Table TelegramError
| Parameter | Type | Description |
|---|---|---|
| error_code | string | undefined | An optional code that provides additional information about the error. This is typically specific to the type of error encountered. |
| type | TelegramErrorTypes | The type of the error, categorized as one of the predefined TelegramErrorTypes, such as NetworkError, ApiError, etc. |
| message | string | Inherited from the base Error class, this property contains a message describing the error. |
| stack | string | undefined | Also inherited from the base Error class, this property provides a stack trace at the point where the error was instantiated, if available. |
Polling Wait Manager
The "Polling Wait Manager" is a crucial component utilized for the efficient management of the polling process in applications that communicate with a remote server through polling. Polling involves sending periodic requests to a server to retrieve updates or data. The Polling Wait Manager plays a pivotal role in ensuring the effective control of this polling process and handling pauses in the operation of an application.
Using Polling Wait Manager
The Polling Wait Manager proves to be invaluable in applications that depend on polling to receive updates or data from a remote server. It serves to guarantee the efficient and optimal management of polling, dynamically turning it off when not required. This not only conserves valuable resources but also prevents excessive server load.
TelegramAPI Class and Polling Wait Manager
The TelegramAPI class offers a seamless integration with the Polling Wait Manager, empowering you to take charge of the polling process. Here is an overview of the available methods along with their descriptions:
Polling Wait Manager Methods
getPollingWaitManager(): PollingWaitManager | undefined: ThegetPollingWaitManagermethod provides the means to fetch the current Polling Wait Manager object or returnsundefinedif it hasn't been initialized.setPollingWaitManager(name: string, func: () => boolean): void: With thesetPollingWaitManagermethod, you can effortlessly create or modify a function within the Polling Wait Manager. This function requires the name of the function and a callback function that should return abooleanvalue. If the Polling Wait Manager doesn't exist, this method will create it dynamically.removePollingWaitManager(name: string): voidTheremovePollingWaitManagermethod allows you to selectively remove a function from the Polling Wait Manager by specifying its name. This function deletion process is seamless and effective.
These methods are instrumental in efficiently managing the polling process within your application by defining conditions under which polling should continue or cease. They serve as invaluable tools for optimizing the operation of applications reliant on polling to receive updates or data.
Examples 1: Initializing and Using Polling Wait Manager
Here's a basic guide on how to use the CodeCast-Duo Telegram Bot API in your project:
const { Telegram } = require('@codecast-duo/codecast-duo-telegrambot');
const bot = new Telegram({
telegramToken: "TELEGRAM_TOKEN",
});
const pollingWaitManager = bot.getPollingWaitManager();
let continuePolling= false;
function shouldContinuePolling() {
return continuePolling;
}
setTimeout(() => {
continuePolling = true;
}, 30000);
bot.setPollingWaitManager("exampleFunction", shouldContinuePolling);
In this example, we initialize the TelegramAPI instance, retrieve the Polling Wait Manager, define a function (shouldContinuePolling) that determines whether polling should continue, set this function in the Polling Wait Manager.
Examples 2: Removing a Polling Function
bot.removePollingWaitManager("exampleFunction");
In this example, we remove a polling function named "exampleFunction" from the Polling Wait Manager. This function will no longer be used to determine whether polling should continue.