├── .gitignore ├── README.md ├── app.js ├── commands ├── echo.js ├── status.js └── wiki.js ├── config.js ├── package.json └── startbot.sh /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### Telegram Bot 2 | - - - 3 | 4 | ##### Requirements 5 | - - - 6 | * Telegram messenger CLI ([https://github.com/vysheng/tg](https://github.com/vysheng/tg)) 7 | 8 | ##### Running 9 | - - - 10 | Create or edit startbot.sh, make sure to include 11 | 12 | telegram-cli -k /path/to/api/key 13 | 14 | Run the bot 15 | 16 | node app.js 17 | 18 | #### Adding Commands 19 | - - - 20 | Edit config.js, and add a new command file to the commands folder. All commands should have the following structure: 21 | 22 | var command = { 23 | process: function(command, telegramProcess) { 24 | // handle command here 25 | }; 26 | module.exports = command; 27 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | 2 | var fs = require('fs'); 3 | var _ = require('lodash'); 4 | var stripAnsi = require('strip-ansi'); 5 | var spawn = require('child_process').spawn; 6 | var telegramProcess = spawn('./startbot.sh'); 7 | 8 | var Config = { }; 9 | var CommandProcessers = {}; 10 | telegramProcess.stdout.setEncoding('utf8'); 11 | 12 | // Give process 2secs to start before watching stdout 13 | setTimeout(function() { 14 | 15 | console.log('starting bot'); 16 | // Need to call dialog_list to get all chats and contacts 17 | telegramProcess.stdin.write('dialog_list\n'); 18 | 19 | loadConfig(function(configdata) { 20 | Config = configdata; 21 | telegramProcess.stdout.on('data', function(data) { 22 | var lines = data.toString().split('\n'); 23 | 24 | // telegram cli constantly outputs '>', don't bother trying to parse those 25 | if (lines.length > 1) { 26 | // telegram cli uses ansi color codes...need to strip them for parsing 27 | lines = _.map(lines, function(line) { 28 | return stripAnsi(line); 29 | }); 30 | 31 | // Message output should always be in the first line of data 32 | if (lines[0].indexOf('>>>') > -1) { 33 | console.log(lines[0]); 34 | var commandObj = buildCommandObj(lines[0]); 35 | processCommand(commandObj); 36 | } 37 | } 38 | }); 39 | }); 40 | }, 2000); 41 | 42 | function parseCLIOutput(data) { 43 | var splitData = data.split(' >>> '); 44 | 45 | // Message is always the last element 46 | var message = splitData[splitData.length - 1]; 47 | var metaData = splitData[0].split(' '); 48 | 49 | //User/Group to send to will always be the 3rd element. 50 | // User who sent the message is always last element of meta data. 51 | var sendTo = metaData[2]; 52 | var user = metaData[metaData.length - 1]; 53 | 54 | return { 55 | sendTo: sendTo, 56 | user: user, 57 | message: message 58 | }; 59 | } 60 | 61 | function parseMessage(message) { 62 | var commandIdentifier = message.substring(0, 2); 63 | message = message.substring(2, message.length); 64 | 65 | // Only process messages that start with "#!" as commands 66 | if (commandIdentifier === '#!') { 67 | var command = message.match(/^[^\s]+/); 68 | 69 | // Should always be 1 70 | if (command.length > 0) { 71 | command = command[0]; 72 | } else { 73 | return false; 74 | } 75 | 76 | var commandArgs = message.substring(command.length + 1, message.length); 77 | 78 | return { 79 | command: command, 80 | args: commandArgs 81 | }; 82 | } else { 83 | return false; 84 | } 85 | } 86 | 87 | function processCommand(commandObj) { 88 | // Find command processor from config file 89 | var commandConfig = _.find(Config.commands, function(c) { 90 | return c.command === commandObj.command.command; 91 | }); 92 | 93 | if (commandConfig) { 94 | // Check if the command was already proccessed previously. 95 | if (!CommandProcessers[commandConfig.command]) { 96 | CommandProcessers[commandConfig.command] = require('./commands/' + commandConfig.processor); 97 | } 98 | CommandProcessers[commandConfig.command].process(commandObj, telegramProcess); 99 | } else { 100 | console.log('Could not find command'); 101 | } 102 | } 103 | 104 | function buildCommandObj(data) { 105 | var parsedOutput = parseCLIOutput(data); 106 | var parsedMessage = parseMessage(parsedOutput.message); 107 | 108 | return { 109 | sendTo: parsedOutput.sendTo, 110 | user: parsedOutput.user, 111 | command: parsedMessage 112 | }; 113 | } 114 | 115 | function loadConfig(callback) { 116 | fs.readFile('config.js', 'utf8', function(err, data) { 117 | if (err) 118 | return console.log(err); 119 | 120 | callback(JSON.parse(data)); 121 | }); 122 | } 123 | -------------------------------------------------------------------------------- /commands/echo.js: -------------------------------------------------------------------------------- 1 | var echoCommand = { 2 | process: function(command, telegramProcess) { 3 | console.log('Processing echo command'); 4 | console.log(command); 5 | console.log('msg ' + command.user + ' ' + command.command.args + '\n'); 6 | 7 | telegramProcess.stdin.write('msg ' + command.sendTo + ' "' + command.command.args + '"\n'); 8 | } 9 | }; 10 | 11 | module.exports = echoCommand; -------------------------------------------------------------------------------- /commands/status.js: -------------------------------------------------------------------------------- 1 | var os = require('os'), 2 | exec = require('child_process').exec; 3 | 4 | var statusCommand = { 5 | process: function(command, telegramProcess) { 6 | console.log('processing status command'); 7 | console.log(command); 8 | exec('cat /etc/issue', function(error, distro, stderr) { 9 | if (!error) { 10 | var rtrStr = distro.split('\n').join('') + os.arch() + '\\n' + 11 | 'CPU Load: ' + (os.loadavg()[1] * 100).toFixed(2) + '%\\n' + 12 | 'Mem Usage: ' + ((os.freemem() / os.totalmem()) * 100).toFixed(2) + '%\\n' + 13 | 'Uptime: ' + (os.uptime() / 60 / 60).toFixed(2) + ' hours'; 14 | 15 | telegramProcess.stdin.write('msg ' + command.sendTo + ' "' + rtrStr + '"\n'); 16 | } 17 | }); 18 | } 19 | }; 20 | 21 | module.exports = statusCommand; -------------------------------------------------------------------------------- /commands/wiki.js: -------------------------------------------------------------------------------- 1 | var request = require('request'), 2 | cheerio = require('cheerio'); 3 | 4 | var wikiCommand = { 5 | process: function(command, telegramProcess) { 6 | console.log('Processing wiki command'); 7 | console.log(command); 8 | var searchURL = 'http://en.wikipedia.org/w/api.php?action=opensearch&search=' + command.command.args + '&format=json'; 9 | 10 | // Search wikipedia to get proper article name 11 | request(searchURL, function(error, response, results) { 12 | if (!error) { 13 | results = JSON.parse(results); 14 | var articleName = results[1][0]; 15 | if (articleName) { 16 | // Get article's page id from title 17 | var articleURL = 'http://en.wikipedia.org/w/api.php?action=query&prop=extracts&format=json&exintro=&titles=' + escape(articleName) + '&continue=' 18 | 19 | request(articleURL, function(error, response, articleResult) { 20 | var articleData = JSON.parse(articleResult); 21 | 22 | // Get html for article 23 | var articleHtmlReqUrl = 'http://en.wikipedia.org/wiki?curid=' + articleData.query.pages[Object.keys(articleData.query.pages)].pageid; 24 | request(articleHtmlReqUrl, function(error, response, articleHtml) { 25 | if (error) 26 | console.log(error); 27 | 28 | $ = cheerio.load(articleHtml); 29 | var firstParagraph = $('p').first().text(); 30 | telegramProcess.stdin.write("msg " + command.sendTo + " " + firstParagraph + "\n"); 31 | }); 32 | }); 33 | } 34 | } 35 | }); 36 | } 37 | }; 38 | 39 | module.exports = wikiCommand; -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | { 2 | "commands": [ 3 | { 4 | "command": "echo", 5 | "processor": "echo.js" 6 | }, 7 | { 8 | "command": "wiki", 9 | "processor": "wiki.js" 10 | }, 11 | { 12 | "command": "status", 13 | "processor": "status.js" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-telegram-bot", 3 | "version": "0.1.0", 4 | "dependencies": { 5 | "lodash": "2.4.1", 6 | "strip-ansi": "^2.0.0", 7 | "cheerio": "0.18.0", 8 | "request": "2.47.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /startbot.sh: -------------------------------------------------------------------------------- 1 | PATH=$PATH:~/tg/bin 2 | export PATH 3 | telegram-cli -k ~/tg/bin/tg-public.pub 4 | --------------------------------------------------------------------------------