
npm -g install telegram-bot-api-c
git clone https://github.com/Daeren/telegram-bot-api-c.git
require("telegram-bot-api-c").call("TK", "sendMessage", [0, "+"])
require("telegram-bot-api-c")("TK").api.sendMessage({chat_id: 0, text: "+"})
require("telegram-bot-api-c")("TK").polling(bot => bot.answer().html("+").send())
> tg-bot --token TK --method sendMessage --chat_id 0 --text "+"
Telegram Bot API, Bot API 2.x, Bot API 3.5
- Proxy: +
- Array and Map as a data source (.call, .callJson, .api[method]): +
- Analytics: tgb-pl-botanio
- Added: tgBot.api[sendMethod] => error.retryAfter
- Added: sendMediaGroup (doesn't support "attach://")
- All methods in the Bot API are case-insensitive (method: .call, .callJson)
- message: buffer, stream, string
- location|venue|contact: buffer, string
- photo|audio|voice|video|document|sticker|video_note: buffer, stream, file_id, path, url
- certificate: buffer, stream, path, url
Goals:
- High stability;
- Low memory usage;
- Maximum performance;
- Flexibility.
Index

const rTgBot = require("telegram-bot-api-c");
const gBot = rTgBot(process.env.TELEGRAM_BOT_TOKEN),
gApi = gBot.api;
gBot.promise(require("bluebird"));
gApi
.sendMessage(["0", "Hi"])
.then(console.info, console.error);
gApi.sendMessage(["0", "Hi"], (e, data) => console.log(e || data));
gBot.callJson("sendMessage", ["0", "Hi"], (e, data, res) => console.log(e || data));
gBot.call("sendMessage", ["0", "Hi"], (e, data, res) => console.log(e || data));
gBot
.polling(onDefault)
.catch(onError)
.use(bot => "syncGotoMyMenu")
.use((bot, data, next) => next(new Error("never get")))
.use("/start", bot => { })
.on("/start", onCmdStart_1)
.on("/start", onCmdStart_2)
.on("/start", onCmdStart_3)
.on("enterChat", onEnterChat)
.on("text:syncGotoMyMenu", onText)
.on("photo document", onPhotoOrDoc)
.on("pinnedMessage", onPinnedMessage)
.on(/^id\s+(\d+)/i, onTextRegEx)
.on(/^(id)\s+(\d+)/i, "type id", onTextRegEx)
.on(/^(login)\s+(\w+)/i, ["type", "login"], onTextRegEx);
function onDefault(bot) { }
function onError(error) { }
function onCmdStart_1(bot, params, next) { next(); }
function onCmdStart_2(bot, params) { }
function onCmdStart_3(bot, params) { }
function onEnterChat(bot, member) { }
function onText(bot, text) { }
function onPhotoOrDoc(bot, data) { }
function onPinnedMessage(bot, message) { }
function onTextRegEx(bot, data) { }
Proxy
const gBot = rBot(process.env.TELEGRAM_BOT_TOKEN);
const gProxyStr = "127.0.0.1:1337",
gProxyArr = ["127.0.0.1", "1337"],
gProxyObj = {
"host": "127.0.0.1",
"port": 1337
};
function getMe(callback) { gBot.api.getMe(callback); }
gBot.proxy(gProxyObj);
getMe(t => {
objBot.proxy(gProxyStr);
getMe(t => {
objBot.proxy();
getMe();
});
});
rBot.callJson({
"token": process.env.TELEGRAM_BOT_TOKEN,
"method": "getMe",
"proxy": gProxyArr
}, (e, d) => {});
rBot.callJson(process.env.TELEGRAM_BOT_TOKEN, "getMe", (e, d) => {}, gProxyObj);
Polling
const gBot = rBot(process.env.TELEGRAM_BOT_TOKEN);
const gOptions = {
"limit": 100,
"timeout": 0,
"interval": 2
};
const gSrv = gBot
.polling(gOptions, onMsg)
.on("/stop", onCmdStop);
function onMsg(bot) {
const msg = bot.isGroup && bot.isReply ? ">_>" : "Stop me: /stop";
bot.answer().isReply().text(msg).send();
}
function onCmdStop(bot, params) {
gSrv.stop();
bot.answer().text(JSON.stringify(params)).send();
}
HTTP
const rBot = require("telegram-bot-api-c");
const gSrvOptions = {
"certDir": "/www/site",
"key": "/3_site.xx.key",
"cert": "/2_site.xx.crt",
"ca": [
"/AddTrustExternalCARoot.crt",
"/COMODORSAAddTrustCA.crt",
"/COMODORSADomainValidationSecureServerCA.crt"
],
"host": "site.xx"
};
const gBotFather = rBot();
const gMyBot = rBot(process.env.TG_BOT_TOKEN_MY),
gOtherBot = rBot(process.env.TG_BOT_TOKEN_OTHER);
const gSrv = gBotFather.http(gSrvOptions);
gSrv
.bot(gMyBot)
.on("/start", onCmdStart)
.on("/stop", onCmdStop);
gSrv
.bot(gOtherBot, "/urlOtherBot", onMsgOtherBot);
function onMsgOtherBot(bot) { }
function onCmdStart(bot, params) { }
function onCmdStop(bot, params) { }
Virtual
const gBot = rBot(process.env.TELEGRAM_BOT_TOKEN);
const gSrv = gBot
.virtual(function(bot) {
bot.answer().text("Not found!").send();
})
.on("photo", console.log);
gBot
.api
.setWebhook({"url": "https://site.xx/dev-bot"})
.then(function(isOk) {
const rExpress = require("express"),
rBodyParser = require("body-parser");
rExpress()
.use(rBodyParser.json())
.post("/dev-bot", gSrv.middleware)
.listen(3000, "localhost");
});
gSrv.input(null, {
"update_id": 0,
"message": {
"message_id": 0,
"from": {
"id": 0,
"first_name": "D",
"username": ""
},
"chat": {
"id": 0,
"first_name": "D",
"username": "",
"type": "private"
},
"date": 0,
"text": "Hello"
}
});
mServer
const gBot = rBot(process.env.TELEGRAM_BOT_TOKEN);
gBot
.api
.setWebhook({"url": "https://site.xx/myBot"})
.then(function(isOk) {
if(!isOk) {
throw new Error("Oops...problem with the webhook...");
}
gBot.http(gSrvOptions, cbMsg);
});
NGINX + Node.js
const gBot = rBot();
const gSrvOptions = {
"ssl": false,
"autoWebhook": "site.xx:88",
"host": "localhost",
"port": 1490
};
gBot.http(gSrvOptions, onMsg);
gBot.http();
gBot.http(onMsg);
Response Builder
objSrv
.use(function(bot) {
bot
.answer()
.chatAction("typing")
.text("https://google.com", "markdown")
.disableWebPagePreview()
.keyboard([["X"], ["Y"]])
.markdown("*text*")
.html("<a>text</a>")
.chatAction("upload_photo")
.photo("https://www.google.ru/images/logos/ps_logo2.png", "myCaption")
.caption("#2EASY")
.keyboard("old")
.keyboard("new", "selective")
.location(69, 96)
.latitude(13)
.keyboard()
.send()
.then(console.log);
const customKb = {
"keyboard": [["1"], ["2"], ["3"]],
"resize_keyboard": true
};
bot
.answer()
.text("Hi")
.keyboard(customKb)
.send((e, r) => console.log(e || r));
const template = "Hi, {name}!";
const buttons = [["{btnMenu}", "{btnOptions}"]];
const input = {
"name": "MiElPotato",
"btnMenu": "Menu +",
"btnOptions": "Options"
};
bot
.answer()
.text(template)
.keyboard(buttons, "resize")
.render(input)
.send();
bot
.answer()
.text("Msg: {0} + {1}")
.render(["H", "i"])
.keyboard([["X: {0}", "Y: {1}"]])
.send();
});
Name |
Args |
|
- |
html |
text, disable_web_page_preview, disable_notification, reply_to_message_id, reply_markup |
markdown |
text, disable_web_page_preview, disable_notification, reply_to_message_id, reply_markup |
|
- |
text |
text, parse_mode, disable_web_page_preview, disable_notification, reply_to_message_id, reply_markup |
photo |
photo, caption, disable_notification, reply_to_message_id, reply_markup |
audio |
audio, performer, title, duration, caption, disable_notification, reply_to_message_id, reply_markup |
document |
document, caption, disable_notification, reply_to_message_id, reply_markup |
sticker |
sticker, disable_notification, reply_to_message_id, reply_markup |
video |
video, width, height, duration, caption, disable_notification, reply_to_message_id, reply_markup |
voice |
voice, duration, caption, disable_notification, reply_to_message_id, reply_markup |
videoNote |
videoNote, duration, length, disable_notification, reply_to_message_id, reply_markup |
location |
latitude, longitude, disable_notification, reply_to_message_id, reply_markup |
venue |
latitude, longitude, title, address, foursquare_id, disable_notification, reply_to_message_id, reply_markup |
contact |
phone_number, first_name, last_name, disable_notification, reply_to_message_id, reply_markup |
chatAction |
action |
game |
game_short_name, disable_notification, reply_to_message_id, reply_markup |
invoice |
title ... ... reply_markup |
|
- |
inlineQuery |
results, next_offset, is_personal, cache_time, switch_pm_text, switch_pm_parameter |
callbackQuery |
text, show_alert |
shippingQuery |
ok, shipping_options, error_message |
preCheckoutQuery |
ok, error_message |
Tg Upload
gBot.enable("tgUrlUpload");
gBot
.polling()
.on("text", function(bot, url) {
bot.answer().photo(url).send();
});
Plugin
gSrv
.use(function(bot, data, next) {
console.log("Async | Type: any");
if(data === "next") {
next();
}
})
.use("text", function(bot) {
console.log("F:Sync | Type: text");
bot.user = {};
})
.use(function(bot) {
bot.user.id = 1;
});
gSrv
.on("text", function(bot, data) {
bot.user.id;
});
Goto
gSrv
.use(function(bot, data, next) {
next(data === "room" ? "room.menu" : "");
})
.use(function(bot) {
console.log("If not the room");
})
.on("text", function(bot, data) { })
.on("text:room.menu", function(bot, data) { });
JS Generators
gBot
.polling(function* (bot) {
const result = yield send(bot);
console.info(result);
yield error();
})
.catch(function* (error) {
console.error(error);
})
.use(function* (bot) {
yield auth("D", "13");
})
.use("text", function* (bot, data) {
yield save();
if(data === "key") {
return "eventYield";
}
})
.on("text:eventYield", function* (bot, data) {
console.log("eventYield:", data);
});
function auth(login, password) {
return new Promise(x => setTimeout(x, 1000));
}
function send(bot) {
return bot.answer().text("Ok, let's go...").send();
}
Render
gBot.engine(require("ejs"))
data = {"x": "H", "y": "i"};
bot.render("EJS | Text: <%= x %> + <%= y %>", data);
data = ["H", "i"];
bot.render("Array | Text: {0} + {1}", data);
data = {"x": "H", "y": "i"};
bot.render("Hashtable | Text: {x} + {y}", data);
Keyboard
const rBot = require("telegram-bot-api-c");
function onMsg(bot) {
const data = {};
data.chat_id = bot.cid;
data.text = "Hell Word!";
data.reply_markup = bot.keyboard();
data.reply_markup = bot.keyboard([["1", "2"], ["3"]]);
data.reply_markup = bot.keyboard.hOx();
data.reply_markup = bot.keyboard.inline.hOx();
bot.api.sendMessage(data);
}
rBot.keyboard.numpad(true);
rBot.keyboard.numpad(false, true);
rBot.keyboard.inline.numpad();
rBot.keyboard(buttons[, params])
rBot.keyboard.inline(inlButtons, isVertically)
Name |
Note |
|
- |
_Ox |
O / X |
_Pn |
+ / - |
_Ud |
Upwards / Downwards arrow |
_Lr |
Leftwards / Rightwards arrow |
_Gb |
Like / Dislike |
|
- |
abcd |
ABCD |
numpad |
0-9 |
|
- |
hide |
|
Download
gBot.download("file_id", "dir");
gBot.download("file_id", "dir", "name.mp3");
gBot
.download("file_id")
.then(function(info) {
info.stream.pipe(require("fs").createWriteStream("./" + info.name));
});
gBot
.download("file_id", function(error, info) {
info.stream.pipe(require("fs").createWriteStream("./myFile"));
});
InlineQuery
https://core.telegram.org/bots/inline
gBot
.polling()
.on("inlineQuery", function(bot, data) {
const idx = Date.now().toString(32) + Math.random().toString(24);
const results = [
{
"type": "article",
"title": "Title #1",
"message_text": "Text...",
"thumb_url": "https://pp.vk.me/c627530/v627530230/2fce2/PF9loxF4ick.jpg"
},
{
"type": "article",
"title": "Title #2: " + data.query,
"message_text": "Text...yeah"
},
{
"type": "photo",
"photo_width": 128,
"photo_height": 128,
"photo_url": "https://pp.vk.me/c627530/v627530230/2fce2/PF9loxF4ick.jpg",
"thumb_url": "https://pp.vk.me/c627530/v627530230/2fce2/PF9loxF4ick.jpg"
}
]
.map((t, i) => { t.id = idx + i; return t; });
bot
.answer()
.inlineQuery(results)
.send()
.then(console.info, console.error);
});
bot
.api
.answerInlineQuery({
"inline_query_id": 0,
"results": results
})
.then(console.info, console.error);
Send file as Buffer
const imgBuffer = require("fs").readFileSync(__dirname + "/MiElPotato.jpg");
objSrv
.use(function(bot, next) {
bot
.answer()
.photo(imgBuffer)
.filename("MiElPotato.jpg")
.filename("/path/MiElPotato.jpg")
.send();
});
api.sendPhoto({
"chat_id": 0,
"photo": imgBuffer,
"filename": "MiElPotato.jpg"
});
api.sendDocument({
"chat_id": 0,
"document": imgBuffer
});
CLI
Key |
Note |
|
- |
-j |
insert white space into the output JSON string for readability purposes |
|
- |
--token |
high priority |
--method |
high priority |
--proxy |
"ip:port" |
> set TELEGRAM_BOT_TOKEN=X
> set TELEGRAM_BOT_METHOD=X
> set TELEGRAM_BOT_PROXY=X
...
> tg-bot --token X --method sendMessage --key val -bool
> node telegram-bot-api-c --token X --method sendMessage --key val -bool
...
> tg-bot --token X --method sendMessage --chat_id 0 --text "Hi" -disable_web_page_preview
> tg-bot --token X --method sendMessage < "./examples/msg.json"
> tg-bot --token X --method sendPhoto --chat_id 0 --photo "/path/MiElPotato.jpg"
> tg-bot --token X --method sendPhoto --chat_id 0 --photo "https://www.google.ru/images/logos/ps_logo2.png"
...
> tg-bot
> {"token": "", "method": "sendMessage", "chat_id": 0, "text": "1"}
> <enter>
(result)
> {"chat_id": 0, "text": "2", "j": true, "proxy": "ip:port"}
> <enter>
(result)
Test
npm -g install mocha
npm install chai
set TELEGRAM_BOT_TOKEN=X
set TELEGRAM_CHAT_ID=X
set TELEGRAM_MSG_ID=X
cd <module>
npm test

Module
Method |
Arguments |
Note |
|
- |
|
keyboard |
buttons[, params] |
return: object; buttons: string/array; params: "resize once selective" |
parseCmd |
text[, strict] |
return: {type, name, text, cmd}; strict: maxLen32 + alphanum + underscore |
|
- |
|
call |
token, method[, data][, callback(error, buffer, response)][, proxy][, tgUrlUpload] |
|
call |
options{token, method, proxy, tgUrlUpload}[, data][, callback] |
|
callJson |
token, method[, data][, callback(error, json, response)][, proxy][, tgUrlUpload] |
|
callJson |
options{token, method, proxy, tgUrlUpload}[, data][, callback] |
|
Instance
Attribute |
Type |
Note |
|
- |
|
api |
object |
See Telegram Bot API |
|
- |
|
keyboard |
function |
|
parseCmd |
function |
|
Method |
Arguments |
Return |
|
- |
|
|
- |
|
enable |
key |
this |
disable |
key |
this |
enabled |
key |
true/false |
disabled |
key |
true/false |
|
- |
|
engine |
instance |
this |
promise |
instance |
this |
token |
[token] |
this or token |
proxy |
[proxy] |
this |
|
- |
|
call |
method[, data][, callback(error, buffer, response)] |
|
callJson |
method[, data][, callback(error, json, response)] |
|
|
- |
|
render |
template, data |
string |
download |
fid[, dir][, name][, callback(error, info {id,size,file,stream})] |
promise or undefined |
|
- |
|
http |
[options][, callback(bot, cmd)] |
object |
polling |
[options][, callback(bot, cmd)] |
object |
virtual |
[callback(bot, cmd)] |
object |
Methods: Response Builder
Name |
Args |
Note |
|
- |
|
inlineQuery |
(results) |
|
callbackQuery |
([message]) |
|
|
- |
|
render |
(data) |
|
keyboard |
(buttons[, params]) |
|
inlineKeyboard |
(buttons[, isVertically]) |
|
|
- |
|
isReply |
([flag]) |
|
send |
([callback]) |
|
|
- |
|
text |
|
|
photo |
|
Ext: jpg, jpeg, gif, tif, png, bmp |
audio |
|
Ext: mp3 |
document |
|
|
sticker |
|
Ext: webp [, jpg, jpeg, gif, tif, png, bmp] |
video |
|
Ext: mp4 |
voice |
|
Ext: ogg |
location |
|
|
venue |
|
|
contact |
|
|
chatAction |
|
|
game |
|
|
Methods: Server
Name |
Arguments |
Return |
|
- |
|
|
POLLING |
|
|
- |
|
start |
|
this |
stop |
|
this |
|
HTTP |
|
|
- |
|
bot |
bot[, path][, onMsg(json, request)] |
new srvInstance |
|
- |
|
|
VIRTUAL |
|
|
- |
|
input |
error, data |
|
middleware |
|
|
|
- |
|
|
ALL |
|
|
- |
|
catch |
callback(error) |
this |
use |
[type], [params], callback(bot[, data, next]) |
this |
on |
type[, params], callback(data, params[, next]) |
this |
off |
[type][, callback] |
this |
Fields: bot | srv.on('', bot => 0)
Name |
Type |
Note |
|
- |
|
isGroup |
boolean |
bot.isGroup = bot.message.chat.type === [super]group |
isReply |
boolean |
bot.isReply = !!bot.message.reply_to_message |
|
- |
|
cid |
number |
bot.cid = bot.message.chat.id |
mid |
number |
bot.mid = bot.message.message_id |
qid |
string |
bot.qid = bot.inlineQuery.id |
cqid |
string |
bot.cqid = bot.callbackQuery.id |
sid |
string |
bot.sid = bot.shipping_query.id |
pqid |
string |
bot.pqid = bot.pre_checkout_query.id |
|
- |
|
command |
object |
Incoming command |
|
- |
|
updateType |
string |
|
updateSubType |
string |
|
eventType |
string |
|
eventSubType |
string |
|
gotoState |
string |
|
|
- |
|
from |
object |
Persistent |
|
- |
|
message |
object |
Incoming message |
inlineQuery |
object |
Incoming inline query |
chosenInlineResult |
object |
The result of an inline query that was chosen |
callbackQuery |
object |
Incoming callback query |
|
- |
|
answer |
function() |
Response Builder; message; Uses: cid, mid |
answer |
function() |
Response Builder; inlineQuery; Uses: qid |
answer |
function() |
Response Builder; callbackQuery; Uses: cqid |
Events: use / on
Name |
Args |
Note |
|
- |
|
message |
bot, message[, next] |
|
editedMessage |
bot, message[, next] |
|
|
- |
|
channelPost |
bot, post[, next] |
|
editedChannelPost |
bot, post[, next] |
|
|
- |
|
inlineQuery |
bot, data[, next] |
|
chosenInlineResult |
bot, data[, next] |
|
callbackQuery |
bot, data[, next] |
|
|
- |
|
pinnedMessage |
bot, message[, next] |
|
|
- |
|
invoice |
bot, data[, next] |
|
successfulPayment |
bot, data[, next] |
|
|
- |
|
enterChat |
bot, data[, next] |
|
leftChat |
bot, data[, next] |
|
|
- |
|
chatTitle |
bot, data[, next] |
|
chatNewPhoto |
bot, data[, next] |
|
chatDeletePhoto |
bot, data[, next] |
|
|
- |
|
chatCreated |
bot, data[, next] |
|
superChatCreated |
bot, data[, next] |
|
channelChatCreated |
bot, data[, next] |
|
|
- |
|
migrateToChatId |
bot, data[, next] |
|
migrateFromChatId |
bot, data[, next] |
|
|
- |
|
text |
bot, data[, next] |
|
photo |
bot, data[, next] |
|
audio |
bot, data[, next] |
|
document |
bot, data[, next] |
|
sticker |
bot, data[, next] |
|
video |
bot, data[, next] |
|
voice |
bot, data[, next] |
|
videoNote |
bot, data[, next] |
|
location |
bot, data[, next] |
|
venue |
bot, data[, next] |
|
contact |
bot, data[, next] |
|
game |
bot, data[, next] |
|
|
- |
|
* |
bot, data[, next] |
|
/[name] |
bot, params[, next] |
CMD |
|
- |
|
(regexp) |
bot, params[, next] |
|
License
MIT
@ Daeren
@ Telegram