!Codacycodbcodl !NodeSecuritynodesecb
```
npm -g install telegram-bot-api-c
git clone https://github.com/Daeren/telegram-bot-api-c.git
```
```js
require("telegram-bot-api-c").call("TK", "sendMessage", 0, "+")
```
```js
require("telegram-bot-api-c")("TK").api.sendMessage({chatid: 0, text: "+"})
```
```js
require("telegram-bot-api-c")("TK").polling(bot => bot.answer().html("+").send())
```
```js
tg-bot --token TK --method sendMessage --chatid 0 --text "+"``` Telegram Bot API3, Bot API 2.x100, Bot API 3.5
- Proxy: +
- Analytics: tgb-pl-botanio4
- Added: tgBot.apisendMethod => error.retryAfter
- Added: sendMediaGroup150 (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|videonote: buffer, stream, fileid, path, url
- certificate: buffer, stream, path, url
Goals:
- High stability;
- Low memory usage;
- Maximum performance;
- Flexibility.
Index
!architectureimage-architecture ```js const rTgBot = require("telegram-bot-api-c"); const gBot = rTgBot(process.env.TELEGRAMBOTTOKEN),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.errorcode - callJson("sendMessage" ...
rTgBot or gBot
gBot.ERRINTERNALSERVER
gBot.ERRNOTFOUND
gBot.ERRFORBIDDEN
gBot.ERRMESSAGELIMITS
gBot.ERRUSEDWEBHOOK
gBot.ERRINVALIDTOKEN
gBot.ERRBADREQUEST
gBot.ERRBADPROXY
gBot.ERRFAILEDPARSEDATA
/
//---------------------------->
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 onCmdStart1(bot, params, next) { next(); } // <-- Async
function onCmdStart2(bot, params) { } // <-- Sync
function onCmdStart3(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
/
```
Proxy
```js const gBot = rBot(process.env.TELEGRAMBOTTOKEN); const gProxyStr = "127.0.0.1:1337", // <-- Only HTTPSgProxyArr = ["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.TELEGRAMBOTTOKEN, "getMe", (e, d) => {}, gProxyObj);
```
Polling
```js const gBot = rBot(process.env.TELEGRAMBOTTOKEN); 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();
}
```
HTTP
```js 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.TGBOTTOKENMY),
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) { }
```
Virtual
```js const gBot = rBot(process.env.TELEGRAMBOTTOKEN); 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"
}
});
```
mServer
```js const gBot = rBot(process.env.TELEGRAMBOTTOKEN); 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
```js 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
```
Response Builder
```js 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, disablewebpagepreview, disablenotification, replytomessageid, replymarkup |
| markdown | text, disablewebpagepreview, disablenotification, replytomessageid, replymarkup |
| | - |
| text | text, parsemode, disablewebpagepreview, disablenotification, replytomessageid, replymarkup |
| photo | photo, caption, disablenotification, replytomessageid, replymarkup |
| audio | audio, performer, title, duration, caption, disablenotification, replytomessageid, replymarkup |
| document | document, caption, disablenotification, replytomessageid, replymarkup |
| sticker | sticker, disablenotification, replytomessageid, replymarkup |
| video | video, width, height, duration, caption, disablenotification, replytomessageid, replymarkup |
| voice | voice, duration, caption, disablenotification, replytomessageid, replymarkup |
| videoNote | videoNote, duration, length, disablenotification, replytomessageid, replymarkup |
| location | latitude, longitude, disablenotification, replytomessageid, replymarkup |
| venue | latitude, longitude, title, address, foursquareid, disablenotification, replytomessageid, replymarkup |
| contact | phonenumber, firstname, lastname, disablenotification, replytomessageid, replymarkup |
| chatAction | action |
| game | gameshortname, disablenotification, replytomessageid, replymarkup |
| invoice | title ... ... replymarkup |
| | - |
| inlineQuery | results, nextoffset, ispersonal, cachetime, switchpmtext, switchpmparameter |
| callbackQuery | text, showalert |
| shippingQuery | ok, shippingoptions, errormessage |
| preCheckoutQuery | ok, errormessage |
Tg Upload
```js 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 fileid 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.
/
```
Plugin
```js 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
```js 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) { });
```
JS Generators
```js 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
```js //-----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); ```Keyboard
```js 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 | |
Download
```js gBot.download("fileid", "dir"/, callback/); gBot.download("fileid", "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"));
});
```
InlineQuery
https://core.telegram.org/bots/inline ```js 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);
```
Send file as Buffer
```js 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
});
```
CLI
| Key | Note | |-------------------|-------------------------------------------------------------------------------| | | - | | -j | insert white space into the output JSON string for readability purposes | | | - | | --token | high priority | | --method | high priority | | --proxy | "ip:port" | ```js // Environment variables: low priorityset TELEGRAMBOTTOKEN=X
set TELEGRAMBOTMETHOD=X
set TELEGRAMBOTPROXY=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 --chatid 0 --text "Hi" -disablewebpagepreview
tg-bot --token X --method sendMessage < "./examples/msg.json"
tg-bot --token X --method sendPhoto --chatid 0 --photo "/path/MiElPotato.jpg"
tg-bot --token X --method sendPhoto --chatid 0 --photo "https://www.google.ru/images/logos/pslogo2.png"...
tg-bot
{"token": "", "method": "sendMessage", "chatid": 0, "text": "1"}(result)
{"chatid": 0, "text": "2", "j": true, "proxy": "ip:port"}(result) ```