alicezetion 1.0.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.
Files changed (49) hide show
  1. package/.cache/replit/__replit_disk_meta.json +1 -0
  2. package/.cache/replit/modules.stamp +0 -0
  3. package/.cache/replit/nix/env.json +1 -0
  4. package/.travis.yml +6 -0
  5. package/README.md +40 -0
  6. package/alice/add.js +99 -0
  7. package/alice/admin.js +65 -0
  8. package/alice/archive.js +41 -0
  9. package/alice/block.js +72 -0
  10. package/alice/chat.js +415 -0
  11. package/alice/color.js +53 -0
  12. package/alice/deletegc.js +43 -0
  13. package/alice/deletemsg.js +43 -0
  14. package/alice/delivered.js +41 -0
  15. package/alice/emoji.js +41 -0
  16. package/alice/emojiurl.js +29 -0
  17. package/alice/forward.js +47 -0
  18. package/alice/friend.js +70 -0
  19. package/alice/gchistorydeprecated.js +76 -0
  20. package/alice/gcimage.js +115 -0
  21. package/alice/gcimg.js +66 -0
  22. package/alice/gcinfo.js +170 -0
  23. package/alice/gcinfodeprecated.js +65 -0
  24. package/alice/gclist.js +220 -0
  25. package/alice/gclistdeprecated.js +75 -0
  26. package/alice/gcolor.js +22 -0
  27. package/alice/gcsearch.js +39 -0
  28. package/alice/history.js +632 -0
  29. package/alice/id.js +7 -0
  30. package/alice/kick.js +65 -0
  31. package/alice/listen.js +553 -0
  32. package/alice/listenMqtt.js +560 -0
  33. package/alice/logout.js +59 -0
  34. package/alice/msgrequest.js +51 -0
  35. package/alice/mute.js +38 -0
  36. package/alice/nickname.js +44 -0
  37. package/alice/poll.js +55 -0
  38. package/alice/react.js +82 -0
  39. package/alice/read.js +52 -0
  40. package/alice/resolveimgurl.js +31 -0
  41. package/alice/seen.js +36 -0
  42. package/alice/title.js +73 -0
  43. package/alice/typeindicator.js +77 -0
  44. package/alice/unsend.js +35 -0
  45. package/alice/userid.js +52 -0
  46. package/alice/userinfo.js +57 -0
  47. package/index.js +423 -0
  48. package/package.json +70 -0
  49. package/utils.js +1283 -0
@@ -0,0 +1,560 @@
1
+ /* eslint-disable no-redeclare */
2
+ "use strict";
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+ var mqtt = require('mqtt');
6
+ var websocket = require('websocket-stream');
7
+
8
+ var identity = function () {};
9
+
10
+ //Don't really know what this does but I think it's for the active state
11
+ //TODO: Move to ctx when implemented
12
+ var chatOn = true;
13
+ var foreground = false;
14
+
15
+ var topics = [
16
+ "/t_ms",
17
+ "/thread_typing",
18
+ "/orca_typing_notifications",
19
+ "/orca_presence",
20
+ "/legacy_web",
21
+ "/br_sr",
22
+ "/sr_res",
23
+ "/webrtc",
24
+ "/onevc",
25
+ "/notify_disconnect",
26
+ "/inbox",
27
+ "/mercury",
28
+ "/messaging_events",
29
+ "/orca_message_notifications",
30
+ "/pp",
31
+ "/webrtc_response",
32
+ ];
33
+
34
+ function listenMqtt(defaultFuncs, bot, ctx, globalCallback) {
35
+ var sessionID = Math.floor(Math.random() * 9007199254740991) + 1;
36
+ var username = {
37
+ u: ctx.userID,
38
+ s: sessionID,
39
+ chat_on: chatOn,
40
+ fg: foreground,
41
+ d: utils.getGUID(),
42
+ ct: "websocket",
43
+ //App id from facebook
44
+ aid: "219994525426954",
45
+ mqtt_sid: "",
46
+ cp: 3,
47
+ ecp: 10,
48
+ st: topics,
49
+ pm: [],
50
+ dc: "",
51
+ no_auto_fg: true,
52
+ gas: null
53
+ };
54
+ var cookies = ctx.jar.getCookies("https://www.facebook.com").join("; ");
55
+
56
+ //Region could be changed for better ping. (Region atn: Southeast Asia, region ash: West US, prob) (Don't really know if we need it).
57
+ //// var host = 'wss://edge-chat.facebook.com/chat?region=atn&sid=' + sessionID;
58
+ var host = 'wss://edge-chat.facebook.com/chat?sid=' + sessionID;
59
+
60
+ var options = {
61
+ clientId: "mqttwsclient",
62
+ protocolId: 'MQIsdp',
63
+ protocolVersion: 3,
64
+ username: JSON.stringify(username),
65
+ clean: true,
66
+ wsOptions: {
67
+ headers: {
68
+ 'Cookie': cookies,
69
+ 'Origin': 'https://www.facebook.com',
70
+ 'User-Agent': ctx.globalOptions.userAgent,
71
+ 'Referer': 'https://www.facebook.com',
72
+ 'Host': 'edge-chat.facebook.com'
73
+ },
74
+ origin: 'https://www.facebook.com',
75
+ protocolVersion: 13
76
+ }
77
+ };
78
+
79
+ ctx.mqttClient = new mqtt.Client(_ => websocket(host, options.wsOptions), options);
80
+
81
+ var mqttClient = ctx.mqttClient;
82
+
83
+ mqttClient.on('error', function(err) {
84
+ log.error(err);
85
+ mqttClient.end();
86
+ globalCallback("Connection refused: Server unavailable", null);
87
+ });
88
+
89
+ mqttClient.on('connect', function() {
90
+ var topic;
91
+ var queue = {
92
+ sync_api_version: 10,
93
+ max_deltas_able_to_process: 1000,
94
+ delta_batch_size: 500,
95
+ encoding: "JSON",
96
+ entity_fbid: ctx.userID,
97
+ };
98
+
99
+ if(ctx.globalOptions.pageID) {
100
+ queue.entity_fbid = ctx.globalOptions.pageID;
101
+ }
102
+
103
+ if(ctx.syncToken) {
104
+ topic = "/messenger_sync_get_diffs";
105
+ queue.last_seq_id = ctx.lastSeqId;
106
+ queue.sync_token = ctx.syncToken;
107
+ } else {
108
+ topic = "/messenger_sync_create_queue";
109
+ queue.initial_titan_sequence_id = ctx.lastSeqId;
110
+ queue.device_params = null;
111
+ }
112
+
113
+ mqttClient.publish(topic, JSON.stringify(queue), {qos: 1, retain: false});
114
+ });
115
+
116
+ mqttClient.on('message', function(topic, message, packet) {
117
+ var jsonMessage = JSON.parse(message);
118
+ if(topic === "/t_ms") {
119
+ if(jsonMessage.firstDeltaSeqId && jsonMessage.syncToken) {
120
+ ctx.lastSeqId = jsonMessage.firstDeltaSeqId;
121
+ ctx.syncToken = jsonMessage.syncToken;
122
+ }
123
+
124
+ if(jsonMessage.lastIssuedSeqId) {
125
+ ctx.lastSeqId = parseInt(jsonMessage.lastIssuedSeqId);
126
+ }
127
+
128
+ if(jsonMessage.queueEntityId && ctx.globalOptions.pageID &&
129
+ ctx.globalOptions.pageID != jsonMessage.queueEntityId) {
130
+ return;
131
+ }
132
+
133
+ //If it contains more than 1 delta
134
+ for (var i in jsonMessage.deltas) {
135
+ var delta = jsonMessage.deltas[i];
136
+ parseDelta(defaultFuncs, api, ctx, globalCallback, { "delta": delta });
137
+ }
138
+ } else if (topic === "/thread_typing" || topic === "/orca_typing_notifications") {
139
+ var typ = {
140
+ type: "typ",
141
+ isTyping: !!jsonMessage.state,
142
+ from: jsonMessage.sender_fbid.toString(),
143
+ threadID: utils.formatID((jsonMessage.thread || jsonMessage.sender_fbid).toString())
144
+ };
145
+ (function () { globalCallback(null, typ); })();
146
+ } else if (topic === "/orca_presence") {
147
+ if (!ctx.globalOptions.updatePresence) {
148
+ for (var i in jsonMessage.list) {
149
+ var data = jsonMessage.list[i];
150
+ var userID = data["u"];
151
+
152
+ var presence = {
153
+ type: "presence",
154
+ userID: userID.toString(),
155
+ //Convert to ms
156
+ timestamp: data["l"] * 1000,
157
+ statuses: data["p"]
158
+ };
159
+ (function () { globalCallback(null, presence); })();
160
+ }
161
+ }
162
+ }
163
+
164
+ });
165
+
166
+ mqttClient.on('close', function() {
167
+ // client.end();
168
+ });
169
+ }
170
+
171
+ function parseDelta(defaultFuncs, api, ctx, globalCallback, v) {
172
+ if(v.delta.class == "NewMessage") {
173
+ (function resolveAttachmentUrl(i) {
174
+ // sometimes, with sticker message in group, delta does not contain 'attachments' property.
175
+ if (v.delta.attachments && (i == v.delta.attachments.length)) {
176
+ var fmtMsg;
177
+ try {
178
+ fmtMsg = utils.formatDeltaMessage(v);
179
+ } catch (err) {
180
+ return globalCallback({
181
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
182
+ detail: err,
183
+ res: v,
184
+ type: "parse_error"
185
+ });
186
+ }
187
+ if (fmtMsg) {
188
+ if (ctx.globalOptions.autoMarkDelivery) {
189
+ markDelivery(ctx, api, fmtMsg.threadID, fmtMsg.messageID);
190
+ }
191
+ }
192
+ return !ctx.globalOptions.selfListen &&
193
+ fmtMsg.senderID === ctx.userID ?
194
+ undefined :
195
+ (function () { globalCallback(null, fmtMsg); })();
196
+ } else {
197
+ if (
198
+ v.delta.attachments && (v.delta.attachments[i].mercury.attach_type == "photo")
199
+ ) {
200
+ api.resolvePhotoUrl(
201
+ v.delta.attachments[i].fbid,
202
+ (err, url) => {
203
+ if (!err)
204
+ v.delta.attachments[
205
+ i
206
+ ].mercury.metadata.url = url;
207
+ return resolveAttachmentUrl(i + 1);
208
+ }
209
+ );
210
+ } else {
211
+ return resolveAttachmentUrl(i + 1);
212
+ }
213
+ }
214
+ })(0);
215
+ }
216
+
217
+ if (v.delta.class == "ClientPayload") {
218
+ var clientPayload = utils.decodeClientPayload(
219
+ v.delta.payload
220
+ );
221
+ if (clientPayload && clientPayload.deltas) {
222
+ for (var i in clientPayload.deltas) {
223
+ var delta = clientPayload.deltas[i];
224
+ if (delta.deltaMessageReaction && !!ctx.globalOptions.listenEvents) {
225
+ (function () { globalCallback(null, {
226
+ type: "message_reaction",
227
+ threadID: (delta.deltaMessageReaction.threadKey
228
+ .threadFbId ?
229
+ delta.deltaMessageReaction.threadKey.threadFbId : delta.deltaMessageReaction.threadKey
230
+ .otherUserFbId).toString(),
231
+ messageID: delta.deltaMessageReaction.messageId,
232
+ reaction: delta.deltaMessageReaction.reaction,
233
+ senderID: delta.deltaMessageReaction.senderId.toString(),
234
+ userID: delta.deltaMessageReaction.userId.toString()
235
+ }); })();
236
+ } else if (delta.deltaRecallMessageData && !!ctx.globalOptions.listenEvents) {
237
+ (function () { globalCallback(null, {
238
+ type: "message_unsend",
239
+ threadID: (delta.deltaRecallMessageData.threadKey.threadFbId ?
240
+ delta.deltaRecallMessageData.threadKey.threadFbId : delta.deltaRecallMessageData.threadKey
241
+ .otherUserFbId).toString(),
242
+ messageID: delta.deltaRecallMessageData.messageID,
243
+ senderID: delta.deltaRecallMessageData.senderID.toString(),
244
+ deletionTimestamp: delta.deltaRecallMessageData.deletionTimestamp,
245
+ timestamp: delta.deltaRecallMessageData.timestamp
246
+ }); })();
247
+ } else if (delta.deltaMessageReply) {
248
+ //Mention block - #1
249
+ var mdata =
250
+ delta.deltaMessageReply.message === undefined ? [] :
251
+ delta.deltaMessageReply.message.data === undefined ? [] :
252
+ delta.deltaMessageReply.message.data.prng === undefined ? [] :
253
+ JSON.parse(delta.deltaMessageReply.message.data.prng);
254
+ var m_id = mdata.map(u => u.i);
255
+ var m_offset = mdata.map(u => u.o);
256
+ var m_length = mdata.map(u => u.l);
257
+
258
+ var mentions = {};
259
+
260
+ for (var i = 0; i < m_id.length; i++) {
261
+ mentions[m_id[i]] = (delta.deltaMessageReply.message.body || "").substring(
262
+ m_offset[i],
263
+ m_offset[i] + m_length[i]
264
+ );
265
+ }
266
+ //Mention block - 1#
267
+ var callbackToReturn = {
268
+ type: "message_reply",
269
+ threadID: (delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId ?
270
+ delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.message.messageMetadata.threadKey
271
+ .otherUserFbId).toString(),
272
+ messageID: delta.deltaMessageReply.message.messageMetadata.messageId,
273
+ senderID: delta.deltaMessageReply.message.messageMetadata.actorFbId.toString(),
274
+ attachments: delta.deltaMessageReply.message.attachments.map(function (att) {
275
+ var mercury = JSON.parse(att.mercuryJSON);
276
+ Object.assign(att, mercury);
277
+ return att;
278
+ }).map(att => {
279
+ var x;
280
+ try {
281
+ x = utils._formatAttachment(att);
282
+ } catch (ex) {
283
+ x = att;
284
+ x.error = ex;
285
+ x.type = "unknown";
286
+ }
287
+ return x;
288
+ }),
289
+ body: delta.deltaMessageReply.message.body || "",
290
+ isGroup: !!delta.deltaMessageReply.message.messageMetadata.threadKey.threadFbId,
291
+ mentions: mentions,
292
+ timestamp: delta.deltaMessageReply.message.messageMetadata.timestamp,
293
+ };
294
+
295
+ if (delta.deltaMessageReply.repliedToMessage) {
296
+ //Mention block - #2
297
+ mdata =
298
+ delta.deltaMessageReply.repliedToMessage === undefined ? [] :
299
+ delta.deltaMessageReply.repliedToMessage.data === undefined ? [] :
300
+ delta.deltaMessageReply.repliedToMessage.data.prng === undefined ? [] :
301
+ JSON.parse(delta.deltaMessageReply.repliedToMessage.data.prng);
302
+ m_id = mdata.map(u => u.i);
303
+ m_offset = mdata.map(u => u.o);
304
+ m_length = mdata.map(u => u.l);
305
+
306
+ var rmentions = {};
307
+
308
+ for (var i = 0; i < m_id.length; i++) {
309
+ rmentions[m_id[i]] = (delta.deltaMessageReply.repliedToMessage.body || "").substring(
310
+ m_offset[i],
311
+ m_offset[i] + m_length[i]
312
+ );
313
+ }
314
+ //Mention block - 2#
315
+ callbackToReturn.messageReply = {
316
+ threadID: (delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId ?
317
+ delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId : delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey
318
+ .otherUserFbId).toString(),
319
+ messageID: delta.deltaMessageReply.repliedToMessage.messageMetadata.messageId,
320
+ senderID: delta.deltaMessageReply.repliedToMessage.messageMetadata.actorFbId.toString(),
321
+ attachments: delta.deltaMessageReply.repliedToMessage.attachments.map(function (att) {
322
+ var mercury = JSON.parse(att.mercuryJSON);
323
+ Object.assign(att, mercury);
324
+ return att;
325
+ }).map(att => {
326
+ var x;
327
+ try {
328
+ x = utils._formatAttachment(att);
329
+ } catch (ex) {
330
+ x = att;
331
+ x.error = ex;
332
+ x.type = "unknown";
333
+ }
334
+ return x;
335
+ }),
336
+ body: delta.deltaMessageReply.repliedToMessage.body || "",
337
+ isGroup: !!delta.deltaMessageReply.repliedToMessage.messageMetadata.threadKey.threadFbId,
338
+ mentions: rmentions,
339
+ timestamp: delta.deltaMessageReply.repliedToMessage.messageMetadata.timestamp,
340
+ };
341
+ }
342
+
343
+ if (ctx.globalOptions.autoMarkDelivery) {
344
+ markDelivery(ctx, api, callbackToReturn.threadID, callbackToReturn.messageID);
345
+ }
346
+
347
+ return !ctx.globalOptions.selfListen &&
348
+ callbackToReturn.senderID === ctx.userID ?
349
+ undefined :
350
+ (function () { globalCallback(null, callbackToReturn); })();
351
+ }
352
+ }
353
+ return;
354
+ }
355
+ }
356
+
357
+ if (v.delta.class !== "NewMessage" &&
358
+ !ctx.globalOptions.listenEvents
359
+ )
360
+ return;
361
+
362
+ switch (v.delta.class) {
363
+ case "ReadReceipt":
364
+ var fmtMsg;
365
+ try {
366
+ fmtMsg = utils.formatDeltaReadReceipt(v.delta);
367
+ } catch (err) {
368
+ return globalCallback({
369
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
370
+ detail: err,
371
+ res: v.delta,
372
+ type: "parse_error"
373
+ });
374
+ }
375
+ return (function () { globalCallback(null, fmtMsg); })();
376
+ case "AdminTextMessage":
377
+ switch (v.delta.type) {
378
+ case "change_thread_theme":
379
+ case "change_thread_nickname":
380
+ case "change_thread_icon":
381
+ break;
382
+ case "group_poll":
383
+ var fmtMsg;
384
+ try {
385
+ fmtMsg = utils.formatDeltaEvent(v.delta);
386
+ } catch (err) {
387
+ return globalCallback({
388
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
389
+ detail: err,
390
+ res: v.delta,
391
+ type: "parse_error"
392
+ });
393
+ }
394
+ return (function () { globalCallback(null, fmtMsg); })();
395
+ default:
396
+ return;
397
+ }
398
+ break;
399
+ //For group images
400
+ case "ForcedFetch":
401
+ if (!v.delta.threadKey) return;
402
+ var mid = v.delta.messageId;
403
+ var tid = v.delta.threadKey.threadFbId;
404
+ if (mid && tid) {
405
+ const form = {
406
+ "av": ctx.globalOptions.pageID,
407
+ "queries": JSON.stringify({
408
+ "o0": {
409
+ //This doc_id is valid as of ? (prob January 18, 2020)
410
+ "doc_id": "1768656253222505",
411
+ "query_params": {
412
+ "thread_and_message_id": {
413
+ "thread_id": tid.toString(),
414
+ "message_id": mid.toString(),
415
+ }
416
+ }
417
+ }
418
+ })
419
+ };
420
+
421
+ defaultFuncs
422
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
423
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
424
+ .then((resData) => {
425
+ if (resData[resData.length - 1].error_results > 0) {
426
+ throw resData[0].o0.errors;
427
+ }
428
+
429
+ if (resData[resData.length - 1].successful_results === 0) {
430
+ throw { error: "forcedFetch: there was no successful_results", res: resData };
431
+ }
432
+
433
+ var fetchData = resData[0].o0.data.message;
434
+ if (fetchData && fetchData.__typename === "ThreadImageMessage") {
435
+ (!ctx.globalOptions.selfListen &&
436
+ fetchData.message_sender.id.toString() === ctx.userID) ||
437
+ !ctx.loggedIn ?
438
+ undefined :
439
+ (function () { globalCallback(null, {
440
+ type: "change_thread_image",
441
+ threadID: utils.formatID(tid.toString()),
442
+ snippet: fetchData.snippet,
443
+ timestamp: fetchData.timestamp_precise,
444
+ author: fetchData.message_sender.id,
445
+ image: {
446
+ attachmentID: fetchData.image_with_metadata && fetchData.image_with_metadata.legacy_attachment_id,
447
+ width: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.x,
448
+ height: fetchData.image_with_metadata && fetchData.image_with_metadata.original_dimensions.y,
449
+ url: fetchData.image_with_metadata && fetchData.image_with_metadata.preview.uri
450
+ }
451
+ }); })();
452
+ }
453
+ })
454
+ .catch((err) => {
455
+ log.error("forcedFetch", err);
456
+ });
457
+ }
458
+ break;
459
+ case "ThreadName":
460
+ case "ParticipantsAddedToGroupThread":
461
+ case "ParticipantLeftGroupThread":
462
+ var formattedEvent;
463
+ try {
464
+ formattedEvent = utils.formatDeltaEvent(v.delta);
465
+ } catch (err) {
466
+ return globalCallback({
467
+ error: "Problem parsing message object. Please open an issue at https://github.com/Schmavery/facebook-chat-api/issues.",
468
+ detail: err,
469
+ res: v.delta,
470
+ type: "parse_error"
471
+ });
472
+ }
473
+ return (!ctx.globalOptions.selfListen &&
474
+ formattedEvent.author.toString() === ctx.userID) ||
475
+ !ctx.loggedIn ?
476
+ undefined :
477
+ (function () { globalCallback(null, formattedEvent); })();
478
+ }
479
+ }
480
+
481
+ function markDelivery(ctx, api, threadID, messageID) {
482
+ if (threadID && messageID) {
483
+ api.markAsDelivered(threadID, messageID, (err) => {
484
+ if (err) {
485
+ log.error(err);
486
+ } else {
487
+ if (ctx.globalOptions.autoMarkRead) {
488
+ api.markAsRead(threadID, (err) => {
489
+ if (err) {
490
+ log.error(err);
491
+ }
492
+ });
493
+ }
494
+ }
495
+ });
496
+ }
497
+ }
498
+
499
+ module.exports = function (defaultFuncs, api, ctx) {
500
+ var globalCallback = identity;
501
+ return function (callback) {
502
+ globalCallback = callback;
503
+
504
+ //Reset some stuff
505
+ ctx.lastSeqId = 0;
506
+ ctx.syncToken = undefined;
507
+
508
+ //Same request as getThreadList
509
+ const form = {
510
+ "av": ctx.globalOptions.pageID,
511
+ "queries": JSON.stringify({
512
+ "o0": {
513
+ "doc_id": "1349387578499440",
514
+ "query_params": {
515
+ "limit": 1,
516
+ "before": null,
517
+ "tags": ["INBOX"],
518
+ "includeDeliveryReceipts": false,
519
+ "includeSeqID": true
520
+ }
521
+ }
522
+ })
523
+ };
524
+
525
+ defaultFuncs
526
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
527
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
528
+ .then((resData) => {
529
+ if (resData && resData.length > 0 && resData[resData.length - 1].error_results > 0) {
530
+ throw resData[0].o0.errors;
531
+ }
532
+
533
+ if (resData[resData.length - 1].successful_results === 0) {
534
+ throw { error: "getSeqId: there was no successful_results", res: resData };
535
+ }
536
+
537
+ if (resData[0].o0.data.viewer.message_threads.sync_sequence_id) {
538
+ ctx.lastSeqId = resData[0].o0.data.viewer.message_threads.sync_sequence_id;
539
+ listenMqtt(defaultFuncs, api, ctx, globalCallback);
540
+ }
541
+
542
+ })
543
+ .catch((err) => {
544
+ log.error("getSeqId", err);
545
+ return callback(err);
546
+ });
547
+
548
+ var stopListening = function () {
549
+ globalCallback = identity;
550
+
551
+ if(ctx.mqttClient)
552
+ {
553
+ ctx.mqttClient.end();
554
+ ctx.mqttClient = undefined;
555
+ }
556
+ };
557
+
558
+ return stopListening;
559
+ };
560
+ };
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+
6
+ module.exports = function(defaultFuncs, bot, ctx) {
7
+ return function logout(callback) {
8
+ callback = callback || function() {};
9
+
10
+ var form = {
11
+ pmid: "0"
12
+ };
13
+
14
+ defaultFuncs
15
+ .post(
16
+ "https://www.facebook.com/bluebar/modern_settings_menu/?help_type=364455653583099&show_contextual_help=1",
17
+ ctx.jar,
18
+ form
19
+ )
20
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
21
+ .then(function(resData) {
22
+ var elem = resData.jsmods.instances[0][2][0].filter(function(v) {
23
+ return v.value === "logout";
24
+ })[0];
25
+
26
+ var html = resData.jsmods.markup.filter(function(v) {
27
+ return v[0] === elem.markup.__m;
28
+ })[0][1].__html;
29
+
30
+ var form = {
31
+ fb_dtsg: utils.getFrom(html, '"fb_dtsg" value="', '"'),
32
+ ref: utils.getFrom(html, '"ref" value="', '"'),
33
+ h: utils.getFrom(html, '"h" value="', '"')
34
+ };
35
+
36
+ return defaultFuncs
37
+ .post("https://www.facebook.com/logout.php", ctx.jar, form)
38
+ .then(utils.saveCookies(ctx.jar));
39
+ })
40
+ .then(function(res) {
41
+ if (!res.headers) {
42
+ throw { error: "An error occurred when logging out." };
43
+ }
44
+
45
+ return defaultFuncs
46
+ .get(res.headers.location, ctx.jar)
47
+ .then(utils.saveCookies(ctx.jar));
48
+ })
49
+ .then(function() {
50
+ ctx.loggedIn = false;
51
+ log.info("logout", "Logged out successfully.");
52
+ callback();
53
+ })
54
+ .catch(function(err) {
55
+ log.error("logout", err);
56
+ return callback(err);
57
+ });
58
+ };
59
+ };
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+
6
+ module.exports = function(defaultFuncs, bot, ctx) {
7
+ return function handleMessageRequest(threadID, accept, callback) {
8
+ if (utils.getType(accept) !== "Boolean") {
9
+ throw {
10
+ error: "Please pass a boolean as a second argument."
11
+ };
12
+ }
13
+
14
+ if (!callback) {
15
+ callback = function() {};
16
+ }
17
+
18
+ var form = {
19
+ client: "mercury"
20
+ };
21
+
22
+ if (utils.getType(threadID) !== "Array") {
23
+ threadID = [threadID];
24
+ }
25
+
26
+ var messageBox = accept ? "inbox" : "other";
27
+
28
+ for (var i = 0; i < threadID.length; i++) {
29
+ form[messageBox + "[" + i + "]"] = threadID[i];
30
+ }
31
+
32
+ defaultFuncs
33
+ .post(
34
+ "https://www.facebook.com/ajax/mercury/move_thread.php",
35
+ ctx.jar,
36
+ form
37
+ )
38
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
39
+ .then(function(resData) {
40
+ if (resData.error) {
41
+ throw resData;
42
+ }
43
+
44
+ return callback();
45
+ })
46
+ .catch(function(err) {
47
+ log.error("handleMessageRequest", err);
48
+ return callback(err);
49
+ });
50
+ };
51
+ };
package/alice/mute.js ADDED
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+
6
+ module.exports = function(defaultFuncs, bot, ctx) {
7
+ // muteSecond: -1=permanent mute, 0=unmute, 60=one minute, 3600=one hour, etc.
8
+ return function muteThread(threadID, muteSeconds, callback) {
9
+ if (!callback) {
10
+ callback = function() {};
11
+ }
12
+
13
+ var form = {
14
+ thread_fbid: threadID,
15
+ mute_settings: muteSeconds
16
+ };
17
+
18
+ defaultFuncs
19
+ .post(
20
+ "https://www.facebook.com/ajax/mercury/change_mute_thread.php",
21
+ ctx.jar,
22
+ form
23
+ )
24
+ .then(utils.saveCookies(ctx.jar))
25
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
26
+ .then(function(resData) {
27
+ if (resData.error) {
28
+ throw resData;
29
+ }
30
+
31
+ return callback();
32
+ })
33
+ .catch(function(err) {
34
+ log.error("muteThread", err);
35
+ return callback(err);
36
+ });
37
+ };
38
+ };