node-facebook-messenger-api 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jshintrc +4 -0
- package/README.md +180 -0
- package/account-link-handler.js +176 -0
- package/example/public/index.html +8 -0
- package/example/server.js +87 -0
- package/messenger.js +768 -0
- package/node-facebook-messenger-api.js +15 -0
- package/package.json +37 -0
- package/screenshots/confirm-subscribe-page.png +0 -0
- package/screenshots/create-app.png +0 -0
- package/screenshots/create-page.png +0 -0
- package/screenshots/heroku-create.png +0 -0
- package/screenshots/page-access-token.png +0 -0
- package/screenshots/page-subscribed.png +0 -0
- package/screenshots/send-message-hi.png +0 -0
- package/screenshots/setup-messenger.png +0 -0
- package/screenshots/setup-webhooks.png +0 -0
- package/screenshots/subscribe-page.png +0 -0
- package/screenshots/webhook-config.png +0 -0
- package/test/analytics.test.js +157 -0
- package/webhook-handler.js +170 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
module.exports = {
|
4
|
+
messenger: function () {
|
5
|
+
return require('./messenger');
|
6
|
+
},
|
7
|
+
accountlinkHandler: function () {
|
8
|
+
return require('./account-link-handler');
|
9
|
+
},
|
10
|
+
webhookHandler: function () {
|
11
|
+
return require('./webhook-handler');
|
12
|
+
}
|
13
|
+
};
|
14
|
+
|
15
|
+
var messengerapi = require('./messenger');
|
package/package.json
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
{
|
2
|
+
"name": "node-facebook-messenger-api",
|
3
|
+
"version": "4.1.0",
|
4
|
+
"description": "Simple Node.js Facebook Messenger API",
|
5
|
+
"main": "node-facebook-messenger-api.js",
|
6
|
+
"scripts": {
|
7
|
+
"test": "jest"
|
8
|
+
},
|
9
|
+
"repository": {
|
10
|
+
"type": "git",
|
11
|
+
"url": "git://github.com/perusworld/node-facebook-messenger-api.git"
|
12
|
+
},
|
13
|
+
"keywords": [
|
14
|
+
"nodejs",
|
15
|
+
"facebook",
|
16
|
+
"messenger",
|
17
|
+
"api"
|
18
|
+
],
|
19
|
+
"author": "Saravana Perumal Shanmugam <saravanaperumal@msn.com>",
|
20
|
+
"license": "MIT",
|
21
|
+
"bugs": {
|
22
|
+
"url": "https://github.com/perusworld/node-facebook-messenger-api/issues"
|
23
|
+
},
|
24
|
+
"homepage": "https://github.com/perusworld/node-facebook-messenger-api",
|
25
|
+
"dependencies": {
|
26
|
+
"async": "^3.2.2",
|
27
|
+
"axios": "^1.8.3",
|
28
|
+
"debug": "^3.1.0",
|
29
|
+
"merge": "^2.1.1",
|
30
|
+
"request": "^2.81.0"
|
31
|
+
},
|
32
|
+
"devDependencies": {
|
33
|
+
"body-parser": "^1.20.1",
|
34
|
+
"express": "^4.18.2",
|
35
|
+
"jest": "^29.4.3"
|
36
|
+
}
|
37
|
+
}
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,157 @@
|
|
1
|
+
const fs = require('fs');
|
2
|
+
var async = require('async');
|
3
|
+
|
4
|
+
var messengerapi = require('../node-facebook-messenger-api').messenger();
|
5
|
+
|
6
|
+
beforeEach(() => {
|
7
|
+
//NOOP
|
8
|
+
});
|
9
|
+
|
10
|
+
afterEach(() => {
|
11
|
+
//NOOP
|
12
|
+
});
|
13
|
+
|
14
|
+
function getMessenger(logLevel) {
|
15
|
+
return new messengerapi.Messenger({
|
16
|
+
appSecret: 'appSecret',
|
17
|
+
validationToken: 'validationToken',
|
18
|
+
pageAccessToken: 'pageAccessToken',
|
19
|
+
urlPrefix: 'urlPrefix',
|
20
|
+
analyticsLogLevel: logLevel,
|
21
|
+
pageId: 'pageId',
|
22
|
+
appId: 'appId'
|
23
|
+
});
|
24
|
+
}
|
25
|
+
|
26
|
+
test('check none log', (done) => {
|
27
|
+
var messenger = getMessenger(messengerapi.ANALYTICS_LEVEL_NONE);
|
28
|
+
messenger.sendActivity = (payload, callback) => {
|
29
|
+
callback(null, { resp: true, statusCode: 200 }, "{\"success\":true}");
|
30
|
+
};
|
31
|
+
messenger.analyticsEvent(messengerapi.ANALYTICS_LEVEL_CRITICAL, 'blah', () => {
|
32
|
+
return {
|
33
|
+
_eventName: "wont't be called"
|
34
|
+
};
|
35
|
+
}, (err, resp) => {
|
36
|
+
expect(err).toBeNull();
|
37
|
+
expect(resp).not.toBeNull();
|
38
|
+
expect(resp.skip).toBeDefined();
|
39
|
+
expect(resp.skip).toBeTruthy();
|
40
|
+
done();
|
41
|
+
});
|
42
|
+
});
|
43
|
+
|
44
|
+
test('check verbose log', (done) => {
|
45
|
+
var messenger = getMessenger(messengerapi.ANALYTICS_LEVEL_VERBOSE);
|
46
|
+
messenger.sendActivity = (payload, callback) => {
|
47
|
+
callback(null, { resp: true, statusCode: 200 }, "{\"success\":true}");
|
48
|
+
};
|
49
|
+
messenger.analyticsEvent(messengerapi.ANALYTICS_LEVEL_VERBOSE, 'blah', () => {
|
50
|
+
return {
|
51
|
+
_eventName: "will be called"
|
52
|
+
};
|
53
|
+
}, (err, resp) => {
|
54
|
+
expect(err).toBeNull();
|
55
|
+
expect(resp).not.toBeNull();
|
56
|
+
expect(resp.success).toBeDefined();
|
57
|
+
expect(resp.success).toBeTruthy();
|
58
|
+
done();
|
59
|
+
});
|
60
|
+
});
|
61
|
+
|
62
|
+
test('check critical log', (done) => {
|
63
|
+
var messenger = getMessenger(messengerapi.ANALYTICS_LEVEL_CRITICAL);
|
64
|
+
messenger.sendActivity = (payload, callback) => {
|
65
|
+
callback(null, { resp: true, statusCode: 200 }, "{\"success\":true}");
|
66
|
+
};
|
67
|
+
messenger.analyticsEvent(messengerapi.ANALYTICS_LEVEL_CRITICAL, 'blah', () => {
|
68
|
+
return {
|
69
|
+
_eventName: "will be called"
|
70
|
+
};
|
71
|
+
}, (err, resp) => {
|
72
|
+
expect(err).toBeNull();
|
73
|
+
expect(resp).not.toBeNull();
|
74
|
+
expect(resp.success).toBeDefined();
|
75
|
+
expect(resp.success).toBeTruthy();
|
76
|
+
done();
|
77
|
+
});
|
78
|
+
});
|
79
|
+
|
80
|
+
test('check verbose on critical log', (done) => {
|
81
|
+
var messenger = getMessenger(messengerapi.ANALYTICS_LEVEL_CRITICAL);
|
82
|
+
messenger.sendActivity = (payload, callback) => {
|
83
|
+
callback(null, { resp: true, statusCode: 200 }, "{\"success\":true}");
|
84
|
+
};
|
85
|
+
messenger.analyticsEvent(messengerapi.ANALYTICS_LEVEL_VERBOSE, 'blah', () => {
|
86
|
+
return {
|
87
|
+
_eventName: "won't be called"
|
88
|
+
};
|
89
|
+
}, (err, resp) => {
|
90
|
+
expect(err).toBeNull();
|
91
|
+
expect(resp).not.toBeNull();
|
92
|
+
expect(resp.skip).toBeDefined();
|
93
|
+
expect(resp.skip).toBeTruthy();
|
94
|
+
done();
|
95
|
+
});
|
96
|
+
});
|
97
|
+
|
98
|
+
test('check critical on verbose log', (done) => {
|
99
|
+
var messenger = getMessenger(messengerapi.ANALYTICS_LEVEL_VERBOSE);
|
100
|
+
messenger.sendActivity = (payload, callback) => {
|
101
|
+
callback(null, { resp: true, statusCode: 200 }, "{\"success\":true}");
|
102
|
+
};
|
103
|
+
messenger.analyticsEvent(messengerapi.ANALYTICS_LEVEL_CRITICAL, 'blah', () => {
|
104
|
+
return {
|
105
|
+
_eventName: "will be called"
|
106
|
+
};
|
107
|
+
}, (err, resp) => {
|
108
|
+
expect(err).toBeNull();
|
109
|
+
expect(resp).not.toBeNull();
|
110
|
+
expect(resp.success).toBeDefined();
|
111
|
+
expect(resp.success).toBeTruthy();
|
112
|
+
done();
|
113
|
+
});
|
114
|
+
});
|
115
|
+
|
116
|
+
test('check unknown log', (done) => {
|
117
|
+
var messenger = getMessenger(messengerapi.ANALYTICS_LEVEL_VERBOSE);
|
118
|
+
messenger.sendActivity = (payload, callback) => {
|
119
|
+
callback(null, { resp: true, statusCode: 200 }, "{\"success\":true}");
|
120
|
+
};
|
121
|
+
messenger.analyticsEvent(10, 'blah', () => {
|
122
|
+
return {
|
123
|
+
_eventName: "won't be called"
|
124
|
+
};
|
125
|
+
}, (err, resp) => {
|
126
|
+
expect(err).toBeNull();
|
127
|
+
expect(resp).not.toBeNull();
|
128
|
+
expect(resp.skip).toBeDefined();
|
129
|
+
expect(resp.skip).toBeTruthy();
|
130
|
+
done();
|
131
|
+
});
|
132
|
+
});
|
133
|
+
|
134
|
+
test('check error', (done) => {
|
135
|
+
var messenger = getMessenger(messengerapi.ANALYTICS_LEVEL_VERBOSE);
|
136
|
+
messenger.sendActivity = (payload, callback) => {
|
137
|
+
callback({ error: true }, { resp: true, statusCode: 201 }, "{\"success\":false}");
|
138
|
+
};
|
139
|
+
messenger.analyticsEvent(messengerapi.ANALYTICS_LEVEL_VERBOSE, 'blah', () => {
|
140
|
+
return {
|
141
|
+
_eventName: "won't be called"
|
142
|
+
};
|
143
|
+
}, (err, resp) => {
|
144
|
+
expect(err).not.toBeNull();
|
145
|
+
expect(err[1].error).toBeTruthy();
|
146
|
+
expect(resp).toBeNull();
|
147
|
+
done();
|
148
|
+
});
|
149
|
+
});
|
150
|
+
|
151
|
+
test('check error quickAnalytics', () => {
|
152
|
+
var messenger = getMessenger(messengerapi.ANALYTICS_LEVEL_VERBOSE);
|
153
|
+
messenger.sendActivity = (payload, callback) => {
|
154
|
+
callback({ error: true }, { resp: true, statusCode: 201 }, "{\"success\":false}");
|
155
|
+
};
|
156
|
+
messenger.quickAnalytics(messengerapi.ANALYTICS_LEVEL_VERBOSE, 'blah', "won't be called");
|
157
|
+
});
|
@@ -0,0 +1,170 @@
|
|
1
|
+
const
|
2
|
+
error = require('debug')('error'),
|
3
|
+
debug = require('debug')('fb-webhook-handler'),
|
4
|
+
bodyParser = require('body-parser');
|
5
|
+
|
6
|
+
module.exports = function (messenger, messageHandler, verifySignature, ignores, router) {
|
7
|
+
|
8
|
+
if (verifySignature) {
|
9
|
+
router.use(bodyParser.json({
|
10
|
+
verify: function (req, res, buf) {
|
11
|
+
if (ignores && ignores.includes(req.url)) {
|
12
|
+
debug('Ignoring signature verification for', req.url);
|
13
|
+
} else {
|
14
|
+
if (messenger.verifySignature(req.headers["x-hub-signature"], buf)) {
|
15
|
+
//NOOP
|
16
|
+
} else {
|
17
|
+
throw new Error("Couldn't validate the request signature.");
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}));
|
22
|
+
} else {
|
23
|
+
router.use(bodyParser.json());
|
24
|
+
}
|
25
|
+
router.use(bodyParser.urlencoded({
|
26
|
+
extended: true
|
27
|
+
}));
|
28
|
+
|
29
|
+
/*
|
30
|
+
* Use your own validation token. Check that the token used in the Webhook
|
31
|
+
* setup is the same token used here.
|
32
|
+
*
|
33
|
+
*/
|
34
|
+
router.get('/webhook', function (req, res) {
|
35
|
+
if (req.query['hub.mode'] === 'subscribe' && messenger.matchToken(req.query['hub.verify_token'])) {
|
36
|
+
debug("Validating webhook");
|
37
|
+
res.status(200).send(req.query['hub.challenge']);
|
38
|
+
} else {
|
39
|
+
error("Failed validation. Make sure the validation tokens match.");
|
40
|
+
res.sendStatus(403);
|
41
|
+
}
|
42
|
+
});
|
43
|
+
|
44
|
+
/*
|
45
|
+
* All callbacks for Messenger are POST-ed. They will be sent to the same
|
46
|
+
* webhook. Be sure to subscribe your app to your page to receive callbacks
|
47
|
+
* for your page.
|
48
|
+
* https://developers.facebook.com/docs/messenger-platform/product-overview/setup#subscribe_app
|
49
|
+
*
|
50
|
+
*/
|
51
|
+
router.post('/webhook', function (req, res) {
|
52
|
+
try {
|
53
|
+
var data = req.body;
|
54
|
+
if (data.object == 'page') {
|
55
|
+
data.entry.forEach(function (pageEntry) {
|
56
|
+
var pageID = pageEntry.id;
|
57
|
+
var timeOfEvent = pageEntry.time;
|
58
|
+
pageEntry.messaging.forEach(function (messagingEvent) {
|
59
|
+
if (messagingEvent.optin) {
|
60
|
+
receivedAuthentication(messagingEvent);
|
61
|
+
} else if (messagingEvent.message) {
|
62
|
+
receivedMessage(messagingEvent);
|
63
|
+
} else if (messagingEvent.delivery) {
|
64
|
+
receivedDeliveryConfirmation(messagingEvent);
|
65
|
+
} else if (messagingEvent.postback) {
|
66
|
+
receivedPostback(messagingEvent);
|
67
|
+
} else if (messagingEvent.read) {
|
68
|
+
receivedMessageRead(messagingEvent);
|
69
|
+
} else if (messagingEvent.account_linking) {
|
70
|
+
receivedAccountLink(messagingEvent);
|
71
|
+
} else {
|
72
|
+
debug("Webhook received unknown messagingEvent: ", messagingEvent);
|
73
|
+
}
|
74
|
+
});
|
75
|
+
});
|
76
|
+
}
|
77
|
+
} catch (err) {
|
78
|
+
error(err);
|
79
|
+
}
|
80
|
+
res.sendStatus(200);
|
81
|
+
});
|
82
|
+
|
83
|
+
/*
|
84
|
+
* Authorization Event
|
85
|
+
*
|
86
|
+
* The value for 'optin.ref' is defined in the entry point. For the "Send to
|
87
|
+
* Messenger" plugin, it is the 'data-ref' field. Read more at
|
88
|
+
* https://developers.facebook.com/docs/messenger-platform/webhook-reference/authentication
|
89
|
+
*
|
90
|
+
*/
|
91
|
+
function receivedAuthentication(event) {
|
92
|
+
messageHandler.receivedAuthentication(event);
|
93
|
+
}
|
94
|
+
|
95
|
+
/*
|
96
|
+
* Message Event
|
97
|
+
*
|
98
|
+
* This event is called when a message is sent to your page. The 'message'
|
99
|
+
* object format can vary depending on the kind of message that was received.
|
100
|
+
* Read more at https://developers.facebook.com/docs/messenger-platform/webhook-reference/message-received
|
101
|
+
*
|
102
|
+
* For this example, we're going to echo any text that we get. If we get some
|
103
|
+
* special keywords ('button', 'generic', 'receipt'), then we'll send back
|
104
|
+
* examples of those bubbles to illustrate the special message bubbles we've
|
105
|
+
* created. If we receive a message with an attachment (image, video, audio),
|
106
|
+
* then we'll simply confirm that we've received the attachment.
|
107
|
+
*
|
108
|
+
*/
|
109
|
+
function receivedMessage(event) {
|
110
|
+
messageHandler.handleMessage(event);
|
111
|
+
}
|
112
|
+
|
113
|
+
|
114
|
+
/*
|
115
|
+
* Delivery Confirmation Event
|
116
|
+
*
|
117
|
+
* This event is sent to confirm the delivery of a message. Read more about
|
118
|
+
* these fields at https://developers.facebook.com/docs/messenger-platform/webhook-reference/message-delivered
|
119
|
+
*
|
120
|
+
*/
|
121
|
+
function receivedDeliveryConfirmation(event) {
|
122
|
+
messageHandler.receivedDeliveryConfirmation(event);
|
123
|
+
}
|
124
|
+
|
125
|
+
|
126
|
+
/*
|
127
|
+
* Postback Event
|
128
|
+
*
|
129
|
+
* This event is called when a postback is tapped on a Structured Message.
|
130
|
+
* https://developers.facebook.com/docs/messenger-platform/webhook-reference/postback-received
|
131
|
+
*
|
132
|
+
*/
|
133
|
+
function receivedPostback(event) {
|
134
|
+
messageHandler.receivedPostback(event);
|
135
|
+
}
|
136
|
+
|
137
|
+
/*
|
138
|
+
* Message Read Event
|
139
|
+
*
|
140
|
+
* This event is called when a previously-sent message has been read.
|
141
|
+
* https://developers.facebook.com/docs/messenger-platform/webhook-reference/message-read
|
142
|
+
*
|
143
|
+
*/
|
144
|
+
function receivedMessageRead(event) {
|
145
|
+
messageHandler.receivedMessageRead(event);
|
146
|
+
}
|
147
|
+
|
148
|
+
/*
|
149
|
+
* Account Link Event
|
150
|
+
*
|
151
|
+
* This event is called when the Link Account or UnLink Account action has been
|
152
|
+
* tapped.
|
153
|
+
* https://developers.facebook.com/docs/messenger-platform/webhook-reference/account-linking
|
154
|
+
*
|
155
|
+
*/
|
156
|
+
function receivedAccountLink(event) {
|
157
|
+
var status = event.account_linking.status;
|
158
|
+
|
159
|
+
if ('linked' == status) {
|
160
|
+
messageHandler.doLinking(event);
|
161
|
+
} else if ('unlinked' == status) {
|
162
|
+
messageHandler.doUnlinking(event);
|
163
|
+
} else {
|
164
|
+
error('unknown linking event', event);
|
165
|
+
}
|
166
|
+
|
167
|
+
}
|
168
|
+
|
169
|
+
return router;
|
170
|
+
};
|