├── .gitignore ├── package.json ├── README.md └── telegrambot.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TelegramBot", 3 | "version": "0.0.1", 4 | "description": "A generic node module for working with Telegram Bots", 5 | "main": "telegrambot.js", 6 | "keywords": [ "telegram" ], 7 | "author": "Bryan Abrams", 8 | "repository" : { 9 | "type" : "git", 10 | "url" : "https://github.com/abramsba/TelegramBot" 11 | }, 12 | "license": "BSD", 13 | "dependencies": { 14 | "promise": "~7.0.3", 15 | "request": "~2.58.0", 16 | "underscore": "~1.8.3" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | TelegramBot 3 | =========== 4 | 5 | **TelegramBot** is a simple node based module for creating programs which make use of telegram bots. 6 | 7 | https://core.telegram.org/bots 8 | https://core.telegram.org/bots/api 9 | 10 | ## Creating A Bot 11 | 12 | 1. Create a new bot on telegram via `@BotFather` and receive a token. 13 | 2. Require `telegrambot.js` in your node application 14 | 3. Create a new instance of `TelegramBot` and pass the token you received from `@BotFather` 15 | 4. Either have a webhook URL already set or supply one via the function `setWebhook` 16 | 5. Add new commands by using the function `addCommand` 17 | 6. Override the functions in `TelegramBot.functions` 18 | 7. Enjoy! 19 | 20 | This module only supports updating via `setWebhook` and not `getUpdates`. 21 | 22 | ```js 23 | 24 | // https://github.com/abramsba/TelegramBot/blob/master/telegrambot.js#L6 25 | // Create a new instance of a bot and supply your token. When created 26 | // the 'getMe' method will be called to receive the name and id of the bot 27 | var bot = new TelegramBot(''); 28 | 29 | // https://github.com/abramsba/TelegramBot/blob/master/telegrambot.js#L176 30 | // Supply a URL which is listening for updates 31 | bot.setWebhook( 'https://url.to.hook/' ); 32 | 33 | // https://github.com/abramsba/TelegramBot/blob/master/telegrambot.js#L135 34 | // Add a command 'test', arguments are space seperated. URL encoding is supported 35 | bot.addCommand( 'test', function( id, from, chat, date, arguments ) { 36 | console.log( from, chat, arguments ); 37 | }); 38 | 39 | // https://github.com/abramsba/TelegramBot/blob/master/telegrambot.js#L11 40 | bot.functions.onPlainText = function( id, from, chat, date, message ) { 41 | console.log("This will be called when a normal text message is received.", id, from, chat, date, message); 42 | } 43 | 44 | ``` 45 | 46 | -------------------------------------------------------------------------------- /telegrambot.js: -------------------------------------------------------------------------------- 1 | 2 | var _ = require('underscore'); 3 | var request = require('request'); 4 | var promise = require('promise'); 5 | 6 | var TelegramBot = function( token ) { 7 | this.api_url = 'https://api.telegram.org/bot' + token; 8 | this.command_character = '/'; 9 | this.commands = {}; 10 | // Default Functions for logging the actions, override with your own functions 11 | this.functions = { 12 | onPlainText: function( id, from, chat, date, message ) { console.log( "onPlainText", id, from, chat, date, message ); }, 13 | onAudio: function( id, from, chat, date, audio ) { console.log( "onAudio", audio ); }, 14 | onDocument: function( id, from, chat, date, document ) { console.log( "onDocument", document ); }, 15 | onPhoto: function( id, from, chat, date, photo ) { console.log( "onPhoto", photo ); }, 16 | onSticker: function( id, from, chat, date, sticker ) { console.log( "onSticker", sticker ); }, 17 | onVideo: function( id, from, chat, date, video ) { console.log( "onVideo", video ); }, 18 | onContact: function( id, from, chat, date, contact ) { console.log( "onContact", contact ); }, 19 | onLocation: function( id, from, chat, date, location ) { console.log( "onLocation", location ); }, 20 | onNewParticipant: function( id, from, chat, date, user ) { console.log( "onNewParticipant", user ); }, 21 | onLeftParticipant: function( id, from, chat, date, user ) { console.log( "onLeftParticipant", user ); }, 22 | }; 23 | this.ready = false; 24 | this.bot_id = -1; 25 | this.bot_name = "uninitialized"; 26 | 27 | var self = this; 28 | this.getMe().then( function(body) { self.setReady(body) }, console.log ); 29 | } 30 | 31 | /* 32 | * When created this bot does a 'getMe' to get details on the robot 33 | */ 34 | TelegramBot.prototype.setReady = function( body ) { 35 | if ( body.ok == true ) { 36 | this.bot_id = body.result.id; 37 | this.bot_name = body.result.username; 38 | this.ready = true; 39 | } 40 | } 41 | 42 | /* 43 | * https://core.telegram.org/bots/api#setwebhook 44 | * When the webhook is called, this function is called and proceeds with execution 45 | * if the updated message text contains a command. 46 | */ 47 | TelegramBot.prototype.onUpdate = function( message ) { 48 | var id = message.message_id; 49 | var from = message.from; 50 | var date = message.date; 51 | var chat = message.chat; 52 | if ( this.ready == true ) { 53 | if ( this.isChat(message) && this.isCommand(message) ) { 54 | this.onCommand( id, from, chat, date, this.parseArguments(message.text) ); 55 | } 56 | else { 57 | if ( this.isChat(message) ) { 58 | this.functions.onPlainText( id, from, chat, date, message.text ); 59 | } 60 | else if ( message.audio != undefined ) { 61 | this.functions.onAudio( id, from, chat, date, message.audio ); 62 | } 63 | else if ( message.document != undefined ) { 64 | this.functions.onDocument( id, from, chat, date, message.document ); 65 | } 66 | else if ( message.photo != undefined ) { 67 | this.functions.onPhoto( id, from, chat, date, message.photo ); 68 | } 69 | else if ( message.sticker != undefined ) { 70 | this.functions.onSticker( id, from, chat, date, message.sticker ); 71 | } 72 | else if ( message.video != undefined ) { 73 | this.functions.onVideo( id, from, chat, date, message.video ); 74 | } 75 | else if ( message.contact != undefined ) { 76 | this.functions.onContact( id, from, chat, date, message.contact ); 77 | } 78 | else if ( message.location != undefined ) { 79 | this.functions.onLocation( id, from, chat, date, message.location ); 80 | } 81 | else if ( message.new_chat_participant != undefined ) { 82 | this.functions.onNewParticipant( id, from, chat, date, message.new_chat_participant ); 83 | } 84 | else if ( message.left_chat_participant != undefined ) { 85 | this.functions.onLeftParticipant( id, from, chat, date, message.left_chat_participant ); 86 | } 87 | } 88 | } 89 | } 90 | 91 | /* 92 | * Runs the specified command if registered. Name is excluding the / character. 93 | */ 94 | TelegramBot.prototype.onCommand = function( id, from, chat, date, args ) { 95 | var run = this.commands[args[0]]; 96 | if ( run != undefined ) 97 | run( id, from, chat, date, args.splice( 1, args.length ) ); 98 | } 99 | 100 | /* 101 | * 102 | 103 | /* 104 | * Returns true if the first character of the message text is a '/' 105 | */ 106 | TelegramBot.prototype.isCommand = function( message ) { 107 | return message.text[0] === this.command_character; 108 | } 109 | 110 | /* 111 | * Returns true if the message is from a group or sent to the bot individually 112 | */ 113 | TelegramBot.prototype.isChat = function( message ) { 114 | return message.text != undefined; 115 | } 116 | 117 | /* 118 | * Split the string at spaces and return the arguments 119 | */ 120 | TelegramBot.prototype.parseArguments = function( text ) { 121 | var args_parsed = []; 122 | var args_split = text.split(" "); 123 | _.each( args_split, function(arg, index) { 124 | if ( index == 0 ) 125 | args_parsed.push( arg.substring(1, arg.length) ); 126 | else 127 | args_parsed.push( decodeURIComponent(arg) ); 128 | }); 129 | return args_parsed; 130 | } 131 | 132 | /* 133 | * Add a command to be executed when a user calls a command 134 | */ 135 | TelegramBot.prototype.addCommand = function( name, callback ) { 136 | if ( this.commands[name] != undefined ) return false; 137 | this.commands[name] = callback; 138 | } 139 | 140 | /* 141 | * Given a map where the key is the parameter and the value is the argument 142 | * Build up a URL for calling a service 143 | */ 144 | TelegramBot.prototype.buildURI = function( resource, params ) { 145 | var param_keys = params != undefined ? _.keys(params) : []; 146 | var uri_resource = this.api_url + '/' + resource; 147 | var uri_params = ""; 148 | _.each( param_keys, function(key, index) { 149 | var uri_param = key + '=' + encodeURIComponent( params[key] ); 150 | if ( index != param_keys.length - 1 ) 151 | uri_param += "&"; 152 | uri_params += uri_param; 153 | }); 154 | if ( uri_params.length != 0 ) { 155 | uri_resource += "?" + uri_params 156 | } 157 | return uri_resource; 158 | } 159 | 160 | /* 161 | * Send a HTTPS request and return a promise 162 | */ 163 | TelegramBot.prototype.httpsRequest = function( url ) { 164 | return new promise( function(fulfill, reject) { 165 | request( url, function( error, response, body ) { 166 | if(error) reject(error); 167 | else fulfill(JSON.parse(body)); 168 | }); 169 | }); 170 | } 171 | 172 | /* 173 | * https://core.telegram.org/bots/api#setwebhook 174 | * Use this method to specify a url and receive incoming updates via an outgoing webhook. 175 | */ 176 | TelegramBot.prototype.setWebhook = function( url ) { 177 | var url = this.buildURI( 'setWebhook', { url: url } ); 178 | return this.httpsRequest(url); 179 | } 180 | 181 | /* 182 | * https://core.telegram.org/bots/api#getme 183 | * A simple method for testing your bot's auth token. 184 | */ 185 | TelegramBot.prototype.getMe = function() { 186 | var url = this.buildURI( 'getMe' ); 187 | return this.httpsRequest(url); 188 | } 189 | 190 | /* 191 | * https://core.telegram.org/bots/api#sendmessage 192 | * Use this method to send text messages. On success, the sent Message is returned. 193 | */ 194 | TelegramBot.prototype.sendMessage = function( chat_id, text, disable_web_page_preview, reply_to_message_id, reply_markup ) { 195 | var params = { chat_id: chat_id, text: text }; 196 | if ( disable_web_page_preview != undefined ) 197 | params.disable_web_page_preview = disable_web_page_preview; 198 | if ( reply_to_message_id != undefined ) 199 | params.reply_to_message_id = reply_to_message_id; 200 | if ( reply_markup != undefined ) 201 | params.reply_markup = reply_markup; 202 | return this.httpsRequest( this.buildURI( 'sendMessage', params ) ); 203 | } 204 | 205 | /* 206 | * https://core.telegram.org/bots/api#forwardmessage 207 | * Use this method to forward messages of any kind. On success, the sent Message is returned. 208 | */ 209 | TelegramBot.prototype.forwardMessage = function( chat_id, from_chat_id, message_id ) { 210 | var params = { chat_id: chat_id, from_chat_id: from_chat_id, message_id: message_id }; 211 | return this.httpsRequest( this.buildURI( 'forwardMessage', params ) ); 212 | } 213 | 214 | /* 215 | * https://core.telegram.org/bots/api#sendphoto 216 | * Use this method to send photos. On success, the sent Message is returned. 217 | */ 218 | TelegramBot.prototype.sendPhoto = function( chat_id, photo, caption, reply_to_message_id, reply_markup ) { 219 | var params = { chat_id: chat_id, photo: photo }; 220 | if ( caption != undefined ) 221 | params.caption = caption; 222 | if ( reply_to_message_id != undefined ) 223 | params.reply_to_message_id = reply_to_message_id; 224 | if ( reply_markup != undefined ) 225 | params.reply_markup = reply_markup; 226 | return this.httpsRequest( this.buildURI( 'sendPhoto', params ) ); 227 | } 228 | 229 | /* 230 | * https://core.telegram.org/bots/api#sendsticker 231 | * Use this method to send .webp stickers. 232 | */ 233 | TelegramBot.prototype.sendSticker = function( chat_id, sticker, reply_to_message_id, reply_markup ) { 234 | var params = { chat_id: chat_id, sticker: sticker }; 235 | if ( reply_to_message_id != undefined ) 236 | params.reply_to_message_id = reply_to_message_id; 237 | if ( reply_markup != undefined ) 238 | params.reply_markup = reply_markup; 239 | return this.httpsRequest( this.buildURI( 'sendSticker', params ) ); 240 | } 241 | 242 | /* 243 | * https://core.telegram.org/bots/api#sendaudio 244 | * Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message. For this to work, your audio must be in an .ogg file encoded with OPUS 245 | */ 246 | TelegramBot.prototype.sendAudio = function( chat_id, audio, reply_to_message_id, reply_markup ) { 247 | var params = { chat_id: chat_id, audio: audio }; 248 | if ( reply_to_message_id != undefined ) 249 | params.reply_to_message_id = reply_to_message_id; 250 | if ( reply_markup != undefined ) 251 | params.reply_markup = reply_markup; 252 | return this.httpsRequest( this.buildURI( 'sendAudio', params ) ); 253 | } 254 | 255 | /* 256 | * https://core.telegram.org/bots/api#senddocument 257 | * Use this method to send general files. On success, the sent Message is returned. Bots can currently send files of any type of up to 50 MB in size 258 | */ 259 | TelegramBot.prototype.sendDocument = function( chat_id, document, reply_to_message_id, reply_markup ) { 260 | var params = { chat_id: chat_id, document: document }; 261 | if ( reply_to_message_id != undefined ) 262 | params.reply_to_message_id = reply_to_message_id; 263 | if ( reply_markup != undefined ) 264 | params.reply_markup = reply_markup; 265 | return this.httpsRequest( this.buildURI( 'sendDocument', params ) ); 266 | } 267 | 268 | /* 269 | * https://core.telegram.org/bots/api#sendvideo 270 | * Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). 271 | */ 272 | TelegramBot.prototype.sendVideo = function( chat_id, video, reply_to_message_id, reply_markup ) { 273 | var params = { chat_id: chat_id, video: video }; 274 | if ( reply_to_message_id != undefined ) 275 | params.reply_to_message_id = reply_to_message_id; 276 | if ( reply_markup != undefined ) 277 | params.reply_markup = reply_markup; 278 | return this.httpsRequest( this.buildURI( 'sendVideo', params ) ); 279 | } 280 | 281 | /* 282 | * https://core.telegram.org/bots/api#sendchataction 283 | * Use this method when you need to tell the user that something is happening on the bot's side. 284 | */ 285 | TelegramBot.prototype.sendChatAction = function( chat_id, action ) { 286 | var params = { chat_id: chat_id, action: action }; 287 | return this.httpsRequest( this.buildURI( 'sendChatAction', params ) ); 288 | } 289 | 290 | module.exports = TelegramBot; 291 | 292 | --------------------------------------------------------------------------------