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
- High stability;
- Low memory usage;
- Maximum performance;
- Flexibility.
- Start
- Proxy
- Polling
- HTTP
- Virtual
- mServer
- Nginx + Node.js
- Response Builder
- Tg Upload
- Plugin
- Goto
- JS Generators
- Render
- Keyboard
- Download
- InlineQuery
- Send file as Buffer
- CLI
- Test
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));
// e - Error: request/JSON.parse/response.ok
// data - JSON: response.result or null
//-------]>
gBot.callJson("sendMessage", ["0", "Hi"], (e, data, res) => console.log(e || data));
// e - Error: request/JSON.parse
// data - JSON: response or null
// res - Class: http.IncomingMessage or null
//-------]>
gBot.call("sendMessage", ["0", "Hi"], (e, data, res) => console.log(e || data));
// e - Error: request
// data - Buffer: response or null
// res - Class: http.IncomingMessage or null
//------------]>
/*
e.code - gApi.sendMessage( ...
data.error_code - callJson("sendMessage" ...
rTgBot or gBot
gBot.ERR_INTERNAL_SERVER
gBot.ERR_NOT_FOUND
gBot.ERR_FORBIDDEN
gBot.ERR_MESSAGE_LIMITS
gBot.ERR_USED_WEBHOOK
gBot.ERR_INVALID_TOKEN
gBot.ERR_BAD_REQUEST
gBot.ERR_BAD_PROXY
gBot.ERR_FAILED_PARSE_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(); } // <-- Async
function onCmdStart_2(bot, params) { } // <-- Sync
function onCmdStart_3(bot, params) { } // <-- Sync | end
function onEnterChat(bot, member) { }
function onText(bot, text) { }
function onPhotoOrDoc(bot, data) { }
function onPinnedMessage(bot, message) { }
function onTextRegEx(bot, data) { }
//-----------]>
/*
bot | gBot -> Sugar -> CtxPerRequest
bot instanceof gBot.constructor | true
bot.command.type | common or private
/start [text] -> common
/start@bot [text] -> private
@bot /start [text] -> private
*/
const gBot = rBot(process.env.TELEGRAM_BOT_TOKEN);
const gProxyStr = "127.0.0.1:1337", // <-- Only HTTPS
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(); // <-- Remove
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);
const gBot = rBot(process.env.TELEGRAM_BOT_TOKEN);
const gOptions = {
"limit": 100,
"timeout": 0,
"interval": 2 // <-- Default / Sec.
};
//------------------]>
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();
}
const rBot = require("telegram-bot-api-c");
//-----------------------------------------------------
const gSrvOptions = {
// For Self-signed certificate, you need to upload your public key certificate
// "selfSigned": "fullPath/stream/buffer", // <-- If you use Auto-Webhook
"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) // <-- Auto-Webhook: "/tg_bot_<sha256(token)>"
.on("/start", onCmdStart)
.on("/stop", onCmdStop);
gSrv
.bot(gOtherBot, "/urlOtherBot", onMsgOtherBot); // <-- Auto-Webhook
//------------------]>
function onMsgOtherBot(bot) { }
function onCmdStart(bot, params) { }
function onCmdStop(bot, params) { }
const gBot = rBot(process.env.TELEGRAM_BOT_TOKEN);
const gSrv = gBot
.virtual(function(bot) {
bot.answer().text("Not found!").send();
})
.on("photo", console.log);
//----[Proxy: express]----}>
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");
});
//----[Stress Tests]----}>
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"
}
});
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);
});
const gBot = rBot();
const gSrvOptions = {
"ssl": false,
"autoWebhook": "site.xx:88", // <-- Default: (host + port); `false` - disable
"host": "localhost",
"port": 1490
};
gBot.http(gSrvOptions, onMsg);
//----[DEFAULT]----}>
gBot.http();
gBot.http(onMsg);
// host: localhost
// port: 1488
// autoWebhook: false
// ssl: false
objSrv
.use(function(bot) {
bot
.answer() // <-- Builder + Queue
.chatAction("typing") // <-- Element
.text("https://google.com", "markdown") // <-- Element
//.parseMode("markdown")
.disableWebPagePreview() // <-- Modifier (for the last element)
.keyboard([["X"], ["Y"]]) // <-- Modifier
.markdown("*text*") // <-- Element
.html("<a>text</a>")
.chatAction("upload_photo")
.photo("https://www.google.ru/images/logos/ps_logo2.png", "myCaption")
.caption("#2EASY") // <-- Modifier
.keyboard("old")
.keyboard("new", "selective") // <-- Uses: bot.mid (selective)
.location(69, 96)
.latitude(13)
.keyboard() // <-- Hide
.send() // <-- Uses: bot.cid
.then(console.log); // <-- Return: array | results
//------[ONE ELEMENT]------}>
const customKb = {
"keyboard": [["1"], ["2"], ["3"]],
"resize_keyboard": true
};
bot
.answer()
.text("Hi")
.keyboard(customKb)
.send((e, r) => console.log(e || r)); // <-- Return: hashTable | result
//------[RENDER]------}>
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) // <-- text + keyboard
.send();
bot
.answer()
.text("Msg: {0} + {1}")
.render(["H", "i"]) // <-- text
.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 |
gBot.enable("tgUrlUpload");
gBot
.polling()
.on("text", function(bot, url) {
bot.answer().photo(url).send();
});
/*
Added the option to specify an HTTP URL for a file in all methods where InputFile or file_id can be used (except voice messages).
Telegram will get the file from the specified URL and send it to the user.
Files must be smaller than 5 MB for photos and smaller than 20 MB for all other types of content.
*/
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;
});
gSrv
.use(function(bot, data, next) {
next(data === "room" ? "room.menu" : "");
})
.use(function(bot) {
console.log("If not the room");
// return "room.menu";
})
.on("text", function(bot, data) { })
.on("text:room.menu", function(bot, data) { });
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();
}
//-----[EJS]-----}>
gBot.engine(require("ejs"))
data = {"x": "H", "y": "i"};
bot.render("EJS | Text: <%= x %> + <%= y %>", data);
//-----[DEFAULT]-----}>
data = ["H", "i"];
bot.render("Array | Text: {0} + {1}", data);
data = {"x": "H", "y": "i"};
bot.render("Hashtable | Text: {x} + {y}", data);
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(); // Or: bot.keyboard.hide()
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); // <-- Once
rBot.keyboard.numpad(false, true); // <-- Selective
rBot.keyboard.inline.numpad();
//------------------------------
rBot.keyboard(buttons[, params])
rBot.keyboard.inline(inlButtons, isVertically)
/*
buttons: `string`, `array of array` or `false`
inlButtons: `string`, `array of array` or `object`
params: "resize once selective"
v - vertically; h - horizontally;
vOx, hOx, vPn, hPn, vLr, hLr, vGb, hGb
abcd, numpad, hide
Normal keyboard:
vOx(once, selective)
numpad(once, selective)
*/
Name | Note |
---|---|
- | |
_Ox | O / X |
_Pn | + / - |
_Ud | Upwards / Downwards arrow |
_Lr | Leftwards / Rightwards arrow |
_Gb | Like / Dislike |
- | |
abcd | ABCD |
numpad | 0-9 |
- | |
hide |
gBot.download("file_id", "dir"/*, callback*/);
gBot.download("file_id", "dir", "name.mp3"/*, callback*/);
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"));
});
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; });
// results = {results};
bot
.answer()
.inlineQuery(results)
.send()
.then(console.info, console.error);
});
//------------]>
bot
.api
.answerInlineQuery({
"inline_query_id": 0,
"results": results
})
.then(console.info, console.error);
const imgBuffer = require("fs").readFileSync(__dirname + "/MiElPotato.jpg");
//------------]>
objSrv
.use(function(bot, next) {
bot
.answer()
.photo(imgBuffer)
.filename("MiElPotato.jpg") // <-- It is important
.filename("/path/MiElPotato.jpg") // <-- Same as above
.send();
});
//------------]>
api.sendPhoto({
"chat_id": 0,
"photo": imgBuffer,
"filename": "MiElPotato.jpg" // <-- It is important
});
api.sendDocument({
"chat_id": 0,
"document": imgBuffer
});
Key | Note |
---|---|
- | |
-j | insert white space into the output JSON string for readability purposes |
- | |
--token | high priority |
--method | high priority |
--proxy | "ip:port" |
// Environment variables: low priority
> 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)
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
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] |
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 |
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 |
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 |
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 |
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] |
MIT