Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
@chatbots-pl/powerbot-messenger
Advanced tools
A package for Messenger Platform support in Node.js
Table of contents generated with markdown-toc
const PowerbotMessenger = require('@chatbots-pl/powerbot-messenger')
const pbm = new PowerbotMessenger({
access_token: config.facebook.access_token
})
Configuration object should be passed like new PowerbotMessenger(configObject)
.
Name | Descrition | Type | Default |
---|---|---|---|
access_token | App's access token for desired page | string | null |
api_version | Graph API version to use inrequests | string | 'v5.0' |
endpoint | Sets endpoint to listen on | string | '/webhook' |
log_level | Logging level, one of: debug, info, warning, error or off | string | 'debug' |
log_to_console | Enables or disables Powerbot Messenger logger console output | bool | true |
mark_seen | Automatically check received messages as seen | bool | true |
natural_typing_speed | Speed of message typing in characters per second | int | 50 |
natural_typing | Enable or disable natural typing feature | bool | true |
const Koa = require('koa')
const bodyParser = require('koa-bodyparser')
const PowerbotMessenger = require('@chatbots-pl/powerbot-messenger')
const pbm = new PowerbotMessenger(config)
const app = new Koa()
const messengerWebhook = pbm.Server.init()
app.use(bodyParser())
app.use(messengerWebhook.router.routes())
app.listen(3000)
Now server is listening on /webhook
. Your console should display your verify token.
Server always returns status 200 to facebook!
pbm.Server.init()
returns object with server and bot properties.
routes
property is passed from PowerbotMessenger Koa Router instance.
bot
property is event listener which is designed to catch server events.
Catching events after starting a server is as simple as:
bot.on('text', async (message, raw) => {
...
})
Event | Description | Passed parameters |
---|---|---|
request_incoming | Every request to your webhook | body , ctx |
request_outgoing | Every request sent from bot via Powerbot Messenger library | body , ctx |
log | Any log from Powerbot Messenger (except throwed errors) | logObject |
message_sent | Every message sent from bot via Powerbot Messenger library | body , ctx |
entry | Each entry in received object | entry |
echo | Any message sent by bot (every message with is_echo: true ) | formedMessage , rawMessage |
message | Any message received (each object of entry.messaging ) | formedMessage , rawMessage |
text | Text message received | formedMessage , rawMessage |
location | Each message attachment with type: 'location' | formedMessage , rawMessage |
image | Each message attachment with type: 'image' | formedMessage , rawMessage |
video | Each message attachment with type: 'video' | formedMessage , rawMessage |
audio | Each message attachment with type: 'audio' | formedMessage , rawMessage |
file | Each message attachment with type: 'file' | formedMessage , rawMessage |
fallback | Each message attachment not recognized by messenger platform | formedMessage , rawMessage |
payload | Any payload received (button or quick reply) | formedMessage , rawMessage |
postback | Payload from button reveived | formedMessage , rawMessage |
quick_reply | Payload from quick reply received | formedMessage , rawMessage |
referral | Referral received from m.me link | formedMessage , rawMessage |
change | Each change in received object (ex. new comment on page) | rawChange |
comment | New comment created on page | formedChange , rawChange |
post | New user post created on page | formedChange , rawChange |
optin | Each message containing optin property | formedMessage , rawMessage |
one_time_notif_req | Each message containing token for One Time Notification | formedMessage , rawMessage |
message_read | Each request with information about message read | formedMessage , rawMessage |
handover_thread_received | Chatbot received thread ownership for a user | formedMessage , rawMessage |
handover_thread_taken | Thread ownership for a user has been taken away by another application | formedMessage , rawMessage |
handover_thread_requested | Some app asks to take thread ownership for a user. | formedMessage , rawMessage |
handover_roles_changed | Administrator of connected page changed Handover Protocol role of chatbot. | formedMessage , rawMessage |
standby_message | Same as message but received on standby subscription channel | formedMessage , rawMessage |
standby_message_read | Same as message_read but received on standby subscription channel | formedMessage , rawMessage |
standby_location | Same as location but received on standby subscription channel | formedMessage , rawMessage |
standby_image | Same as image but received on standby subscription channel | formedMessage , rawMessage |
standby_video | Same as video but received on standby subscription channel | formedMessage , rawMessage |
standby_audio | Same as audio but received on standby subscription channel | formedMessage , rawMessage |
standby_file | Same as file but received on standby subscription channel | formedMessage , rawMessage |
standby_fallback | Same as fallback but received on standby subscription channel | formedMessage , rawMessage |
standby_postback | Same as postback but received on standby subscription channel | formedMessage , rawMessage |
standby_quick_reply | Same as quick_reply but received on standby subscription channel | formedMessage , rawMessage |
standby_payload | Same as payload but received on standby subscription channel | formedMessage , rawMessage |
standby_text | Same as text but received on standby subscription channel | formedMessage , rawMessage |
standby_echo | Same as echo but received on standby subscription channel | formedMessage , rawMessage |
As you probably noticed in table above,a lot of events have passed data named formedMessage
and rawMessage
. First object is object created by Powerbot Messenger library containing most useful informations like sender, type or content. It also contains reply
(and handover
, check Handover methods as reply for more information) object which allows you to reply to the message sender without passing recipient id. Second object is unmodified object received from Messenger Platform.
Handover events that with associated user id (handover_thread_*
) are treated like messaging events. This means, that first parameter of event callback has reply
and handover
fields.
For example, some app wants to take thread control to talk with user. You want to inform user about this and then pass thread control to this app:
bot.on('handover_thread_requested', async (ev, raw) => {
try {
await ev.reply.text('Some app wants to talk to you, passing thread control...')
await ev.handover.passThreadControl('263902037430900')
} catch(e) {
console.error(e)
}
})
pbm.send.METHOD()
// OR
message.reply.METHOD()
Each method last parameter is option parameter, which is object. In this object you can pass recipient_id and messaging_type. (Options object will be propably changed soon)
It's recommended to use sender with Powerbot Messenger helpers which allows you to create messeges in a clean way.
All examples below are presented as replying to message
text(message, options)
Sends text to client
await message.reply.text('Your message')
quickReplies(message, replies, options)
Sends quick replies to client.
let qrs = [
new pbm.Helpers.QuickReply('text', 'Yes', 'ANSWER_YES')
new pbm.Helpers.QuickReply('text', 'No', 'ANSWER_NO')
]
await message.reply.quickReplies('Your message', qrs)
buttons(text, buttons, options)
Sends buttons template to user
let buttons = [
new pbm.Helpers.Button('postback', 'Some postback', 'POSTBACK')
new pbm.Helpers.Button('web_url', 'Some link', 'http://example.com')
]
await message.reply.buttons('Your message', buttons)
attachment(type, url, options)
Sends attachment to user
await message.reply.attachment('image', 'https://example.com/assets/image.png')
generic(elements, options)
Sends generic template to user.
let buttons = [
new pbm.Helpers.Button('postback', 'Button no.1', 'PAYLOAD'),
new pbm.Helpers.Button('web_url', 'Button no.2', 'https://example.com/')
]
let card1 = {
title: 'Card One',
subtitle: 'Subtitle no. 1',
image_url: 'https://example.com/images/1.png',
buttons: buttons
}
let cards = [
new pbm.Helpers.Generic(card1),
new pbm.Helpers.Generic('Card Two', 'Subtitle no.2', 'https://example.com/images/2.png', buttons)
]
await message.reply.generic(cards)
media(element, options)
Sends media element to user
const o = {
buttons: [new pbm.Helpers.Button('web_url', 'URL', '<URL_ADDRESS>'), new pbm.Helpers.Button('postback', 'PAYLOAD', '<DEV_PAYLOAD>')],
url: '<URL_TO_MEDIA>',
media_type: 'image'
}
await message.reply.media(o)
oneTimeNotificationRequest (title, payload, options)
Sends One Time Notification request to user
await message.reply.oneTimeNotificationRequest('Get notified when something happened...', 'MY_PAYLOAD')
Using helpers is the easiest way to send desired message to facebook. Helpers are returning object for
Actually, this helper supports following types of buttons:
new pbm.Helpers.Button(type, title, payload)
let postback = new pbm.Helpers.Button('postback', 'Send Payload', 'PAYLOAD')
let web_url = new pbm.Helpers.Button('web_url', 'Go', 'https://example.com/')
let phone_number = new pbm.Helpers.Button('phone_number', 'Call Us', '+15105559999')
let share = new pbm.Helpers.Button('element_share')
let login = new pbm.Helpers.Button('account_link', 'https://example.com/auth')
let logout = new pbm.Helpers.Button('account_unlink')
As first argument of generic message helper you can pass object or string.
new pbm.Helpers.Generic(title, subtitle, image_url, buttons, default_action)
let card1 = {
title: 'Card One',
subtitle: 'Subtitle no. 1',
image_url: 'https://example.com/images/1.png',
buttons: [...]
}
let cards = [
new pbm.Helpers.Generic(card1),
new pbm.Helpers.Generic('Card Two', 'Subtitle no.2', 'image_url', buttons)
]
As first argument of media message helper you can pass object or string.
new pbm.Helpers.Media(type, url|attachemnt_id, buttons)
const o = {
buttons: [new pbm.Helpers.Button('web_url', 'URL', '<URL_ADDRESS>'), new pbm.Helpers.Button('postback', 'PAYLOAD', '<DEV_PAYLOAD>')],
url: '<URL_TO_MEDIA>',
media_type: 'image'
}
const m = new pbm.Helpers.Media(o) // Single media element, this is automatically wrapped in normal usage
As argument you can pass own paylod, default payload is 'GET_STARTED'.
new pbm.Helpers.GetStartedButton(payload)
let get_started = new bot.Helpers.GetStartedButton('OWN_PAYLOAD')
You can pass locale string as second argument, default locale string: default
new pbm.Helpers.Greeting(text, locale)
let greeting = new bot.Helpers.Greeting('Greeting text', 'zh_CN')
new pbm.Helpers.QuickReply(type, title, payload, image_url)
let qr = new bot.Helpers.QuickReply('text', 'Start!', 'START')
pbm.User(messenger_id)
allows to perform some basic operations on specific user.
You can fetch user data like first_name
, gender
, etc with .getData(...fields)
method.
let data = awiat pbm.User(this.data.messenger_id).getData('first_name', 'last_name', 'id')
Attention! Remember that for some fields like gender you need special permissions from facebook, unless your request will fail with status code 400!
You can send message directly to messenger id using User's send object. The rules are the same as using send or reply object.
const user = pbm.User(message.sender_id)
await user.send.text('Hi!')
You can call handover methods for managing thread with User
object:
const user = pbm.User(message.sender_id)
// Pass user's thread control to another app:
await user.handover.passThreadControl(123456789, 'optional metadata')
// Request user's thread control:
await user.handover.requestThreadControl('optional metadata')
// Take control over user's thread:
await user.handover.takeThreadControl('optional metadata')
Powerbot Messenger allows you to easily set static elements of your bot, like Get Started Button, Greeting text or persistent menu.
pbm.send.setting(data)
This function allows you to send any object to graph apip /me/messenger_profile
endpoint. To easily send basic elements to API use Helpers as shown below.
let greeting = new bot.Helpers.Greeting('This is greeting text!')
await pbm.send.setting(greeting)
let get_started = new bot.Helpers.GetStartedButton()
await pbm.send.setting(get_started)
Actually, Powerbot Messenger hasn't got any helper for menu, so you have to craft menu object on your own and then send it.
let menu = {
persistent_menu: [{
locale: "default",
call_to_actions: [{
title: "Options",
type: "postback",
payload: "OPTIONS"
}]
}]
}
await pbm.send.setting(menu)
Powerbot supports Personas API since version v1.1.0. Library can create and delete personas and utilize them with sender module.
const personaId = await pbm.personas.create('Persona name', '<IMAGE_URL>')
await pbm.personas.delete('<IMAGE_URL>')
await message.reply.attachment('image', '<ATTACHMENT_URL|ATTACHMENT_ID>', { persona_id: '<PERSONA_ID>' })
const message = new pbm.Message.Text('Text message created with Generator class')
const framedMessage = new pbm.Frame(message, '1489852771114961', {
persona_id: '<PERSONA_ID>'
})
await pbm.send.raw(framedMessage)
Powerbot Messenger by default sets timeout to your messages that contiant text and displays typing animation to client. This feature is turned on by default and can be configured vie config object passed to Powerbot Messenger instance.
Generator module was created to easily create messages for Broadcast API Creative Messages, but it can be also used to create advanced or unusual messages that are not covered by send methods and helpers. In brief, generator return message in facebook format which you can edit.
Generator module is accessible as Message object (pbm.Message
)
pbm.Message.Text(text, options)
const message = new pbm.Message.Text('This is message created with generator module')
pbm.Message.QuickReplies(text, replies, options)
const replies = [
new pbm.Helpers.QuickReply('text', 'Super', 'PAYLOAD_1'),
new pbm.Helpers.QuickReply('text', 'Ok', 'PAYLOAD_2')
]
const message = new pbm.Message.QuickReplies('This is message created with generator module', replies)
pbm.Message.Buttons(text, buttons, quick_replies, options)
If quick_replies parameter is not an array it's interpreted as options object!
const buttons = [
new pbm.Helpers.Button('postback', 'Button 1', 'PAYLOAD_1'),
new pbm.Helpers.Button('postback', 'Button 2', 'PAYLOAD_2')
]
const message = new pbm.Message.QuickReplies('This is message created with generator module', buttons)
pbm.Message.Generic(elements, options)
const card = {
title: 'Card',
subtitle: 'Subtitle',
image_url: 'https://example.com/images/1.png',
buttons: [...]
}
const cards = [card, card, card]
const message = new pbm.Message.Generic(cards)
pbm.Message.Media(element, options)
const o = {
buttons: [new pbm.Helpers.Button('web_url', 'URL', '<URL_ADDRESS>'), new pbm.Helpers.Button('postback', 'PAYLOAD', '<DEV_PAYLOAD>')],
url: '<URL_TO_MEDIA>',
media_type: 'image'
}
const m = new pbm.Helpers.Media(o) // Single media element, this is automatically wrapped in normal usage
const message = new pbm.Message.Media(m) // Wrapped here
pbm.Message.oneTimeNotificationRequest (title, payload, options)
const message = new pbm.Message.oneTimeNotificationRequest('Get notified when something happened...', 'MY_PAYLOAD')
pbm.Frame(message, recipient_id, options)
Above examples of supported messages shows how to use Generator module. Any generator returns only message body. It means that there isn's recipient object etc and message is compatible only with Broadcast API Creative Message (which is depracated now). If you want to send message from creator as reply to message you will have to use MessageFrame class, which is accessible as pbm.Frame
When message is in frame you can send it using pbm.send.raw()
or message.reply.raw()
(if reply object is available). This is exactly the same, because message in frame has already defined recipient id.
options
Option | Type | Description |
---|---|---|
messaging_type | String | Messaging type param, if desired other than 'RESPONSE' |
tag | String | Message tag in case of messaging_type set to 'MESSAGE_TAG' |
As options you can pass also string, which will be treated as tag
. In that case, messaging_type will be automatically set to 'MESSAGE_TAG'.
const message = new pbm.Message.Text('Text message created with Generator class')
const framedMessage = new pbm.Frame(message, '1489852771114961')
await pbm.send.raw(framedMessage)
const message = new pbm.Message.Text('Text message created with Generator class')
const framedMessage = new pbm.Frame(message, '1489852771114961', {
messaging_type: 'MESSAGE_TAG',
tag: 'NON_PROMOTIONAL_SUBSCRIPTION'
})
await pbm.send.raw(framedMessage)
const message = new pbm.Message.Text('Text message created with Generator class')
const framedMessage = new pbm.Frame(message, '1489852771114961', 'NON_PROMOTIONAL_SUBSCRIPTION')
await pbm.send.raw(framedMessage)
Powerbot handles requests to handover protocol API. Assume that message
in all of the following examples is message
object received in .on('text')
pbm.handover.passControl(appId, userId, metadata)
await pbm.handover.passControl(123456789, message.sender_id)
// Or with metadata:
await pbm.handover.passControl(123456789, message.sender_id, 'some data here')
pbm.handover.takeControl(userId, metadata)
await pbm.handover.takeControl(message.sender_id)
// Or with metadata:
await pbm.handover.takeControl(message.sender_id, 'some data here')
pbm.handover.requestControl(userId, metadata)
await pbm.handover.requestControl(message.sender_id)
// Or with metadata:
await pbm.handover.requestControl(message.sender_id, 'some data here')
pbm.handover.getSecondaryReceivers(...fields)
const data = await pbm.handover.getSecondaryReceivers()
// Or with fileds:
const another = await pbm.handover.getSecondaryReceivers('id', 'name')
pbm.handover.getOwner(userId)
const data = await pbm.handover.getOwner(message.sender_id)
Listed below methods are available as reply to incoming messages (just like message.reply
).
// Pass sender's thread control to another app:
await message.handover.passThreadControl(123456789, 'optional metadata')
// Request sender's thread control:
await message.handover.requestThreadControl('optional metadata')
// Take control over sender's thread:
await message.handover.takeThreadControl('optional metadata')
In some cases handover reply object can be supplied without recipient_id. In such case above functions will throw Graph API Error.
You can receive and reply to comments and posts created on your fanpage. Of corse you will need manage_pages
permission and feed
activated for your webhook.
Powerbot has 2 events to perform that actions - comment
and post
. Reply method of both supports all messages types available in Sender
class.
bot.on('comment', async comment => {
await comment.reply.buttons('Comment message with buttons', [new pbMessenger.Helpers.Button('postback', 'Button title', '<PAYLOAD>')])
})
bot.on('post', async post => {
await post.reply.buttons('post message with buttons', [new pbMessenger.Helpers.Button('postback', 'Button title', '<PAYLOAD>')])
})
Module for uploading attachments via Attachments API
pbm.upload.fromUrl(type, url)
Sends attachment upload request and return uploaded attachment ID. Type param must be supported by Attachments API.
const Koa = require('koa')
const bodyParser = require('koa-bodyparser')
const PowerbotMessenger = require('@chatbots-pl/powerbot-messenger')
const pbm = new PowerbotMessenger({
access_token: '<ACCESS_TOKEN>'
})
const app = new Koa()
const messengerWebhook = pbm.Server.init()
const bot = messengerWebhook.bot
bot.on('message', async (message) => {
try {
await message.reply.text(message.text)
} catch (e) {
console.error(e)
}
})
app.use(bodyParser())
app.use(messengerWebhook.router.routes())
app.listen(3000)
This software is licensed under MIT License.
FAQs
A package for Messenger Platform support in Node.js
The npm package @chatbots-pl/powerbot-messenger receives a total of 106 weekly downloads. As such, @chatbots-pl/powerbot-messenger popularity was classified as not popular.
We found that @chatbots-pl/powerbot-messenger demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.