-
Notifications
You must be signed in to change notification settings - Fork 0
/
statbot.js
119 lines (101 loc) · 3.53 KB
/
statbot.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
let Botkit = require('botkit');
//todo: unit test with https://github.com/spchuang/fb-local-chat-bot
module.exports = function(options){
if(!options.verify_token || !options.page_token || !options.app_secret || !options.page_scoped_user_id)
throw new Error("Fatal: missing required options for statbot initialization.");
let controller = Botkit.facebookbot({
debug: false,
log: true,
access_token: options.page_token,
verify_token: options.verify_token,
app_secret: options.app_secret,
validate_requests: true,
require_delivery: true,
receive_via_postback: true
});
let bot = controller.spawn({});
function listen(port, callback){
callback = callback || function(){};
//Catch-all from user (needs to be set up last I think?)
controller.on('message_received', function(bot, message) {
if(message.user == options.page_scoped_user_id)
bot.reply(message, 'Unknown command.');
});
//Set up receive webhook for Facebook
controller.setupWebserver(port, function(err, webserver) {
if(err)
callback(err);
webserver.get('/uptime', function(req, res){
res.sendStatus(200);
});
controller.createWebhookEndpoints(webserver, bot, function() {
console.log('Ready to receive messages on port ' + port);
callback(null);
});
});
}
let mutelist = new Set();
function mute(channel){
return mutelist.add(channel);
}
function unmute(channel){
return mutelist.delete(channel);
}
//Say things, with caching and a char limit.
//Channel length must be << CHAR_LIMIT for this to work properly.
var saycache = {};
const SAY_CACHE_DELAY = 1500; //ms
const CHAR_LIMIT = 640; //https://developers.facebook.com/docs/messenger-platform/send-api-reference#request
function say(channel, thing){
if(mutelist.has(channel))
return;
if(typeof thing !== "string")
thing = JSON.stringify(thing);
if(!saycache[channel])
saycache[channel] = {timeout: null, content: '[' + channel + ']'};
else
clearTimeout(saycache[channel].timeout);
//Sends only after a delay of no activity.
saycache[channel].timeout = setTimeout(function(){
raw_say(saycache[channel].content);
delete saycache[channel];
}, SAY_CACHE_DELAY);
//Append to the content.
saycache[channel].content += '\n' + thing.replace('\\n', '\n');
//If exceeds the CHAR_LIMIT, chunk off the extra from the beginning
while(saycache[channel].content.length >= CHAR_LIMIT){
raw_say(saycache[channel].content.slice(0, CHAR_LIMIT - 4) + '\n...');
saycache[channel].content = '[' + channel + ']\n' + saycache[channel].content.slice(CHAR_LIMIT - 4);
}
}
function raw_say(text){
bot.say({
text: text,
channel: options.page_scoped_user_id
}, function(err, response){
if (err)
throw JSON.stringify(err);
});
}
//Say things when heard things [this is just a special case; maybe make this a middleware?]
function hears(channel, matches, callback){
controller.hears(matches, 'message_received', function(bot, message){
if(message.user == options.page_scoped_user_id)
callback(message.text, say.bind(null, channel));
});
}
function use(middleware){
middleware(say);
}
return {
controller: controller,
mute: mute,
unmute: unmute,
mutelist: mutelist,
say: say,
hears: hears,
listen: listen,
use: use,
};
}
module.exports.logtail = require('./botbits/logtail');