alicezetion 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,632 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+
6
+ function formatAttachmentsGraphQLResponse(attachment) {
7
+ switch (attachment.__typename) {
8
+ case "MessageImage":
9
+ return {
10
+ type: "photo",
11
+ ID: attachment.legacy_attachment_id,
12
+ filename: attachment.filename,
13
+ thumbnailUrl: attachment.thumbnail.uri,
14
+
15
+ previewUrl: attachment.preview.uri,
16
+ previewWidth: attachment.preview.width,
17
+ previewHeight: attachment.preview.height,
18
+
19
+ largePreviewUrl: attachment.large_preview.uri,
20
+ largePreviewHeight: attachment.large_preview.height,
21
+ largePreviewWidth: attachment.large_preview.width,
22
+
23
+ // You have to query for the real image. See below.
24
+ url: attachment.large_preview.uri, // @Legacy
25
+ width: attachment.large_preview.width, // @Legacy
26
+ height: attachment.large_preview.height, // @Legacy
27
+ name: attachment.filename, // @Legacy
28
+
29
+ // @Undocumented
30
+ attributionApp: attachment.attribution_app
31
+ ? {
32
+ attributionAppID: attachment.attribution_app.id,
33
+ name: attachment.attribution_app.name,
34
+ logo: attachment.attribution_app.square_logo
35
+ }
36
+ : null
37
+
38
+ // @TODO No idea what this is, should we expose it?
39
+ // Ben - July 15th 2017
40
+ // renderAsSticker: attachment.render_as_sticker,
41
+
42
+ // This is _not_ the real URI, this is still just a large preview.
43
+ // To get the URL we'll need to support a POST query to
44
+ //
45
+ // https://www.facebook.com/webgraphql/query/
46
+ //
47
+ // With the following query params:
48
+ //
49
+ // query_id:728987990612546
50
+ // variables:{"id":"100009069356507","photoID":"10213724771692996"}
51
+ // dpr:1
52
+ //
53
+ // No special form though.
54
+ };
55
+ case "MessageAnimatedImage":
56
+ return {
57
+ type: "animated_image",
58
+ ID: attachment.legacy_attachment_id,
59
+ filename: attachment.filename,
60
+
61
+ previewUrl: attachment.preview_image.uri,
62
+ previewWidth: attachment.preview_image.width,
63
+ previewHeight: attachment.preview_image.height,
64
+
65
+ url: attachment.animated_image.uri,
66
+ width: attachment.animated_image.width,
67
+ height: attachment.animated_image.height,
68
+
69
+ thumbnailUrl: attachment.preview_image.uri, // @Legacy
70
+ name: attachment.filename, // @Legacy
71
+ facebookUrl: attachment.animated_image.uri, // @Legacy
72
+ rawGifImage: attachment.animated_image.uri, // @Legacy
73
+ animatedGifUrl: attachment.animated_image.uri, // @Legacy
74
+ animatedGifPreviewUrl: attachment.preview_image.uri, // @Legacy
75
+ animatedWebpUrl: attachment.animated_image.uri, // @Legacy
76
+ animatedWebpPreviewUrl: attachment.preview_image.uri, // @Legacy
77
+
78
+ // @Undocumented
79
+ attributionApp: attachment.attribution_app
80
+ ? {
81
+ attributionAppID: attachment.attribution_app.id,
82
+ name: attachment.attribution_app.name,
83
+ logo: attachment.attribution_app.square_logo
84
+ }
85
+ : null
86
+ };
87
+ case "MessageVideo":
88
+ return {
89
+ type: "video",
90
+ filename: attachment.filename,
91
+ ID: attachment.legacy_attachment_id,
92
+
93
+ thumbnailUrl: attachment.large_image.uri, // @Legacy
94
+
95
+ previewUrl: attachment.large_image.uri,
96
+ previewWidth: attachment.large_image.width,
97
+ previewHeight: attachment.large_image.height,
98
+
99
+ url: attachment.playable_url,
100
+ width: attachment.original_dimensions.x,
101
+ height: attachment.original_dimensions.y,
102
+
103
+ duration: attachment.playable_duration_in_ms,
104
+ videoType: attachment.video_type.toLowerCase()
105
+ };
106
+ break;
107
+ case "MessageFile":
108
+ return {
109
+ type: "file",
110
+ filename: attachment.filename,
111
+ ID: attachment.message_file_fbid,
112
+
113
+ url: attachment.url,
114
+ isMalicious: attachment.is_malicious,
115
+ contentType: attachment.content_type,
116
+
117
+ name: attachment.filename, // @Legacy
118
+ mimeType: "", // @Legacy
119
+ fileSize: -1 // @Legacy
120
+ };
121
+ case "MessageAudio":
122
+ return {
123
+ type: "audio",
124
+ filename: attachment.filename,
125
+ ID: attachment.url_shimhash, // Not fowardable
126
+
127
+ audioType: attachment.audio_type,
128
+ duration: attachment.playable_duration_in_ms,
129
+ url: attachment.playable_url,
130
+
131
+ isVoiceMail: attachment.is_voicemail
132
+ };
133
+ default:
134
+ return {
135
+ error: "Don't know about attachment type " + attachment.__typename
136
+ };
137
+ }
138
+ }
139
+
140
+ function formatExtensibleAttachment(attachment) {
141
+ if (attachment.story_attachment) {
142
+ return {
143
+ type: "share",
144
+ ID: attachment.legacy_attachment_id,
145
+ url: attachment.story_attachment.url,
146
+
147
+ title: attachment.story_attachment.title_with_entities.text,
148
+ description:
149
+ attachment.story_attachment.description &&
150
+ attachment.story_attachment.description.text,
151
+ source:
152
+ attachment.story_attachment.source == null
153
+ ? null
154
+ : attachment.story_attachment.source.text,
155
+
156
+ image:
157
+ attachment.story_attachment.media == null
158
+ ? null
159
+ : attachment.story_attachment.media.animated_image == null &&
160
+ attachment.story_attachment.media.image == null
161
+ ? null
162
+ : (
163
+ attachment.story_attachment.media.animated_image ||
164
+ attachment.story_attachment.media.image
165
+ ).uri,
166
+ width:
167
+ attachment.story_attachment.media == null
168
+ ? null
169
+ : attachment.story_attachment.media.animated_image == null &&
170
+ attachment.story_attachment.media.image == null
171
+ ? null
172
+ : (
173
+ attachment.story_attachment.media.animated_image ||
174
+ attachment.story_attachment.media.image
175
+ ).width,
176
+ height:
177
+ attachment.story_attachment.media == null
178
+ ? null
179
+ : attachment.story_attachment.media.animated_image == null &&
180
+ attachment.story_attachment.media.image == null
181
+ ? null
182
+ : (
183
+ attachment.story_attachment.media.animated_image ||
184
+ attachment.story_attachment.media.image
185
+ ).height,
186
+ playable:
187
+ attachment.story_attachment.media == null
188
+ ? null
189
+ : attachment.story_attachment.media.is_playable,
190
+ duration:
191
+ attachment.story_attachment.media == null
192
+ ? null
193
+ : attachment.story_attachment.media.playable_duration_in_ms,
194
+ playableUrl:
195
+ attachment.story_attachment.media == null
196
+ ? null
197
+ : attachment.story_attachment.media.playable_url,
198
+
199
+ subattachments: attachment.story_attachment.subattachments,
200
+
201
+ // Format example:
202
+ //
203
+ // [{
204
+ // key: "width",
205
+ // value: { text: "1280" }
206
+ // }]
207
+ //
208
+ // That we turn into:
209
+ //
210
+ // {
211
+ // width: "1280"
212
+ // }
213
+ //
214
+ properties: attachment.story_attachment.properties.reduce(function(
215
+ obj,
216
+ cur
217
+ ) {
218
+ obj[cur.key] = cur.value.text;
219
+ return obj;
220
+ },
221
+ {}),
222
+
223
+ // Deprecated fields
224
+ animatedImageSize: "", // @Legacy
225
+ facebookUrl: "", // @Legacy
226
+ styleList: "", // @Legacy
227
+ target: "", // @Legacy
228
+ thumbnailUrl:
229
+ attachment.story_attachment.media == null
230
+ ? null
231
+ : attachment.story_attachment.media.animated_image == null &&
232
+ attachment.story_attachment.media.image == null
233
+ ? null
234
+ : (
235
+ attachment.story_attachment.media.animated_image ||
236
+ attachment.story_attachment.media.image
237
+ ).uri, // @Legacy
238
+ thumbnailWidth:
239
+ attachment.story_attachment.media == null
240
+ ? null
241
+ : attachment.story_attachment.media.animated_image == null &&
242
+ attachment.story_attachment.media.image == null
243
+ ? null
244
+ : (
245
+ attachment.story_attachment.media.animated_image ||
246
+ attachment.story_attachment.media.image
247
+ ).width, // @Legacy
248
+ thumbnailHeight:
249
+ attachment.story_attachment.media == null
250
+ ? null
251
+ : attachment.story_attachment.media.animated_image == null &&
252
+ attachment.story_attachment.media.image == null
253
+ ? null
254
+ : (
255
+ attachment.story_attachment.media.animated_image ||
256
+ attachment.story_attachment.media.image
257
+ ).height // @Legacy
258
+ };
259
+ } else {
260
+ return { error: "Don't know what to do with extensible_attachment." };
261
+ }
262
+ }
263
+
264
+ function formatReactionsGraphQL(reaction) {
265
+ return {
266
+ reaction: reaction.reaction,
267
+ userID: reaction.user.id
268
+ };
269
+ }
270
+
271
+ function formatEventData(event) {
272
+ if (event == null) {
273
+ return {};
274
+ }
275
+
276
+ switch (event.__typename) {
277
+ case "ThemeColorExtensibleMessageAdminText":
278
+ return {
279
+ color: event.theme_color
280
+ };
281
+ case "ThreadNicknameExtensibleMessageAdminText":
282
+ return {
283
+ nickname: event.nickname,
284
+ participantID: event.participant_id
285
+ };
286
+ case "ThreadIconExtensibleMessageAdminText":
287
+ return {
288
+ threadIcon: event.thread_icon
289
+ };
290
+ case "InstantGameUpdateExtensibleMessageAdminText":
291
+ return {
292
+ gameID: (event.game == null ? null : event.game.id),
293
+ update_type: event.update_type,
294
+ collapsed_text: event.collapsed_text,
295
+ expanded_text: event.expanded_text,
296
+ instant_game_update_data: event.instant_game_update_data
297
+ };
298
+ case "GameScoreExtensibleMessageAdminText":
299
+ return {
300
+ game_type: event.game_type
301
+ };
302
+ case "RtcCallLogExtensibleMessageAdminText":
303
+ return {
304
+ event: event.event,
305
+ is_video_call: event.is_video_call,
306
+ server_info_data: event.server_info_data
307
+ };
308
+ case "GroupPollExtensibleMessageAdminText":
309
+ return {
310
+ event_type: event.event_type,
311
+ total_count: event.total_count,
312
+ question: event.question
313
+ };
314
+ case "AcceptPendingThreadExtensibleMessageAdminText":
315
+ return {
316
+ accepter_id: event.accepter_id,
317
+ requester_id: event.requester_id
318
+ };
319
+ case "ConfirmFriendRequestExtensibleMessageAdminText":
320
+ return {
321
+ friend_request_recipient: event.friend_request_recipient,
322
+ friend_request_sender: event.friend_request_sender
323
+ };
324
+ case "AddContactExtensibleMessageAdminText":
325
+ return {
326
+ contact_added_id: event.contact_added_id,
327
+ contact_adder_id: event.contact_adder_id
328
+ };
329
+ case "AdExtensibleMessageAdminText":
330
+ return {
331
+ ad_client_token: event.ad_client_token,
332
+ ad_id: event.ad_id,
333
+ ad_preferences_link: event.ad_preferences_link,
334
+ ad_properties: event.ad_properties
335
+ };
336
+ // never data
337
+ case "ParticipantJoinedGroupCallExtensibleMessageAdminText":
338
+ case "ThreadEphemeralTtlModeExtensibleMessageAdminText":
339
+ case "StartedSharingVideoExtensibleMessageAdminText":
340
+ case "LightweightEventCreateExtensibleMessageAdminText":
341
+ case "LightweightEventNotifyExtensibleMessageAdminText":
342
+ case "LightweightEventNotifyBeforeEventExtensibleMessageAdminText":
343
+ case "LightweightEventUpdateTitleExtensibleMessageAdminText":
344
+ case "LightweightEventUpdateTimeExtensibleMessageAdminText":
345
+ case "LightweightEventUpdateLocationExtensibleMessageAdminText":
346
+ case "LightweightEventDeleteExtensibleMessageAdminText":
347
+ return {};
348
+ default:
349
+ return {
350
+ error: "Don't know what to with event data type " + event.__typename
351
+ };
352
+ }
353
+ }
354
+
355
+ function formatMessagesGraphQLResponse(data) {
356
+ var messageThread = data.o0.data.message_thread;
357
+ var threadID = messageThread.thread_key.thread_fbid
358
+ ? messageThread.thread_key.thread_fbid
359
+ : messageThread.thread_key.other_user_id;
360
+
361
+ var messages = messageThread.messages.nodes.map(function(d) {
362
+ switch (d.__typename) {
363
+ case "UserMessage":
364
+ // Give priority to stickers. They're seen as normal messages but we've
365
+ // been considering them as attachments.
366
+ var maybeStickerAttachment;
367
+ if (d.sticker && d.sticker.pack) {
368
+ maybeStickerAttachment = [
369
+ {
370
+ type: "sticker",
371
+ ID: d.sticker.id,
372
+ url: d.sticker.url,
373
+
374
+ packID: d.sticker.pack ? d.sticker.pack.id : null,
375
+ spriteUrl: d.sticker.sprite_image,
376
+ spriteUrl2x: d.sticker.sprite_image_2x,
377
+ width: d.sticker.width,
378
+ height: d.sticker.height,
379
+
380
+ caption: d.snippet, // Not sure what the heck caption was.
381
+ description: d.sticker.label, // Not sure about this one either.
382
+
383
+ frameCount: d.sticker.frame_count,
384
+ frameRate: d.sticker.frame_rate,
385
+ framesPerRow: d.sticker.frames_per_row,
386
+ framesPerCol: d.sticker.frames_per_col,
387
+
388
+ stickerID: d.sticker.id, // @Legacy
389
+ spriteURI: d.sticker.sprite_image, // @Legacy
390
+ spriteURI2x: d.sticker.sprite_image_2x // @Legacy
391
+ }
392
+ ];
393
+ }
394
+
395
+ var mentionsObj = {};
396
+ if (d.message !== null) {
397
+ d.message.ranges.forEach(e => {
398
+ mentionsObj[e.entity.id] = d.message.text.substr(e.offset, e.length);
399
+ });
400
+ }
401
+
402
+ return {
403
+ type: "message",
404
+ attachments: maybeStickerAttachment
405
+ ? maybeStickerAttachment
406
+ : d.blob_attachments && d.blob_attachments.length > 0
407
+ ? d.blob_attachments.map(formatAttachmentsGraphQLResponse)
408
+ : d.extensible_attachment
409
+ ? [formatExtensibleAttachment(d.extensible_attachment)]
410
+ : [],
411
+ body: d.message !== null ? d.message.text : '',
412
+ isGroup: messageThread.thread_type === "GROUP",
413
+ messageID: d.message_id,
414
+ senderID: d.message_sender.id,
415
+ threadID: threadID,
416
+ timestamp: d.timestamp_precise,
417
+
418
+ mentions: mentionsObj,
419
+ isUnread: d.unread,
420
+
421
+ // New
422
+ messageReactions: d.message_reactions
423
+ ? d.message_reactions.map(formatReactionsGraphQL)
424
+ : null,
425
+ isSponsored: d.is_sponsored,
426
+ snippet: d.snippet
427
+ };
428
+ case "ThreadNameMessage":
429
+ return {
430
+ type: "event",
431
+ messageID: d.message_id,
432
+ threadID: threadID,
433
+ isGroup: messageThread.thread_type === "GROUP",
434
+ senderID: d.message_sender.id,
435
+ timestamp: d.timestamp_precise,
436
+ eventType: "change_thread_name",
437
+ snippet: d.snippet,
438
+ eventData: {
439
+ threadName: d.thread_name
440
+ },
441
+
442
+ // @Legacy
443
+ author: d.message_sender.id,
444
+ logMessageType: "log:thread-name",
445
+ logMessageData: { name: d.thread_name }
446
+ };
447
+ case "ThreadImageMessage":
448
+ return {
449
+ type: "event",
450
+ messageID: d.message_id,
451
+ threadID: threadID,
452
+ isGroup: messageThread.thread_type === "GROUP",
453
+ senderID: d.message_sender.id,
454
+ timestamp: d.timestamp_precise,
455
+ eventType: "change_thread_image",
456
+ snippet: d.snippet,
457
+ eventData:
458
+ d.image_with_metadata == null
459
+ ? {} /* removed image */
460
+ : {
461
+ /* image added */
462
+ threadImage: {
463
+ attachmentID: d.image_with_metadata.legacy_attachment_id,
464
+ width: d.image_with_metadata.original_dimensions.x,
465
+ height: d.image_with_metadata.original_dimensions.y,
466
+ url: d.image_with_metadata.preview.uri
467
+ }
468
+ },
469
+
470
+ // @Legacy
471
+ logMessageType: "log:thread-icon",
472
+ logMessageData: {
473
+ thread_icon: d.image_with_metadata
474
+ ? d.image_with_metadata.preview.uri
475
+ : null
476
+ }
477
+ };
478
+ case "ParticipantLeftMessage":
479
+ return {
480
+ type: "event",
481
+ messageID: d.message_id,
482
+ threadID: threadID,
483
+ isGroup: messageThread.thread_type === "GROUP",
484
+ senderID: d.message_sender.id,
485
+ timestamp: d.timestamp_precise,
486
+ eventType: "remove_participants",
487
+ snippet: d.snippet,
488
+ eventData: {
489
+ // Array of IDs.
490
+ participantsRemoved: d.participants_removed.map(function(p) {
491
+ return p.id;
492
+ })
493
+ },
494
+
495
+ // @Legacy
496
+ logMessageType: "log:unsubscribe",
497
+ logMessageData: {
498
+ leftParticipantFbId: d.participants_removed.map(function(p) {
499
+ return p.id;
500
+ })
501
+ }
502
+ };
503
+ case "ParticipantsAddedMessage":
504
+ return {
505
+ type: "event",
506
+ messageID: d.message_id,
507
+ threadID: threadID,
508
+ isGroup: messageThread.thread_type === "GROUP",
509
+ senderID: d.message_sender.id,
510
+ timestamp: d.timestamp_precise,
511
+ eventType: "add_participants",
512
+ snippet: d.snippet,
513
+ eventData: {
514
+ // Array of IDs.
515
+ participantsAdded: d.participants_added.map(function(p) {
516
+ return p.id;
517
+ })
518
+ },
519
+
520
+ // @Legacy
521
+ logMessageType: "log:subscribe",
522
+ logMessageData: {
523
+ addedParticipants: d.participants_added.map(function(p) {
524
+ return p.id;
525
+ })
526
+ }
527
+ };
528
+ case "VideoCallMessage":
529
+ return {
530
+ type: "event",
531
+ messageID: d.message_id,
532
+ threadID: threadID,
533
+ isGroup: messageThread.thread_type === "GROUP",
534
+ senderID: d.message_sender.id,
535
+ timestamp: d.timestamp_precise,
536
+ eventType: "video_call",
537
+ snippet: d.snippet,
538
+
539
+ // @Legacy
540
+ logMessageType: "other"
541
+ };
542
+ case "VoiceCallMessage":
543
+ return {
544
+ type: "event",
545
+ messageID: d.message_id,
546
+ threadID: threadID,
547
+ isGroup: messageThread.thread_type === "GROUP",
548
+ senderID: d.message_sender.id,
549
+ timestamp: d.timestamp_precise,
550
+ eventType: "voice_call",
551
+ snippet: d.snippet,
552
+
553
+ // @Legacy
554
+ logMessageType: "other"
555
+ };
556
+ case "GenericAdminTextMessage":
557
+ return {
558
+ type: "event",
559
+ messageID: d.message_id,
560
+ threadID: threadID,
561
+ isGroup: messageThread.thread_type === "GROUP",
562
+ senderID: d.message_sender.id,
563
+ timestamp: d.timestamp_precise,
564
+ snippet: d.snippet,
565
+ eventType: d.extensible_message_admin_text_type.toLowerCase(),
566
+ eventData: formatEventData(d.extensible_message_admin_text),
567
+
568
+ // @Legacy
569
+ logMessageType: utils.getAdminTextMessageType(
570
+ d.extensible_message_admin_text_type
571
+ ),
572
+ logMessageData: d.extensible_message_admin_text // Maybe different?
573
+ };
574
+ default:
575
+ return { error: "Don't know about message type " + d.__typename };
576
+ }
577
+ });
578
+ return messages;
579
+ }
580
+
581
+ module.exports = function(defaultFuncs, bot, ctx) {
582
+ return function getThreadHistoryGraphQL(
583
+ threadID,
584
+ amount,
585
+ timestamp,
586
+ callback
587
+ ) {
588
+ if (!callback) {
589
+ throw { error: "getThreadHistoryGraphQL: need callback" };
590
+ }
591
+
592
+ // `queries` has to be a string. I couldn't tell from the dev console. This
593
+ // took me a really long time to figure out. I deserve a cookie for this.
594
+ var form = {
595
+ "av": ctx.globalOptions.pageID,
596
+ queries: JSON.stringify({
597
+ o0: {
598
+ // This doc_id was valid on February 2nd 2017.
599
+ doc_id: "1498317363570230",
600
+ query_params: {
601
+ id: threadID,
602
+ message_limit: amount,
603
+ load_messages: 1,
604
+ load_read_receipts: false,
605
+ before: timestamp
606
+ }
607
+ }
608
+ })
609
+ };
610
+
611
+ defaultFuncs
612
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
613
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
614
+ .then(function(resData) {
615
+ if (resData.error) {
616
+ throw resData;
617
+ }
618
+ // This returns us an array of things. The last one is the success /
619
+ // failure one.
620
+ // @TODO What do we do in this case?
621
+ if (resData[resData.length - 1].error_results !== 0) {
622
+ throw new Error("well darn there was an error_result");
623
+ }
624
+
625
+ callback(null, formatMessagesGraphQLResponse(resData[0]));
626
+ })
627
+ .catch(function(err) {
628
+ log.error("getThreadHistoryGraphQL", err);
629
+ return callback(err);
630
+ });
631
+ };
632
+ };
package/alice/id.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+
3
+ module.exports = function(defaultFuncs, bot, ctx) {
4
+ return function getCurrentUserID() {
5
+ return ctx.userID;
6
+ };
7
+ };
package/alice/kick.js ADDED
@@ -0,0 +1,65 @@
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 removeUserFromGroup(userID, threadID, callback) {
8
+ if (
9
+ !callback &&
10
+ (utils.getType(threadID) === "Function" ||
11
+ utils.getType(threadID) === "AsyncFunction")
12
+ ) {
13
+ throw { error: "please pass a threadID as a second argument." };
14
+ }
15
+ if (
16
+ utils.getType(threadID) !== "Number" &&
17
+ utils.getType(threadID) !== "String"
18
+ ) {
19
+ throw {
20
+ error:
21
+ "threadID should be of type Number or String and not " +
22
+ utils.getType(threadID) +
23
+ "."
24
+ };
25
+ }
26
+ if (
27
+ utils.getType(userID) !== "Number" &&
28
+ utils.getType(userID) !== "String"
29
+ ) {
30
+ throw {
31
+ error:
32
+ "userID should be of type Number or String and not " +
33
+ utils.getType(userID) +
34
+ "."
35
+ };
36
+ }
37
+
38
+ if (!callback) {
39
+ callback = function() {};
40
+ }
41
+
42
+ var form = {
43
+ uid: userID,
44
+ tid: threadID
45
+ };
46
+
47
+ defaultFuncs
48
+ .post("https://www.facebook.com/chat/remove_participants", ctx.jar, form)
49
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
50
+ .then(function(resData) {
51
+ if (!resData) {
52
+ throw { error: "Remove from group failed." };
53
+ }
54
+ if (resData.error) {
55
+ throw resData;
56
+ }
57
+
58
+ return callback();
59
+ })
60
+ .catch(function(err) {
61
+ log.error("removeUserFromGroup", err);
62
+ return callback(err);
63
+ });
64
+ };
65
+ };