Constructor
new Opengram(token, optionsopt)
Name | Type | Attributes | Description |
---|---|---|---|
token | string | Bot token given by @BotFather | |
options | OpengramOptions | <optional> | Opengram options |
- Source
Extends
Members
token
Setter for bot token
- Source
token
Getter for bot token
- Source
username
Setter for bot username
- Source
username
Getter for bot username
- Source
webhookReply
Setter for enabling / disabling for webhook reply. if assigned true
- webhook reply enabled
- Source
webhookReply
Returns the status of the webhook reply (enabled / disabled). if true
is returned, the webhook reply is enabled
- Source
Methods
action(triggers, …fns) → {Composer}
Registers some middleware(s) for callback queries, i.e. the updates that Telegram delivers to your bot when a user clicks an inline button (that is a button under a message).
This method is essentially the same as calling
bot.on('callback_query', ctx => { ... })
but it also allows you to match the query data against a given text or regular expression.
// Create an inline keyboard
const keyboard = Markup.inlineKeyboard([
Markup.callbackButton('Go!', 'button-payload')
])
// Send a message with the keyboard
await bot.telegram.sendMessage(chat_id, 'Press a button!', keyboard.extra())
// Listen to users pressing buttons with that specific payload
bot.action('button-payload', ctx => { ... })
// Listen to users pressing any button your bot ever sent
bot.on('callback_query', ctx => { ... })
Always remember to call Telegram#answerCbQuery or OpengramContext#answerCbQuery — even if you don't perform any action: https://core.telegram.org/bots/api#answercallbackquery
bot.on('callback_query', async ctx => {
await ctx.answerCbQuery()
})
You can pass one or an array of triggers (Regexp / strings). Your middleware(s) will be executed if at least one of them matches.
Note how
ctx.match
will contain the result of the regular expression. Soctx.match[1]
refers to the part of the regexp that was matched by([0-9]+)
, i.e. the text that comes after "button:".bot.action(/button:([0-9]+)/, ctx => ctx.reply(`You choose button with number ${ctx.match[1]} in payload`)) const keyboard = Markup.inlineKeyboard([ Markup.callbackButton('Button 1', 'button:1'), Markup.callbackButton('Button 2', 'button:2'), Markup.callbackButton('Button 3', 'button:3') ]) await bot.telegram.sendMessage(chat_id, 'Press a button!', keyboard.extra())
You can also paste function (or array of functions) that takes the value and context as arguments and returns true or false (or some Truthy
result) based on them. This can be used, for example, for dynamic text matching at i18n. The result returned by the function will be available from ctx.match
bot.action(
(value, ctx) => {
//... some checks ...
return ['some', 'data']
},
// Show cb query answer for all queries with "I love some data"
ctx => ctx.answerCbQuery(`I love ${ctx.match[0]} ${ctx.match[1]}`)
)
Name | Type | Attributes | Description |
---|---|---|---|
triggers | Trigger | | One or an array of regular expressions / strings to search in the payload | |
fns | Middleware | <repeatable> | The middleware(s) to register as arguments |
- Overrides
- Source
- Type:
- Composer
cashtag(…args) → {Composer}
Registers some middleware(s) that will only be executed if hashtag
entity is present in the update
Shortcut to Composer.entity('cashtag', ...)
This method matches entity in channel post, message and media caption
Name | Type | Attributes | Description |
---|---|---|---|
args | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Composer
catch(handler) → {Opengram}
Sets default error handler for Opengram errors. For example if you throw synchronous error or return
/ await
promise was rejected, it calls this handler, if one is set. If it has not been set - the bot may crash, if some handler like process.on
does not handle the error.
const { Opengram } = require('opengram')
const bot = new Opengram('token')
async function errorFirst() { throw new Error('Some error') }
function second() { return Promise.reject(new Error('Some error')) }
// Handled with bot.catch()
bot.on('message', ctx => { throw new Error('Some error') })
// Handled with bot.catch(), because you return promise (async function with await on async ops)
bot.hears('asyncFirst', async ctx => { await errorFirst() })
// Handled with bot.catch(), because you return promise (async function with await on async ops)
bot.action('asyncSecond', async ctx => { await second() })
// Handled with bot.catch(), because you return promise
bot.action('asyncSecond', ctx => errorFirst())
// Handled with bot.catch(), because you return promise
bot.on('message', ctx => second())
// Bot crashed, error not handled
bot.action('asyncSecond', ctx => { errorFirst() })
// Bot crashed, error not handled
bot.on('message', async ctx => { second() })
bot.catch((err, ctx) => console.log(err, ctx)) // Print error and error context to console, no crash
bot.launch() // Start the bot
Name | Type | Description |
---|---|---|
handler | function | Error handler accepting error and context |
- Source
- Type:
- Opengram
command(commands, …fns)
Registers some middleware(s) that will only be executed when a certain command is found.
// Reacts to /start commands
bot.command('start', ctx => { ... })
// Reacts to /help commands
bot.command('help', ctx => { ... })
Note: Commands are not matched in the middle of the text.
bot.command('start', ctx => { ... })
// ... does not match:
// A message saying: “some text /start some more text”
// A photo message with the caption “some text /start some more text”
By default, commands are detected in channel posts and media captions, too. This means that ctx.message
for channel post or ctx.message.text
for media is potentially undefined
, so you should use ctx.channelPost
and ctx.message.caption
accordingly for channel posts. Alternatively, if you want to limit your bot to finding commands only in private and group chats, you can use
const { Opengram, Composer: { command } } = require('opengram')
// ...
bot.on('message', command('start', ctx => ctx.reply('Only private / group messages or media with caption')))`
or using Composer.chatType:
const { Opengram, Composer, Composer: { command } } = require('opengram')
// ...
bot.use(
Composer.chatType(
["private", "group", "supergroup"],
command('start', ctx => ctx.reply('Only private / group messages or media with caption'))
)
)
for match all message exclude channel posts, or
const { Opengram, Composer: { command } } = require('opengram')
// ...
bot.on('text', command('start', ctx => ctx.reply('Math commands only text, not media captions')))
for match only text message, not media caption or even store a message-only version of your bot in a variable like so:
Be careful, the example above may not work as expected if
channelMode
is enabled.By default
text
type not match channel posts, butchannel_post
matched astext
type andctx.message
potentiallyundefined
whenchannelMode
enabled. You can add additional chat type check for this case
Name | Type | Attributes | Description |
---|---|---|---|
commands | string | | The command or array of commands to look for | |
fns | Middleware | <repeatable> | The middleware(s) to register as arguments |
- Overrides
- Source
customEmoji(…args) → {Composer}
Registers some middleware(s) that will only be executed if custom_emoji
entity is present in the update
Shortcut to Composer.entity('custom_emoji', ...)
This method matches entity in channel post, message and media caption
Name | Type | Attributes | Description |
---|---|---|---|
args | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Composer
drop(predicate) → {Composer}
Registers middleware behind a custom filter function that operates on the context object and decides whether to execute the middleware.
In other words, the middleware(s) after that middleware will only be executed if the given predicate returns false
for the given context object. Note that the predicate may be asynchronous, i.e. it can return a Promise of a boolean.
This method is the same using filter
(normal usage) with a negated predicate.
// Drop all message updates sent more than 6 hr in all middlewares / handlers registered after bot.drop(...)
bot.drop(ctx => {
if(!ctx.message) return false // Drop only messages
return (Date.now() / 1000) - ctx.message.date < 60 * 60 * 6
})
// Called only for messages with date < 6 hr after send
bot.on('message', () => ctx.reply('Good, update date less then 6 hours!'))
Name | Type | Description |
---|---|---|
predicate | PredicateFn | | The predicate to check. Can be async, returns boolean or Promise with boolean |
- Overrides
- Source
- Type:
- Composer
email(…args) → {Composer}
Registers some middleware(s) that will only be executed if email
entity is present in the update
Shortcut to Composer.entity('email', ...)
This method matches entity in channel post, message and media caption
Name | Type | Attributes | Description |
---|---|---|---|
args | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Composer
entity(predicate, …fns) → {Composer}
Registers some middleware(s) that will only be executed if a certain entity is present in the update
This method matches entity in channel post, message and media caption
Name | Type | Attributes | Description |
---|---|---|---|
predicate | EntityPredicate | The predicate to check. Can be async, returns boolean or Promise with boolean | |
fns | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Composer
filter(predicate) → {Composer}
Registers middleware(s) behind a custom filter function that operates on the context object and decides whether to execute the middleware. In other words, the middleware will only be executed if the given predicate returns true
for the given context object. Otherwise, it will be skipped and the next middleware will be executed.
In other words, the middleware after that middleware will only be executed if the given predicate returns true
for the given context object. Note that the predicate may be asynchronous, i.e. it can return a Promise of a boolean.
// Only process every second update
bot.filter(ctx => ctx.update.update_id % 2 === 0)
bot.on('message', ctx => ctx.reply('Update id of this message is divided by two without a remainder'))
Name | Type | Description |
---|---|---|
predicate | PredicateFn | | The predicate to check. Can be async, returns boolean or Promise with boolean |
- Overrides
- Source
- Type:
- Composer
gameQuery(…fns) → {Composer}
Registers some middleware(s) for game queries, i.e. the updates that Telegram delivers to your bot when a user clicks an inline button for the HTML5 games platform on Telegram.
This method is essentially the same as calling
bot.on('callback_query', ctx => {
if (ctx.callbackQuery.game_short_name) {
...
}
})
Name | Type | Attributes | Description |
---|---|---|---|
fns | Middleware | <repeatable> | The middleware to register as arguments |
- Overrides
- Source
- Type:
- Composer
(async) handleUpdate(update, webhookResponseopt) → {Promise}
Starting processing one update
Name | Type | Attributes | Description |
---|---|---|---|
update | Update | Update object | |
webhookResponse | http. | <optional> | Response object for send webhook reply |
- Source
- Type:
- Promise
(async) handleUpdates(updates) → {Promise}
Starting processing array of updates
Name | Type | Description |
---|---|---|
updates | Array.<Update> | Array of updates |
- Source
Error
- Type:
- Promise
hashtag(…args) → {Composer}
Registers some middleware(s) that will only be executed if hashtag
entity is present in the update
Shortcut to Composer.entity('hashtag', ...)
This method matches entity in channel post, message and media caption
Name | Type | Attributes | Description |
---|---|---|---|
args | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Composer
hears(triggers, …fns)
Registers some middleware(s) that will only be executed when the message / channel post contains some text (in media caption too). Is it possible to pass a regular expression to match:
// Match some text (exact match)
bot.hears('I love anime', ctx => ctx.reply('I love too'))
// Match a regular expression
bot.hears(/\/echo (.+)/, ctx => ctx.reply(ctx.match[1]))
Note how
ctx.match
will contain the result of the regular expression. Soctx.match[1]
refers to the part of the regex that was matched by(.+)
, i.e. the text that comes after "/echo".
You can also paste function (or array of functions) that takes the value and context as arguments and returns true or false (or some Truthy
result) based on them. This can be used, for example, for dynamic text matching at i18n. The result returned by the function will be available from ctx.match
bot.hears(
(value, ctx) => {
//... some checks ...
return ['some', 'data']
},
ctx => ctx.reply(`I love ${ctx.match[0]} ${ctx.match[1]}`) // Replies at all with "I love some data"
)
You can pass an array of triggers. Your middleware will be executed if at least one of them matches.
Both text and captions of the received messages will be scanned. For example, when a photo is sent to the chat and its caption matches the trigger, your middleware will be executed.
If you only want to match text messages and not captions, you can do this:
const { Composer: { hears } } = require('opengram')
// Only matches text messages for the regex
bot.on('text', hears(/\/echo (.+)/, ctx => { ... }))
Be careful, the example above may not work as expected if
channelMode
is enabled.By default
text
type not match channel posts, butchannel_post
matched astext
type andctx.message
potentiallyundefined
whenchannelMode
enabled. You can add additional chat type check for this case
Name | Type | Attributes | Description |
---|---|---|---|
triggers | Trigger | | The text / array of texts / regex / function to look for | |
fns | Middleware | <repeatable> | The middleware(s) to register as argument(s) |
- Overrides
- Source
help(…fns) → {Middleware}
Registers some middleware that will only be executed when /help
command is found.
Shortcut to Composer.command('help', ...)
Name | Type | Attributes | Description |
---|---|---|---|
fns | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Middleware
inlineQuery(triggers, …fns) → {Composer}
Registers middleware for inline queries. Telegram sends an inline query to your bot whenever a user types @your_bot_name ...
into a text field in Telegram.
Your bot will then receive the entered search query and can respond with a number of results (text, images, etc.) that the user can pick from to send a message via your bot to the respective chat. Check here to read more about inline bots.
Note that you have to enable inline mode for you bot by contacting @BotFather first.
// Listen for users typing `@your_bot_name query`
bot.inlineQuery('query', async ctx => {
// Answer the inline query, confer https://core.telegram.org/bots/api#answerinlinequery
await ctx.answerInlineQuery( ... )
})
You can pass one or an array of triggers (Regexp / strings). Your middleware(s) will be executed if at least one of them matches.
Note how
ctx.match
will contain the result of the regular expression. Soctx.match[1]
refers to the part of the regexp that was matched by([0-9]+)
, i.e. the text that comes after "query:".
// Listen for users typing `@your_bot_name query`
bot.inlineQuery(/query:([0-9]+)/, async ctx => {
// Answer the inline query, confer https://core.telegram.org/bots/api#answerinlinequery
await ctx.answerInlineQuery([{
type: 'article',
id: Math.random(),
title: 'Regex test',
cache_time: 1,
description: `Query Regex result: ${ctx.match[1]}`,
input_message_content: {
message_text: `Query Regex result: ${ctx.match[1]}`,
}
}])
})
You can also paste function (or array of functions) that takes the value and context as arguments and returns true or false (or some Truthy
result) based on them. This can be used, for example, for dynamic text matching at i18n. The result returned by the function will be available from ctx.match
bot.inlineQuery(
(value, ctx) => {
//... some checks ...
return ['some', 'data']
},
// Show cb query answer for all queries with "I love some data"
ctx => ctx.answerInlineQuery([{
type: 'article',
id: Math.random(),
title: 'Regex test',
cache_time: 1,
description: `I love ${ctx.match[0]} ${ctx.match[1]}`,
input_message_content: {
message_text: `I love ${ctx.match[0]} ${ctx.match[1]}`,
}
}])
})
Name | Type | Attributes | Description |
---|---|---|---|
triggers | Trigger | | The inline query text or array of text to match | |
fns | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Composer
(async) launch(configopt) → {Promise.<Opengram>}
Launching a bot with a given config
Name | Type | Attributes | Description |
---|---|---|---|
config | LaunchConfig | <optional> | Launch configuration |
- Source
Error
- Type:
- Promise.<Opengram>
mention(…args) → {Composer}
Registers some middleware(s) that will only be executed if mention
entity is present in the update
Shortcut to Composer.entity('mention', ...)
This method matches entity in channel post, message and media caption
Name | Type | Attributes | Description |
---|---|---|---|
args | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Composer
middleware() → {Middleware}
Returns the middleware to embed
- Overrides
- Source
- Type:
- Middleware
on(updateTypes, …fns) → {Composer}
Registers some middleware(s) that will only be executed for some specific updates, namely those matching the provided filter query. Filter queries are a concise way to specify which updates you are interested in.
Here are some examples of valid filter queries:
// All kinds of message updates
bot.on('message', ctx => { ... })
// Text messages
bot.on('text', ctx => { ... })
// Messages with document
bot.on('document', ctx => { ... })
It is possible to pass multiple filter queries in an array, i.e.
// Matches all messages that contain a video or audio
bot.on(['audio', 'video'], ctx => { ... })
Your middleware will be executed if any of the provided filter queries matches (logical OR).
This method returns same as Composer#use.
Name | Type | Attributes | Description |
---|---|---|---|
updateTypes | UpdateType | | The update type or array of update types to use, may also be an array or string | |
fns | Middleware | <repeatable> | The middleware(s) to register with the given types as argument(s) |
- Overrides
- Source
- Type:
- Composer
phone(…args) → {Composer}
Registers some middleware(s) that will only be executed if phone
entity is present in the update
Shortcut to Composer.entity('phone', ...)
This method matches entity in channel post, message and media caption
Name | Type | Attributes | Description |
---|---|---|---|
args | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Composer
secretPathComponent() → {string}
Generate secret token for webhook path
Returns the same result with the same token and process.version
- Source
- 256bit hex string, not really random, based on bot token and
process.version
.
- Type:
- string
settings(…fns) → {Middleware}
Registers some middleware that will only be executed when /settings
command is found.
Shortcut to Composer.command('settings', ...)
Name | Type | Attributes | Description |
---|---|---|---|
fns | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Middleware
spoiler(…args) → {Composer}
Registers some middleware(s) that will only be executed if spoiler
entity is present in the update
Shortcut to Composer.entity('spoiler', ...)
This method matches entity in channel post, message and media caption
Name | Type | Attributes | Description |
---|---|---|---|
args | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Composer
start(…fns) → {Middleware}
Registers some middleware that will only be executed when /start
command is found.
Shortcut to Composer.command('start', ...)
, but with additional functionally, when you use this and deep linking, you can get start payload from ctx.startPayload
For example if user start the bot from link like this: http://t.me/examplebot?start=1234
With this code, bot reply user with text of start payload:
bot.start(ctx => ctx.reply(`Start payload: ${ctx.startPayload}`)) // Reply with "Start payload: 1234"
Name | Type | Attributes | Description |
---|---|---|---|
fns | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Middleware
startPolling(timeoutopt, limitopt, allowedUpdatesopt, stopCallbackopt) → {Opengram}
Starts long polling and updates processing with given configuration
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
timeout | number | <optional> | 30 | Timeout in seconds for long polling. Defaults to 30 |
limit | number | <optional> | 100 | Limits the number of updates to be retrieved. Values between 1-100 are accepted. Defaults to 100. |
allowedUpdates | UpdateType | | <optional> | Array of allowed updates or update name For example, specify | |
stopCallback | function | <optional> | Function called when bot fully stopped. If you call |
- Source
- Type:
- Opengram
startWebhook(optionsopt, tlsOptionsopt, portopt, hostopt, nextCbopt) → {Opengram}
Start webhook server based on NodeJS http or https modules on given host, port
const { Opengram } = require('opengram')
const fs = require('fs')
const bot = new Opengram(process.env.BOT_TOKEN)
bot.hears('hello', => ctx.reply('hi'))
bot.catch(console.log) // Setup error handler
// TLS options
const tlsOptions = {
key: fs.readFileSync('server-key.pem'), // Private key file
cert: fs.readFileSync('server-cert.pem') // Certificate file,
ca: [
// This is necessary only if the client uses a self-signed certificate.
fs.readFileSync('client-cert.pem')
]
}
// Start webhook server
bot.startWebhook(
{
path: '/bot',
secret: '1234567890'
},
tlsOptions,
3000 // Port
'0.0.0.0', // Host, may use if server have multiple IP adders
(req, res) => { // Custom next handler
res.statusCode = 403
res.end('Not allowed!')
}
)
// Set telegram webhook
// The second argument is necessary only if the client uses a self-signed
// certificate. Including it for a verified certificate may cause things to break.
bot.telegram.setWebhook('https://example.com:3000/bot', {
source: 'server-cert.pem'
})
Name | Type | Attributes | Description |
---|---|---|---|
options | StartWebhookOptions | <optional> | Webhook options |
tlsOptions | object | | <optional> | Options for |
port | number | <optional> | Port to listen. Be careful, Telegram only supports 443, 80, 88, 8443 for now. |
host | string | | <optional> | If host is omitted, the server will accept connections on the unspecified IPv6 address (::) when IPv6 is available, or the unspecified IPv4 address (0.0.0.0) otherwise. |
nextCb | function | <optional> | Next handler function, called when webhook handler not match path string or request method. May have two arguments - |
- Source
- Type:
- Opengram
(async) stop(cbopt) → {Promise.<void>}
Stopping the bot. For webhook, it will close the server, for long polling stop getting updates
Name | Type | Attributes | Description |
---|---|---|---|
cb | function | <optional> | Callback function, which called when bot fully stopped |
- Source
- Type:
- Promise.<void>
textLink(…args) → {Composer}
Registers some middleware(s) that will only be executed if text_link
entity is present in the update
Shortcut to Composer.entity('text_link', ...)
This method matches entity in channel post, message and media caption
Name | Type | Attributes | Description |
---|---|---|---|
args | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Composer
textMention(…args) → {Composer}
Registers some middleware(s) that will only be executed if text_mention
entity is present in the update
Shortcut to Composer.entity('text_mention', ...)
This method matches entity in channel post, message and media caption
Name | Type | Attributes | Description |
---|---|---|---|
args | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Composer
url(…args) → {Composer}
Registers some middleware(s) that will only be executed if url
entity is present in the update
Shortcut to Composer.entity('url', ...)
This method matches entity in channel post, message and media caption
Name | Type | Attributes | Description |
---|---|---|---|
args | Middleware | <repeatable> | The middleware(s) to register |
- Overrides
- Source
- Type:
- Composer
use(…fns) → {Composer}
Registers some middleware(s) that receives all updates. It is installed by concatenating it to the end of all previously installed middleware.
Often, this method is used to install middleware(s) that behaves like a plugin, for example session middleware.
bot.use(session())
You can pass middleware separated by commas as arguments or as a chain of calls:
const { Opengram, Stage, session } = require('opengram')
const bot = require('opengram')
const stage = new Stage([...])
bot.use(session(), stage) // As arguments
or
const { Opengram, Stage, session } = require('opengram')
const bot = require('opengram')
const stage = new Stage([...])
bot // As chain of calls
.use(session())
.use(stage)
This method returns a new instance of Composer.
Name | Type | Attributes | Description |
---|---|---|---|
fns | Middleware | <repeatable> | The middleware(s) to register as arguments |
- Overrides
- Source
- Type:
- Composer
webhookCallback(config) → {function}
Generates webhook handler middleware for specified path for Koa / Express / Fastify / NodeJS http or https modules
Using example for express:
const { Opengram } = require('opengram')
const express = require('express')
const app = express()
const bot = new Opengram(process.env.BOT_TOKEN)
// Set the bot response
bot.on('text', ({ replyWithHTML }) => replyWithHTML('<b>Hello</b>'))
// Set telegram webhook
bot.telegram.setWebhook('https://exmaple.com/secret-path')
app.get('/', (req, res) => res.send('Hello World!'))
// Set the bot API endpoint
app.use(bot.webhookCallback('/secret-path'))
app.listen(3000, () => console.log('Bot listening on port 3000!'))
Name | Type | Description |
---|---|---|
config | WebhookCallbackOptions | Options |
- Source
- Type:
- function