telegram-bot-api-c

Lightweight, Simple, Fastest module for Telegram Bot without Dependencies

Downloads in past

Stats

StarsIssuesVersionUpdatedCreatedSize
telegram-bot-api-c
16019.5.06 years ago9 years agoMinified + gzip package size for telegram-bot-api-c in KB

Readme

!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 API
3, Bot API 2.x100, Bot API 3.5
  • Array and Map10 as a data source (.call, .callJson, .apimethod): +
```
  • 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:

  1. High stability;
  1. Low memory usage;
  1. Maximum performance;
  1. 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 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.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("file
id", "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 priority
set 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) ```

Test

```js npm -g install mocha npm install chai set TELEGRAMBOTTOKEN=X set TELEGRAMCHATID=X set TELEGRAMMSGID=X cd npm test ``` !npm testimage-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 API3 | | | - | | | 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 === supergroup | | isReply | boolean | bot.isReply = !!bot.message.replytomessage | | | - | | | cid | number | bot.cid = bot.message.chat.id | | mid | number | bot.mid = bot.message.messageid | | qid | string | bot.qid = bot.inlineQuery.id | | cqid | string | bot.cqid = bot.callbackQuery.id | | sid | string | bot.sid = bot.shippingquery.id | | pqid | string | bot.pqid = bot.precheckoutquery.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 ---------------------------------- @ Daeren1 @ Telegram2