Skip to content

Latest commit

 

History

History
1183 lines (1035 loc) · 31.5 KB

README.md

File metadata and controls

1183 lines (1035 loc) · 31.5 KB

Bot-brother

Node.js library to help you easy create telegram bots. Works on top of node-telegram-bot-api Supports telegram-api 2.0 inline keyboards

Main features:

  • sessions
  • middlewares
  • localization
  • templated keyboards and messages
  • navigation between commands
  • inline keyboards

This bots work on top of bot-brother: @weatherman_bot @zodiac_bot @my_ali_bot @delorean_bot @matchmaker_bot

Table of contents

Install

npm install bot-brother

Simple usage

var bb = require('bot-brother');
var bot = bb({
  key: '<_TELEGRAM_BOT_TOKEN>',
  sessionManager: bb.sessionManager.memory(),
  polling: { interval: 0, timeout: 1 }
});

// Let's create command '/start'.
bot.command('start')
.invoke(function (ctx) {
  // Setting data, data is used in text message templates.
  ctx.data.user = ctx.meta.user;
  // Invoke callback must return promise.
  return ctx.sendMessage('Hello <%=user.first_name%>. How are you?');
})
.answer(function (ctx) {
  ctx.data.answer = ctx.answer;
  // Returns promise.
  return ctx.sendMessage('OK. I understood. You feel <%=answer%>');
});

// Creating command '/upload_photo'.
bot.command('upload_photo')
.invoke(function (ctx) {
  return ctx.sendMessage('Drop me a photo, please');
})
.answer(function (ctx) {
  // ctx.message is an object that represents Message.
  // See https://core.telegram.org/bots/api#message 
  return ctx.sendPhoto(ctx.message.photo[0].file_id, {caption: 'I got your photo!'});
});

Examples of usage

We've written simple notification bot with bot-brother, so you can inspect code here: https://github.com/SerjoPepper/delorean_bot
You can try bot in action here: https://telegram.me/delorean_bot

Commands

Commands can be set with strings or regexps.

bot.command(/^page[0-9]+/).invoke(function (ctx) {
  return ctx.sendMessage('Invoked on any page')
});

bot.command('page1').invoke(function (ctx) {
  return ctx.sendMessage('Invoked only on page1');
});

bot.command('page2').invoke(function (ctx) {
  return ctx.sendMessage('Invoked only on page2');
});

Middlewares

Middlewares are useful for multistage command handling.

var bb = require('bot-brother');
var bot = bb({
  key: '<_TELEGRAM_BOT_TOKEN>'
})

bot.use('before', function (ctx) {
  return findUserFromDbPromise(ctx.meta.user.id).then(function (user) {
    user.vehicle = user.vehicle || 'Car'
    // You can set any fieldname except following:
    // 1. You can't create fields starting with '_', like ctx._variable;
    // 2. 'bot', 'session', 'message', 'isRedirected', 'isSynthetic', 'command', 'isEnded', 'meta' are reserved names.
    ctx.user = user;
  });
});

bot.command('my_command')
.use('before', function (ctx) {
  ctx.user.age = ctx.user.age || '25';
})
.invoke(function (ctx) {
  ctx.data.user = ctx.user;
  return ctx.sendMessage('Your vehicle is <%=user.vehicle%>. Your age is <%=user.age%>.');
});

There are following stages, sorted in order of appearance.

Name Description
before applied before all stages
beforeInvoke applied before invoke stage
beforeAnswer applied before answer stage
invoke same as command.invoke(...)
answer same as command.answer(...)

Let's look at following example, and try to understand how and in what order they will be invoked.

bot.use('before', function (ctx) {
  return ctx.sendMessage('bot before');
})
.use('beforeInvoke', function (ctx) {
  return ctx.sendMessage('bot beforeInvoke');
})
.use('beforeAnswer', function (ctx) {
  return ctx.sendMessage('bot beforeAnswer');
});

// This callback cathes all commands.
bot.command(/.*/).use('before', function (ctx) {
  return ctx.sendMessage('rgx before');
})
.use('beforeInvoke', function (ctx) {
  return ctx.sendMessage('rgx beforeInvoke');
})
.use('beforeAnswer', function (ctx) {
  return ctx.sendMessage('rgx beforeAnswer');
});

bot.command('hello')
.use('before', function (ctx) {
  return ctx.sendMessage('hello before');
})
.use('beforeInvoke', function (ctx) {
  return ctx.sendMessage('hello beforeInvoke');
})
.use('beforeAnswer', function (ctx) {
  return ctx.sendMessage('hello beforeAnswer');
})
.invoke(function (ctx) {
  return ctx.sendMessage('hello invoke');
})
.answer(function (ctx) {
  return ctx.go('world');
});

bot.command('world')
.use('before', function (ctx) {
  return ctx.sendMessage('world before');
})
.invoke(function (ctx) {
  return ctx.sendMessage('world invoke');
});

Bot dialog

me  > /hello
bot > bot before
bot > bot beforeInvoke
bot > rgx before
bot > rgx beforeInvoke
bot > hello before
bot > hello beforeInvoke
bot > hello invoke
me  > I type something
bot > bot before
bot > bot beforeAnswer
bot > rgx before
bot > rgx beforeAnswer
bot > hello beforeAnswer
bot > bot before // We've jumped to "world" command with "ctx.go('world')""
bot > bot beforeInvoke
bot > rgx before
bot > rgx beforeInvoke
bot > world before
bot > world invoke 

Predefined middlewares

There are two predefined middlewares:

Usage:

bot.use('before', bb.middlewares.typing());
bot.use('before', bb.middlewares.botanio('<BOTANIO_API_KEY>'));

Sessions

Sessions can be implemented with Redis, with memory/fs storage or your custom storage

bot.command('memory')
.invoke(function (ctx) {
  return ctx.sendMessage('Type some string');
})
.answer(function (ctx) {
  ctx.session.memory = ctx.session.memory || '';
  ctx.session.memory += ctx.answer;
  ctx.data.memory = ctx.session.memory;
  return ctx.sendMessage('Memory: <%=memory%>');
})

This dialog demonstrates how it works:

me  > /memory
bot > Type some string
me  > 1
bot > 1
me  > 2
bot > 12
me  > hello
bot > 12hello

Redis storage

var bb = require('bot-brother')
bot = bb({
  key: '<_TELEGRAM_BOT_TOKEN>',
  sessionManager: bb.sessionManager.redis({port: '...', host: '...'}),
  polling: { interval: 0, timeout: 1 }
})

With custom Redis-client

var bb = require('bot-brother')
bot = bb({
  key: '<_TELEGRAM_BOT_TOKEN>',
  sessionManager: bb.sessionManager.redis({client: yourCustomRedisConnection}),
  polling: { interval: 0, timeout: 1 }
})

Memory storage

var bb = require('bot-brother')
bot = bb({
  key: '<_TELEGRAM_BOT_TOKEN>',
  // set the path where your session will be saved. You can skip this option
  sessionManager: bb.sessionManager.memory({dir: '/path/to/dir'}), 
  polling: { interval: 0, timeout: 1 }
})

Your custom storage

var bb = require('bot-brother')
bot = bb({
  key: '<_TELEGRAM_BOT_TOKEN>',
  // set the path where your session will be saved. You can skip this option
  sessionManager: function (bot) {
    return bb.sessionManager.create({
      save: function (id, session) {
        // save session
        // should return promise
        return Promise.resolve(true)
      },
      get: function(id) {
        // get session by key
        // should return promise with {Object}
        return fetchYourSessionAsync(id)
      },
      getMultiple: function(ids) {
        // optionally method
        // define it if you use expression: bot.withContexts(ids)
        // should return promise with array of session objects
      },
      getAll: function() {
        // optionally method, same as 'getMultiple'
        // define it if you use bot.withAllContexts
      }
    })
  }, 
  polling: { interval: 0, timeout: 1 }
})

Localization and texts

Localization can be used in texts and keyboards. For templates we use ejs.

// Setting keys and values for locale 'en'.
bot.texts({
  book: {
    chapter1: {
      page1: 'Hello <%=user.first_name%> :smile:'
    },
    chapter2: {
      page3: 'How old are you, <%=user.first_name%>?'
    }
  }
}, {locale: 'en'})

// Setting default localization values (used if key in certain locale did not found).
bot.texts({
  book: {
    chapter1: {
      page2: 'How are you, <%=user.first_name%>?'
    },
    chapter2: {
      page4: 'Good bye, <%=user.first_name%>.'
    }
  }
})

bot.use('before', function (ctx) {
  // Let's set data.user to Telegram user to use value in message templates.
  ctx.data.user = ctx.meta.user
  ctx.session.locale = ctx.session.locale || 'en';
  ctx.setLocale(ctx.session.locale);
});

bot.command('chapter1_page1').invoke(function (ctx) {
  ctx.sendMessage('book.chapter1.page1')
})
bot.command('chapter1_page2').invoke(function (ctx) {
  ctx.sendMessage('book.chapter1.page2')
})
bot.command('chapter2_page3').invoke(function (ctx) {
  ctx.sendMessage('book.chapter2.page3')
})
bot.command('chapter2_page4').invoke(function (ctx) {
  ctx.sendMessage('book.chapter2.page4')
})

When bot-brother sends a message, it tries to interpret this message as a key from your localization set. If key's not found, it interprets the message as a template with variables and renders it via ejs. All local variables can be set via ctx.data.

Texts can be set for following entities:

  • bot
  • command
  • context
bot.texts({
  book: {
    chapter: {
      page: 'Page 1 text'
    }
  }
});

bot.command('page1').invoke(function (ctx) {
  return ctx.sendMessage('book.chapter.page');
});

bot.command('page2').invoke(function (ctx) {
  return ctx.sendMessage('book.chapter.page');
})
.texts({
  book: {
    chapter: {
      page: 'Page 2 text'
    }
  }
});

bot.command('page3')
.use('before', function (ctx) {
  ctx.texts({
    book: {
      chapter: {
        page: 'Page 3 text'
      }
    }
  });
})
.invoke(function (ctx) {
  return ctx.sendMessage('book.chapter.page');
})

Bot dialog:

me  > /page1
bot > Page 1 text
me  > /page2
bot > Page 2 text
me  > /page3
bot > Page 3 text

Keyboards

You can set keyboard for context, command or bot.

// This keyboard is applied for any command.
// Also you can use emoji in keyboard.
bot.keyboard([
  [{':one: go page 1': {go: 'page1'}}],
  [{':two: go page 2': {go: 'page2'}}],
  [{':three: go page 3': {go: 'page3'}}]
])

bot.command('page1').invoke(function (ctx) {
  return ctx.sendMessage('This is page 1')
})

bot.command('page2').invoke(function (ctx) {
  return ctx.sendMessage('This is page 2')
}).keyboard([
  [{':one: go page 1': {go: 'page1'}}],
  [{':three: go page 3': {go: 'page3'}}]
])

bot.command('page3').invoke(function (ctx) {
  ctx.keyboard([
    [{':one: go page 1': {go: 'page1'}}]
    [{':two: go page 2': {go: 'page2'}}]
  ])
})

Going to command

You can go to any command via keyboard. First argument for go method is a command name.

bot.keyboard([[
  {'command1': {go: 'command1'}}
]])

isShown flag

isShown flag can be used to hide keyboard buttons in certain moment.

bot.use('before', function (ctx) {
  ctx.isButtonShown = Math.round() > 0.5;
}).keyboard([[
  {
    'text1': {
      go: 'command1',
      isShown: function (ctx) {
        return ctx.isButtonShown;
      }
    }
  }
]]);

Localization in keyboards

bot.texts({
  menu: {
    item1: ':one: page 1'
    item2: ':two: page 2'
  }
}).keyboard([
  [{'menu.item1': {go: 'page1'}}]
  [{'menu.item2': {go: 'page2'}}]
])

Keyboard templates

You can use keyboard templates

bot.keyboard('footer', [{':arrow_backward:': {go: 'start'}}])

bot.command('start', function (ctx) {
  ctx.sendMessage('Hello there')
}).keyboard([
  [{'Page 1': {go: 'page1'}}],
  [{'Page 2': {go: 'page2'}}]
])

bot.command('page1', function () {
  ctx.sendMessage('This is page 1')
})
.keyboard([
  [{'Page 2': {go: 'page2'}}],
  'footer'
])

bot.command('page2', function () {
  ctx.sendMessage('This is page 1')
})
.keyboard([
  [{'Page 1': {go: 'page1'}}],
  'footer'
])

Keyboard answers

If you want to handle a text answer from your keyboard, use following code:

bot.command('command1')
.invoke(function (ctx) {
  return ctx.sendMessage('Hello')
})
.keyboard([
  [{'answer1': 'answer1'}],
  [{'answer2': {value: 'answer2'}}],
  [{'answer3': 3}],
  [{'answer4': {value: 4}}]
])
.answer(function (ctx) {
  ctx.data.answer = ctx.answer;
  return ctx.sendMessage('Your answer is <%=answer%>');
});

Sometimes you want user to manually enter an answer. Use following code to do this:

// Use 'compliantKeyboard' flag.
bot.command('command1', {compliantKeyboard: true})
.use('before', function (ctx) {
  ctx.keyboard([
    [{'answer1': 1}],
    [{'answer2': 2}],
    [{'answer3': 3}],
    [{'answer4': 4}]
  ]);
})
.invoke(function (ctx) {
  return ctx.sendMessage('Answer me!')
})
.answer(function (ctx) {
  if (typeof ctx.answer === 'number') {
    return ctx.sendMessage('This is an answer from keyboard')
  } else {
    return ctx.sendMessage('This is not an answer from keyboard. Your answer is: ' + ctx.answer)
  }
});

Inline 2.0 keyboards

You can use inline keyboards in the same way as default keyboards

bot.bommand('inline_example')
.use('before', function (ctx) {
  // set any your data to callbackData.
  // IMPORTANT! Try to fit your data in 60 chars, because Telegram has limit for inline buttons 
  ctx.inlineKeyboard([[
    {'Option 1': {callbackData: {myVar: 1}, isShown: function (ctx) { return ctx.callbackData.myVar != 1 }}},
    {'Option 2': {callbackData: {myVar: 2}, isShown: function (ctx) { return ctx.callbackData.myVar != 2 }}},
    // use syntax:
    // 'callback${{CALLBACK_COMMAND}}' (or 'cb${{CALLBACK_COMMAND}}') 
    // 'invoke${{INVOKE_COMMAND}}'
    // to go to another command
    {'Option 3': {go: 'cb$go_inline_example'}},
    {'Option 4': {go: 'invoke$go_inline_example'}}
  ]])
})
.invoke(function (ctx) {
  ctx.sendMessage('Inline data example')
})
.callback(function (ctx) {
  ctx.updateText('Callback data: ' + ctx.callbackData.myVar)
})

bot.command('go_inline_example')
.invoke(function (ctx) {
  ctx.sendMessage('This command invoked directly')
})
.callback(function (ctx) {
  ctx.updateText('Command invoked via callback! type /inline_example to start again')
})

Api

There are three base classes:

  • Bot
  • Command
  • Context

Bot

Bot represents a bot.

var bb = require('bot-brother');
var bot = bb({
  key: '<TELEGRAM_BOT_TOKEN>',
  // optional
  webHook: {
    url: 'https://mybot.com/updates',
    key: '<PEM_PRIVATE_KEY>',
    cert: '<PEM_PUBLIC_KEY>',
    port: 443,
    https: true
  }
})

Has following methods and fields:

bot.api

bot.api is an instance of node-telegram-bot-api

bot.api.sendMessage(chatId, 'message');

bot.command

Creates a command.

bot.command('start').invoke(function (ctx) {
  ctx.sendMessage('Hello')
});

bot.keyboard

bot.keyboard([
  [{column1: 'value1'}]
  [{column2: {go: 'command1'}}]
])

bot.texts

Defined texts can be used in keyboards, messages, photo captions

bot.texts({
  key1: {
    embeddedKey2: 'Hello'
  }
})

// With localization.
bot.texts({
  key1: {
    embeddedKey2: 'Hello2'
  }
}, {locale: 'en'})

Using webHook

Webhook in telegram documentation: https://core.telegram.org/bots/api#setwebhook If your node.js process is running behind the proxy (nginx for example) use following code. We omit webHook.key parameter and run node.js on 3000 unsecure port.

var bb = require('bot-brother');
var bot = bb({
  key: '<TELEGRAM_BOT_TOKEN>',
  webHook: {
    // Your nginx should proxy this to 127.0.0.1:3000
    url: 'https://mybot.com/updates',
    cert: '<PEM_PUBLIC_KEY>',
    port: 3000,
    https: false
  }
})

Otherwise if your node.js server is available outside, use following code:

var bb = require('bot-brother');
var bot = bb({
  key: '<TELEGRAM_BOT_TOKEN>',
  webHook: {
    url: 'https://mybot.com/updates',
    cert: '<PEM_PUBLIC_KEY>',
    key: '<PEM_PRIVATE_KEY>',
    port: 443
  }
})

Command

bot.command('command1')
.invoke(function (ctx) {})
.answer(function (ctx) {})
.keyboard([[]])
.texts([[]])

Context

The context is the essence that runs through all middlewares. You can put some data in the context and use this data in the next handler. Context is passed as the first argument in all middleware handlers.

// this is handler is invoke
bot.use('before', function (ctx) {
  // 'ctx' is an instance of Context
  ctx.someProperty = 'hello';
});

bot.command('mycommand').invoke(function (ctx) {
  // You can use data from previous stage!
  ctx.someProperty === 'hello'; // true
});

You can put any property to context variable. But! You must observe the following rules:

  1. Property name can not start with an underscore. ctx._myVar - bad!, ctx.myVar - good.
  2. Names of properties should not overlap predefined properties or methods. ctx.session = 'Hello' - bad! ctx.mySession = 'Hello' - good.

Context properties

Context has following predefined properties available for reading. Some of them are available for editing. Let's take a look at them:

context.session

You can put any data in context.session. This data will be available in commands and middlewares invoked for the same user. Important! Currently for group chats session data is shared between all users in chat.

bot.command('hello').invoke(function (ctx) {
  return ctx.sendMessage('Hello! What is your name?');
}).answer(function (ctx) {
  // Sets user answer to session.name.
  ctx.session.name = ctx.answer;
  return ctx.sendMessage('OK! I got it.')
});

bot.command('bye').invoke(function (ctx) {
  return ctx.sendMessage('Bye ' + ctx.session.name);
});

This is how it works:

me  > /hello
bot > Hello! What is your name?
me  > John
bot > OK! I remembered it.
me  > /bye
bot > Bye John

context.data

This variable works when rendering message texts. For template rendering we use (ejs)[https://github.com/tj/ejs]. All the data you put in context.data is available in the templates.

bot.texts({
  hello: {
    world: {
      friend: 'Hello world, <%=name%>!'
    }
  }
});

bot.command('hello').invoke(function (ctx) {
  ctx.data.name = 'John';
  ctx.sendMessage('hello.world.friend');
});

This is how it works:

me  > /hello
bot > Hello world, John!

There is predefined method render in context.data. It can be used for rendering embedded keys:

bot.texts({
  hello: {
    world: {
      friend: 'Hello world, <%=name%>!',
      bye: 'Good bye, <%=name%>',
      message: '<%=render("hello.world.friend")%> <%=render("hello.world.bye")%>'
    }
  }
});

bot.command('hello').invoke(function (ctx) {
  ctx.data.name = 'John';
  ctx.sendMessage('hello.world.message');
});

Bot dialog:

me  > /hello
bot > Hello world, John! Good bye, John

context.meta

context.meta contains following fields:

context.command

Represents currently handled command. Has following properties:

  • name - the name of a command
  • args - arguments for a command
  • type - Can be invoke or answer. If handler is invoked with .withContext method, type is synthetic

Suppose that we have the following code:

bot.command('hello')
.invoke(function (ctx) {
  var args = ctx.command.args.join('-');
  var type = ctx.command.type;
  var name = ctx.command.name;
  return ctx.sendMessage('Type '+type+'; Name: '+name+'; Arguments: '+args);
})
.answer(function (ctx) {
  var type = ctx.command.type;
  var name = ctx.command.name;
  var answer = ctx.answer;
  ctx.sendMessage('Type '+type+'; Name: '+name+'; Answer: ' + answer)
});

The result is the following dialogue:

me  > /hello world dear friend
bot > Type: invoke; Name: hello; Arguments: world-dear-friend
me  > bye
bot > Type: answer; Name: hello; Answer: bye

Also you can pass args in this way

me  > /hello__world
bot > Type: invoke; Name: hello; Arguments: world
me  > bye
bot > Type: answer; Name: hello; Answer: bye

context.answer

This is an answer for a command. Context.answer is defined only when user answers with a text message.

context.message

Represents message object. For more details see: https://core.telegram.org/bots/api#message

context.bot

Bot instance

context.isRedirected

Boolean. This flag is set to 'true' when a command was achieved via go method (user did not type text /command in bot). Let's look at the following example:

bot.command('hello').invoke(function (ctx) {
  return ctx.sendMessage('Type something.')
})
.answer(function (ctx) {
  return ctx.go('world');
});

bot.command('world').invoke(function (ctx) {
  return ctx.sendMessage('isRedirected: ' + ctx.isRedirected);
});

User was typing something like this:

me  > /hello
bot > Type something
me  > lol
bot > isRedirected: true

context.isSynthetic

Boolean. This flag is true when we achieve the handler with .withContext method.

bot.use('before', function (ctx) {
  return ctx.sendMessage('isSynthetic before: ' + ctx.isSynthetic);
});

bot.command('withcontext', function (ctx) {
  return ctx.sendMessage('hello').then(function () {
    return bot.withContext(ctx.meta.sessionId, function (ctx) {
      return ctx.sendMessage('isSynthetic in handler: ' + ctx.isSynthetic);
    });
  });
})

Dialog with bot:

me  > /withcontext
bot > isSynthetic before: false
bot > hello
bot > isSynthetic before: true
bot > isSynthetic in handler: true

Context methods

Context has the following methods.

context.keyboard(keyboardDefinition)

Sets keyboard

ctx.keyboard([[{'command 1': {go: 'command1'}}]])

context.hideKeyboard()

ctx.hideKeyboard()

context.inlineKeyboard(keyboardDefinition)

Sets keyboard

ctx.inlineKeyboard([[{'command 1': {callbackData: {myVar: 2}}}]])

context.render(key, data)

Returns rendered text or key

ctx.texts({
  localization: {
    key: {
      name: 'Hi, <%=name%> <%=secondName%>'
    }
  }
})
ctx.data.name = 'John';
var str = ctx.render('localization.key.name', {secondName: 'Doe'});
console.log(str); // outputs 'Hi, John Doe'

context.go()

Returns Promise Goes to some command

var command1 = bot.command('command1')
var command2 = bot.command('command2').invoke(function (ctx) {
  // Go to command1.
  return ctx.go('command1');
})

context.goParent()

Returns Promise Goes to the parent command. A command is considered a descendant if its name begins with the parent command name, for example setting is a parent command, settings_locale is a descendant command.

var command1 = bot.command('command1')
var command1Child = bot.command('command1_child').invoke(function (ctx) {
  return ctx.goParent(); // Goes to command1.
});

context.goBack()

Returns Promise Goes to previously invoked command. Useful in keyboard 'Back' button.

bot.command('hello')
.answer(function (context) {
  return context.goBack()
})
// or
bot.keyboard([[
  {'Back': {go: '$back'}}
]])

context.repeat()

Returns Promise Repeats current state, useful for handling wrong answers.

bot.command('command1')
.invoke(function (ctx) {
  return ctx.sendMessage('How old are you?')
})
.answer(function (ctx) {
  if (isNaN(ctx.answer)) {
    return ctx.repeat(); // Sends 'How old are your?', calls 'invoke' handler.
  }
});

context.end()

Stops middlewares chain.

context.setLocale(locale)

Sets locale for the context. Use it if you need localization.

bot.texts({
  greeting: 'Hello <%=name%>!'
})
bot.use('before', function (ctx) {
  ctx.setLocale('en');
});

context.getLocale()

Returns current locale

context.sendMessage(text, [options])

Returns Promise Sends text message.

See: https://core.telegram.org/bots/api#sendmessage

Param Type Description
text String Text or localization key to be sent
[options] Object Additional Telegram query options

context.forwardMessage(fromChatId, messageId)

Returns Promise Forwards messages of any kind.

Param Type Description
fromChatId Number | String Unique identifier for the chat where the original message was sent
messageId Number | String Unique message identifier

context.sendPhoto(photo, [options])

Returns Promise Sends photo

See: https://core.telegram.org/bots/api#sendphoto

Param Type Description
photo String | stream.Stream A file path or a Stream. Can also be a file_id previously uploaded
[options] Object Additional Telegram query options

context.sendAudio(audio, [options])

Returns Promise Sends audio

See: https://core.telegram.org/bots/api#sendaudio

Param Type Description
audio String | stream.Stream A file path or a Stream. Can also be a file_id previously uploaded.
[options] Object Additional Telegram query options

context.sendDocument(A, [options])

Returns Promise Sends Document

See: https://core.telegram.org/bots/api#sendDocument

Param Type Description
A String | stream.Stream file path or a Stream. Can also be a file_id previously uploaded.
[options] Object Additional Telegram query options

context.sendSticker(A, [options])

Returns Promise Sends .webp stickers.

See: https://core.telegram.org/bots/api#sendsticker

Param Type Description
A String | stream.Stream file path or a Stream. Can also be a file_id previously uploaded.
[options] Object Additional Telegram query options

context.sendVideo(A, [options])

Returns Promise Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document).

See: https://core.telegram.org/bots/api#sendvideo

Param Type Description
A String | stream.Stream file path or a Stream. Can also be a file_id previously uploaded.
[options] Object Additional Telegram query options

context.sendVoice(voice, [options])

Returns Promise Sends voice

Kind: instance method of TelegramBot See: https://core.telegram.org/bots/api#sendvoice

Param Type Description
voice String | stream.Stream A file path or a Stream. Can also be a file_id previously uploaded.
[options] Object Additional Telegram query options

context.sendChatAction(action)

Returns Promise Sends chat action. typing for text messages, upload_photo for photos, record_video or upload_video for videos, record_audio or upload_audio for audio files, upload_document for general files, find_location for location data.

See: https://core.telegram.org/bots/api#sendchataction

Param Type Description
action String Type of action to broadcast.

context.getUserProfilePhotos([offset], [limit])

Returns Promise Use this method to get the list of profile pictures for a user. Returns a UserProfilePhotos object.

See: https://core.telegram.org/bots/api#getuserprofilephotos

Param Type Description
[offset] Number Sequential number of the first photo to be returned. By default, all photos are returned.
[limit] Number Limits the number of photos to be retrieved. Values between 1—100 are accepted. Defaults to 100.

context.sendLocation(latitude, longitude, [options])

Returns Promise Sends location. Use this method to send point on the map.

See: https://core.telegram.org/bots/api#sendlocation

Param Type Description
latitude Float Latitude of location
longitude Float Longitude of location
[options] Object Additional Telegram query options