├── .eslintignore ├── .eslintrc ├── .travis.yml ├── .editorconfig ├── examples └── bot.js ├── .gitignore ├── LICENSE ├── package.json ├── index.js ├── bin └── micro-bot └── readme.md /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["standard"] 3 | } 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 8 4 | - 9 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [*.txt] 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /examples/bot.js: -------------------------------------------------------------------------------- 1 | const { Composer } = require('micro-bot') 2 | const bot = new Composer() 3 | 4 | bot.start((ctx) => ctx.reply('Welcome')) 5 | bot.help((ctx) => ctx.reply('Help message')) 6 | bot.hears('hi', ({ reply }) => reply('Hello')) 7 | bot.on('sticker', ({ reply }) => reply('👍')) 8 | bot.on('message', ({ reply }) => reply('👋')) 9 | 10 | module.exports = bot 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | .nyc_output 35 | coverage 36 | _docpress 37 | package-lock.json 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Vitaly Domnikov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "micro-bot", 3 | "version": "2.5.3", 4 | "description": "Zero-configuration Telegram bot runner", 5 | "author": "Vitaly Domnikov ", 6 | "license": "MIT", 7 | "homepage": "https://github.com/telegraf/micro-bot#readme", 8 | "repository": { 9 | "type": "git", 10 | "url": "git+ssh://git@github.com/telegraf/micro-bot.git" 11 | }, 12 | "bugs": { 13 | "url": "https://github.com/telegraf/micro-bot/issues" 14 | }, 15 | "main": "index.js", 16 | "scripts": { 17 | "test": "eslint ." 18 | }, 19 | "engines": { 20 | "node": ">=8.1" 21 | }, 22 | "bin": { 23 | "micro-bot": "./bin/micro-bot" 24 | }, 25 | "dependencies": { 26 | "dotenv": "^6.0.0", 27 | "minimist": "^1.2.0", 28 | "telegraf": "^3.25.4" 29 | }, 30 | "devDependencies": { 31 | "eslint": "^5.4.0", 32 | "eslint-config-standard": "^12.0.0", 33 | "eslint-plugin-import": "^2.2.0", 34 | "eslint-plugin-node": "^8.0.0", 35 | "eslint-plugin-promise": "^4.0.0", 36 | "eslint-plugin-standard": "^4.0.0" 37 | }, 38 | "keywords": [ 39 | "telegraf", 40 | "telegram", 41 | "bot" 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const Telegraf = require('telegraf') 2 | const Stage = require('telegraf/stage') 3 | const Scene = require('telegraf/scenes/base') 4 | const WizardScene = require('telegraf/scenes/wizard') 5 | 6 | const defaultInit = () => Promise.resolve() 7 | const defaultCb = (req, res) => { 8 | res.statusCode = 404 9 | res.end() 10 | } 11 | 12 | function start ({ token, domain, hookPath, botModule, port, host, silent }) { 13 | const webhook = typeof domain === 'string' || typeof hookPath === 'string' 14 | ? { 15 | domain, 16 | hookPath, 17 | port, 18 | host, 19 | tlsOptions: botModule.tlsOptions, 20 | cb: botModule.server || botModule.requestHandler || defaultCb 21 | } 22 | : null 23 | const bot = new Telegraf(token, botModule.options) 24 | const init = botModule.init || botModule.initialize || defaultInit 25 | bot.catch((err) => console.error('μ-bot: Unhandled error', err)) 26 | bot.use(botModule.bot || botModule.botHandler || botModule) 27 | return init(bot) 28 | .then(() => bot.launch({ webhook })) 29 | .then(() => !silent && console.log(`μ-bot: Bot started`)) 30 | } 31 | 32 | module.exports = Object.assign(Telegraf, { Stage, Scene, WizardScene, start: start }) 33 | -------------------------------------------------------------------------------- /bin/micro-bot: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const { existsSync } = require('fs') 4 | const path = require('path') 5 | const parse = require('minimist') 6 | const dotenv = require('dotenv') 7 | const { start } = require('../') 8 | 9 | const help = () => { 10 | console.log(`Usage: micro-bot [opts] 11 | 12 | -t Bot token 13 | -d Webhook domain [$BOT_DOMAIN or $NOW_URL] 14 | -H Webhook host [0.0.0.0] 15 | -p Webhook port [$PORT or 3000] 16 | -e Load env vars from file. [.env]' 17 | -s Silent mode 18 | -h Show this help message 19 | -v Show version information`) 20 | } 21 | 22 | const args = parse(process.argv, { 23 | alias: { 24 | d: 'domain', 25 | e: 'dotenv', 26 | h: 'help', 27 | H: 'host', 28 | p: 'port', 29 | s: 'silent', 30 | t: 'token', 31 | v: 'version' 32 | }, 33 | boolean: ['h', 'v', 's'], 34 | default: { 35 | H: '0.0.0.0', 36 | p: process.env.PORT || 3000 37 | } 38 | }) 39 | 40 | if (args.help) { 41 | help() 42 | process.exit(0) 43 | } 44 | 45 | if (args.version) { 46 | const packageData = require('../package.json') 47 | console.log(`v${packageData.version}`) 48 | process.exit(0) 49 | } 50 | 51 | if (args.dotenv) { 52 | const dotenvFileName = typeof args.dotenv === 'string' ? args.dotenv : '.env' 53 | if (!existsSync(dotenvFileName)) { 54 | console.error(`μ-bot: -e flag is set but ${dotenvFileName} file is missing`) 55 | help() 56 | process.exit(1) 57 | } 58 | dotenv.config({ path: dotenvFileName }) 59 | } 60 | 61 | const token = args.token || process.env.BOT_TOKEN 62 | if (!token) { 63 | console.error(`μ-bot: Please supply Bot token`) 64 | help() 65 | process.exit(1) 66 | } 67 | 68 | let [,, file] = args._ 69 | 70 | if (!file) { 71 | try { 72 | const packageJson = require(path.resolve(process.cwd(), 'package.json')) 73 | file = packageJson.main || 'index.js' 74 | } catch (err) { 75 | if (err.code === 'MODULE_NOT_FOUND') { 76 | console.error(`μ-bot: Could not read \`package.json\`: ${err.message}`) 77 | process.exit(1) 78 | } 79 | } 80 | } 81 | 82 | if (!file) { 83 | console.error('μ-bot: Please supply a file with bot handler.') 84 | help() 85 | process.exit(1) 86 | } 87 | 88 | if (file[0] !== '/') { 89 | file = path.resolve(process.cwd(), file) 90 | } 91 | 92 | let botModule 93 | try { 94 | botModule = require(file) 95 | } catch (err) { 96 | console.error(`μ-bot: Error when importing ${file}: ${err.stack}`) 97 | process.exit(1) 98 | } 99 | 100 | const domain = args.domain || process.env.BOT_DOMAIN || process.env.NOW_URL 101 | 102 | const botOptions = { 103 | token, 104 | domain, 105 | botModule, 106 | port: args.port, 107 | host: args.host 108 | } 109 | 110 | start(botOptions).catch((err) => { 111 | console.warn(`μ-bot: Failed to start: ${err}`) 112 | }) 113 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ⚠️ This package is deprecated. Use [telegraf](https://github.com/telegraf/telegraf)'s builtin CLI instead. 2 | 3 | [![NPM Version](https://img.shields.io/npm/v/micro-bot.svg?style=flat-square)](https://www.npmjs.com/package/micro-bot) 4 | [![node](https://img.shields.io/node/v/micro-bot.svg?style=flat-square)](https://www.npmjs.com/package/micro-bot) 5 | [![Build Status](https://img.shields.io/travis/telegraf/micro-bot.svg?branch=master&style=flat-square)](https://travis-ci.org/telegraf/micro-bot) 6 | [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](http://standardjs.com/) 7 | 8 | # μ-bot 9 | > 🤖 Zero-configuration Telegram bot runner 10 | 11 | ## Documentation 12 | 13 | `micro-bot` was built on top of [`Telegraf`](https://github.com/telegraf/telegraf) library. 14 | 15 | [Telegraf API documentation](http://telegraf.js.org). 16 | 17 | ## Installation 18 | 19 | Install from NPM: 20 | 21 | ```bash 22 | $ npm install micro-bot 23 | ``` 24 | 25 | ## Scaffolding 26 | 27 | If you have installed latest `yarn` or `npm` you can use [`create-bot`](https://github.com/telegraf/create-bot) scaffolding tool: 28 | 29 | ```bash 30 | $ npm init bot smart-bot 31 | $ cd smart-bot 32 | ``` 33 | 34 | Or using `yarn`: 35 | 36 | ```bash 37 | $ yarn create bot smart-bot 38 | $ cd smart-bot 39 | ``` 40 | 41 | ## Quick start 42 | 43 | The following example will answer with important information about everything. 44 | 45 | ```bash 46 | $ mkdir smart-bot 47 | $ cd smart-bot 48 | $ npm init 49 | $ npm install micro-bot --save 50 | ``` 51 | 52 | Then write your `index.js`. 53 | 54 | ```js 55 | module.exports = ({ reply }) => reply('42') 56 | ``` 57 | 58 | Then in your `package.json`: 59 | 60 | ```js 61 | "main": "index.js", 62 | "scripts": { 63 | "start": "micro-bot" 64 | } 65 | ``` 66 | 67 | To run the bot, use the `micro-bot` command: 68 | 69 | ```bash 70 | $ BOT_TOKEN='TOKEN' npm start 71 | ``` 72 | 73 | or 74 | 75 | ```bash 76 | $ micro-bot -t TOKEN index.js 77 | ``` 78 | 79 | To run the bot with webhook support, provide webhook domain name: 80 | 81 | ```bash 82 | $ micro-bot -t TOKEN -d yourdomain.tld echo.js 83 | ``` 84 | 85 | Supported environment variables: 86 | 87 | * `process.env.BOT_TOKEN` - Bot token 88 | * `process.env.BOT_DOMAIN` - Webhook domain 89 | 90 | ## Deployment to `now` 91 | 92 | Let's deploy your `micro-bot` with Realtime global deployments by Zeit. 93 | 94 | First, install [`now`](https://zeit.co/now) 95 | ```bash 96 | $ npm install now -g 97 | $ now login 98 | ``` 99 | 100 | Finally use `now` to deploy: 101 | 102 | ```bash 103 | $ now -e BOT_TOKEN='YOUR BOT TOKEN' 104 | ``` 105 | 106 | Congratulations, your bot is alive! 🎉 107 | 108 | ## Deployment to Heroku 109 | 110 | Okay, now we will deploy our `micro-bot` to Heroku. Why not?! 111 | 112 | First, install [`heroku binaries`](https://devcenter.heroku.com/articles/getting-started-with-nodejs#set-up) and login via console. 113 | 114 | Then, init new git repo: 115 | ```bash 116 | $ git init 117 | $ heroku create 118 | ``` 119 | 120 | Afterwards, update Heroku config: 121 | 122 | ```bash 123 | $ heroku config:set --app YourAppId BOT_TOKEN='YOUR BOT TOKEN' 124 | $ heroku config:set --app YourAppId BOT_DOMAIN='https://YourAppId.herokuapp.com' 125 | ``` 126 | 127 | Then add `Procfile` into the root of your project, with one line: 128 | 129 | ```Procfile 130 | web: micro-bot -p $PORT 131 | ``` 132 | 133 | Finally use git to deploy: 134 | 135 | ```bash 136 | $ git add index.js package.json 137 | $ git commit -m 'initial commit' 138 | $ git push heroku master 139 | ``` 140 | 141 | #### Example μ-bots 142 | 143 | * [ 🔥 Glitch example](https://glitch.com/edit/#!/dashing-light) 144 | * [`@uncover_bot`](https://telegram.me/uncover_bot) - [Source code](https://uncover.now.sh/_src) 145 | * [`@epub2mobi_bot`](https://telegram.me/epub2mobi_bot) - [Source code](https://epub2mobi.now.sh/_src) 146 | * [`@gorchichkabot`](https://bot.gorchichka.com) - [Source code](https://github.com/agudulin/gorchichkabot) 147 | * [`@aloudbot`](https://telegram.me/aloudbot) - [Source code](https://github.com/shrynx/aloudbot) 148 | 149 | ## Advanced Examples 150 | 151 | ```js 152 | const { mount, reply } = require('micro-bot') 153 | module.exports = mount('sticker', reply('👍')) 154 | ``` 155 | 156 | ```js 157 | const { readFileSync } = require('fs') 158 | const { Composer } = require('micro-bot') 159 | const bot = new Composer() 160 | 161 | bot.start((ctx) => ctx.reply('Welcome')) 162 | bot.help((ctx) => ctx.reply('Help message')) 163 | bot.hears('hi', ({ reply }) => reply('Hello')) 164 | bot.on('sticker', ({ reply }) => reply('👍')) 165 | 166 | // Export bot handler 167 | module.exports = bot 168 | 169 | // Or you can export hash with handlers and options 170 | module.exports = { 171 | bot: bot, 172 | init: (bot) => { 173 | console.log('Bot initialization hook') 174 | }, 175 | server: (req, res, next) => { 176 | console.log('Http request hook') 177 | }, 178 | options: { 179 | telegram: { 180 | agent: new HttpsProxyAgent('proxy url') 181 | } 182 | }, 183 | tlsOptions: { 184 | key: readFileSync('server-key.pem'), 185 | cert: readFileSync('server-cert.pem'), 186 | ca: [ 187 | // This is necessary only if the client uses the self-signed certificate. 188 | readFileSync('client-cert.pem') 189 | ] 190 | } 191 | } 192 | ``` 193 | 194 | ### Stages & Scenes 195 | 196 | ```js 197 | const { Composer, Stage, Scene, session } = require('micro-bot') 198 | 199 | // Greeter scene 200 | const greeter = new Scene('greeter') 201 | greeter.enter((ctx) => ctx.reply('Hi')) 202 | greeter.leave((ctx) => ctx.reply('Buy')) 203 | greeter.hears(/hi/gi, (ctx) => ctx.scene.leave()) 204 | greeter.on('message', (ctx) => ctx.reply('Send `hi`')) 205 | 206 | const stage = new Stage() 207 | stage.register(greeter) 208 | 209 | const bot = new Composer() 210 | bot.use(session()) 211 | bot.use(stage) 212 | bot.command('greeter', (ctx) => ctx.scene.enter('greeter')) 213 | bot.command('cancel', (ctx) => ctx.scene.leave()) 214 | module.exports = bot 215 | 216 | ``` 217 | 218 | ## Credits 219 | 220 | `micro-bot` is highly inspired by [`Micro`](https://github.com/zeit/micro/) 221 | --------------------------------------------------------------------------------