fca-riyad 37.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 (242) hide show
  1. package/CHANGELOG.md +325 -0
  2. package/DOCS.md +2712 -0
  3. package/README.md +410 -0
  4. package/func/checkUpdate.js +7 -0
  5. package/func/logAdapter.js +33 -0
  6. package/func/logger.js +48 -0
  7. package/index.d.ts +751 -0
  8. package/index.js +22 -0
  9. package/module/config.js +40 -0
  10. package/module/login.js +133 -0
  11. package/module/loginHelper.js +1359 -0
  12. package/module/options.js +44 -0
  13. package/package.json +95 -0
  14. package/src/api/action/addExternalModule.js +25 -0
  15. package/src/api/action/changeAvatar.js +137 -0
  16. package/src/api/action/changeBio.js +75 -0
  17. package/src/api/action/enableAutoSaveAppState.js +73 -0
  18. package/src/api/action/getCurrentUserID.js +7 -0
  19. package/src/api/action/handleFriendRequest.js +57 -0
  20. package/src/api/action/logout.js +76 -0
  21. package/src/api/action/refreshFb_dtsg.js +48 -0
  22. package/src/api/action/setPostReaction.js +106 -0
  23. package/src/api/action/unfriend.js +54 -0
  24. package/src/api/http/httpGet.js +46 -0
  25. package/src/api/http/httpPost.js +52 -0
  26. package/src/api/http/postFormData.js +47 -0
  27. package/src/api/messaging/addUserToGroup.js +68 -0
  28. package/src/api/messaging/changeAdminStatus.js +126 -0
  29. package/src/api/messaging/changeArchivedStatus.js +55 -0
  30. package/src/api/messaging/changeBlockedStatus.js +48 -0
  31. package/src/api/messaging/changeGroupImage.js +91 -0
  32. package/src/api/messaging/changeNickname.js +70 -0
  33. package/src/api/messaging/changeThreadColor.js +79 -0
  34. package/src/api/messaging/changeThreadEmoji.js +111 -0
  35. package/src/api/messaging/createNewGroup.js +88 -0
  36. package/src/api/messaging/createPoll.js +46 -0
  37. package/src/api/messaging/createThemeAI.js +98 -0
  38. package/src/api/messaging/deleteMessage.js +136 -0
  39. package/src/api/messaging/deleteThread.js +56 -0
  40. package/src/api/messaging/editMessage.js +90 -0
  41. package/src/api/messaging/forwardAttachment.js +57 -0
  42. package/src/api/messaging/forwardMessage.js +134 -0
  43. package/src/api/messaging/getEmojiUrl.js +29 -0
  44. package/src/api/messaging/getFriendsList.js +82 -0
  45. package/src/api/messaging/getMessage.js +829 -0
  46. package/src/api/messaging/getThemePictures.js +62 -0
  47. package/src/api/messaging/handleMessageRequest.js +65 -0
  48. package/src/api/messaging/markAsDelivered.js +57 -0
  49. package/src/api/messaging/markAsRead.js +88 -0
  50. package/src/api/messaging/markAsReadAll.js +49 -0
  51. package/src/api/messaging/markAsSeen.js +61 -0
  52. package/src/api/messaging/muteThread.js +50 -0
  53. package/src/api/messaging/pinMessage.js +115 -0
  54. package/src/api/messaging/removeUserFromGroup.js +62 -0
  55. package/src/api/messaging/resolvePhotoUrl.js +43 -0
  56. package/src/api/messaging/scheduler.js +264 -0
  57. package/src/api/messaging/searchForThread.js +53 -0
  58. package/src/api/messaging/sendBroadcast.js +93 -0
  59. package/src/api/messaging/sendMessage.js +269 -0
  60. package/src/api/messaging/sendTypingIndicator.js +74 -0
  61. package/src/api/messaging/sessionGuard.js +130 -0
  62. package/src/api/messaging/setMessageReaction.js +95 -0
  63. package/src/api/messaging/setTitle.js +124 -0
  64. package/src/api/messaging/shareContact.js +49 -0
  65. package/src/api/messaging/threadColors.js +128 -0
  66. package/src/api/messaging/unsendMessage.js +81 -0
  67. package/src/api/messaging/uploadAttachment.js +492 -0
  68. package/src/api/socket/OldMessage.js +186 -0
  69. package/src/api/socket/core/connectMqtt.js +269 -0
  70. package/src/api/socket/core/emitAuth.js +103 -0
  71. package/src/api/socket/core/getSeqID.js +321 -0
  72. package/src/api/socket/core/getTaskResponseData.js +25 -0
  73. package/src/api/socket/core/parseDelta.js +387 -0
  74. package/src/api/socket/detail/buildStream.js +215 -0
  75. package/src/api/socket/detail/constants.js +28 -0
  76. package/src/api/socket/e2ee/crypto.js +173 -0
  77. package/src/api/socket/e2ee/e2ee/crypto.js +173 -0
  78. package/src/api/socket/e2ee/e2ee/index.js +421 -0
  79. package/src/api/socket/e2ee/e2ee/proto/ArmadilloApplication.proto +281 -0
  80. package/src/api/socket/e2ee/e2ee/proto/ArmadilloICDC.proto +14 -0
  81. package/src/api/socket/e2ee/e2ee/proto/ConsumerApplication.proto +232 -0
  82. package/src/api/socket/e2ee/e2ee/proto/MessageApplication.proto +82 -0
  83. package/src/api/socket/e2ee/e2ee/proto/MessageTransport.proto +77 -0
  84. package/src/api/socket/e2ee/e2ee/proto/WACommon.proto +66 -0
  85. package/src/api/socket/e2ee/e2ee/proto/WAMediaTransport.proto +176 -0
  86. package/src/api/socket/e2ee/e2ee/proto/proto-writer.ts +76 -0
  87. package/src/api/socket/e2ee/e2ee/protocol.js +196 -0
  88. package/src/api/socket/e2ee/e2ee/ratchet.js +219 -0
  89. package/src/api/socket/e2ee/e2ee/store.js +182 -0
  90. package/src/api/socket/e2ee/e2ee/vendor/fb-e2ee.cjs +9162 -0
  91. package/src/api/socket/e2ee/e2ee/vendor/proto/ArmadilloApplication.proto +281 -0
  92. package/src/api/socket/e2ee/e2ee/vendor/proto/ArmadilloICDC.proto +14 -0
  93. package/src/api/socket/e2ee/e2ee/vendor/proto/ConsumerApplication.proto +232 -0
  94. package/src/api/socket/e2ee/e2ee/vendor/proto/MessageApplication.proto +82 -0
  95. package/src/api/socket/e2ee/e2ee/vendor/proto/MessageTransport.proto +77 -0
  96. package/src/api/socket/e2ee/e2ee/vendor/proto/WACommon.proto +66 -0
  97. package/src/api/socket/e2ee/e2ee/vendor/proto/WAMediaTransport.proto +176 -0
  98. package/src/api/socket/e2ee/e2ee/vendor/proto/proto-writer.ts +76 -0
  99. package/src/api/socket/e2ee/index.js +437 -0
  100. package/src/api/socket/e2ee/proto/ArmadilloApplication.proto +281 -0
  101. package/src/api/socket/e2ee/proto/ArmadilloICDC.proto +14 -0
  102. package/src/api/socket/e2ee/proto/ConsumerApplication.proto +232 -0
  103. package/src/api/socket/e2ee/proto/MessageApplication.proto +82 -0
  104. package/src/api/socket/e2ee/proto/MessageTransport.proto +77 -0
  105. package/src/api/socket/e2ee/proto/WACommon.proto +66 -0
  106. package/src/api/socket/e2ee/proto/WAMediaTransport.proto +176 -0
  107. package/src/api/socket/e2ee/proto/proto-writer.ts +76 -0
  108. package/src/api/socket/e2ee/protocol.js +196 -0
  109. package/src/api/socket/e2ee/ratchet.js +219 -0
  110. package/src/api/socket/e2ee/store.js +182 -0
  111. package/src/api/socket/e2ee/vendor/fb-e2ee.cjs +9162 -0
  112. package/src/api/socket/e2ee/vendor/proto/ArmadilloApplication.proto +281 -0
  113. package/src/api/socket/e2ee/vendor/proto/ArmadilloICDC.proto +14 -0
  114. package/src/api/socket/e2ee/vendor/proto/ConsumerApplication.proto +232 -0
  115. package/src/api/socket/e2ee/vendor/proto/MessageApplication.proto +82 -0
  116. package/src/api/socket/e2ee/vendor/proto/MessageTransport.proto +77 -0
  117. package/src/api/socket/e2ee/vendor/proto/WACommon.proto +66 -0
  118. package/src/api/socket/e2ee/vendor/proto/WAMediaTransport.proto +176 -0
  119. package/src/api/socket/e2ee/vendor/proto/proto-writer.ts +76 -0
  120. package/src/api/socket/listenE2EE.js +75 -0
  121. package/src/api/socket/listenMqtt.js +388 -0
  122. package/src/api/socket/middleware/index.js +216 -0
  123. package/src/api/socket/sendMessage.js +309 -0
  124. package/src/api/socket/sendMessageMqtt.js +69 -0
  125. package/src/api/threads/getThreadHistory.js +664 -0
  126. package/src/api/threads/getThreadInfo.js +296 -0
  127. package/src/api/threads/getThreadList.js +293 -0
  128. package/src/api/threads/getThreadPictures.js +78 -0
  129. package/src/api/users/getUserID.js +65 -0
  130. package/src/api/users/getUserInfo.js +402 -0
  131. package/src/api/users/getUserInfoV2.js +134 -0
  132. package/src/app/MessengerBot.js +209 -0
  133. package/src/app/MessengerContext.js +32 -0
  134. package/src/app/createFcaClient.js +136 -0
  135. package/src/app/threadInfoRealtimeSync.js +284 -0
  136. package/src/core/sendReqMqtt.js +96 -0
  137. package/src/database/helpers.js +53 -0
  138. package/src/database/models/index.js +88 -0
  139. package/src/database/models/thread.js +50 -0
  140. package/src/database/models/user.js +46 -0
  141. package/src/database/threadData.js +94 -0
  142. package/src/database/userData.js +98 -0
  143. package/src/remote/remoteClient.js +123 -0
  144. package/src/utils/broadcast.js +51 -0
  145. package/src/utils/client.js +10 -0
  146. package/src/utils/constants.js +23 -0
  147. package/src/utils/cookies.js +68 -0
  148. package/src/utils/format/attachment.js +357 -0
  149. package/src/utils/format/cookie.js +9 -0
  150. package/src/utils/format/date.js +50 -0
  151. package/src/utils/format/decode.js +44 -0
  152. package/src/utils/format/delta.js +194 -0
  153. package/src/utils/format/ids.js +64 -0
  154. package/src/utils/format/index.js +64 -0
  155. package/src/utils/format/message.js +88 -0
  156. package/src/utils/format/presence.js +132 -0
  157. package/src/utils/format/readTyp.js +44 -0
  158. package/src/utils/format/thread.js +42 -0
  159. package/src/utils/format/utils.js +141 -0
  160. package/src/utils/headers.js +115 -0
  161. package/src/utils/loginParser/autoLogin.js +125 -0
  162. package/src/utils/loginParser/helpers.js +43 -0
  163. package/src/utils/loginParser/index.js +10 -0
  164. package/src/utils/loginParser/parseAndCheckLogin.js +220 -0
  165. package/src/utils/loginParser/textUtils.js +28 -0
  166. package/src/utils/nexca-logger.js +144 -0
  167. package/src/utils/nexca-utils.js +686 -0
  168. package/src/utils/request/client.js +26 -0
  169. package/src/utils/request/config.js +23 -0
  170. package/src/utils/request/defaults.js +46 -0
  171. package/src/utils/request/helpers.js +46 -0
  172. package/src/utils/request/index.js +17 -0
  173. package/src/utils/request/methods.js +163 -0
  174. package/src/utils/request/proxy.js +21 -0
  175. package/src/utils/request/retry.js +77 -0
  176. package/src/utils/request/sanitize.js +49 -0
  177. package/src/utils/versionCheck.js +47 -0
  178. package/src/vendor/fca-unofficial/.github/workflows/nodejs.yml +26 -0
  179. package/src/vendor/fca-unofficial/.github/workflows/npmpublish.yml +30 -0
  180. package/src/vendor/fca-unofficial/.travis.yml +6 -0
  181. package/src/vendor/fca-unofficial/DOCS.md +1731 -0
  182. package/src/vendor/fca-unofficial/LICENSE-MIT +21 -0
  183. package/src/vendor/fca-unofficial/README.md +225 -0
  184. package/src/vendor/fca-unofficial/index.js +619 -0
  185. package/src/vendor/fca-unofficial/package.json +76 -0
  186. package/src/vendor/fca-unofficial/src/addExternalModule.js +19 -0
  187. package/src/vendor/fca-unofficial/src/addUserToGroup.js +113 -0
  188. package/src/vendor/fca-unofficial/src/changeAdminStatus.js +79 -0
  189. package/src/vendor/fca-unofficial/src/changeArchivedStatus.js +55 -0
  190. package/src/vendor/fca-unofficial/src/changeBio.js +77 -0
  191. package/src/vendor/fca-unofficial/src/changeBlockedStatus.js +47 -0
  192. package/src/vendor/fca-unofficial/src/changeGroupImage.js +129 -0
  193. package/src/vendor/fca-unofficial/src/changeNickname.js +59 -0
  194. package/src/vendor/fca-unofficial/src/changeThreadColor.js +71 -0
  195. package/src/vendor/fca-unofficial/src/changeThreadEmoji.js +55 -0
  196. package/src/vendor/fca-unofficial/src/createNewGroup.js +86 -0
  197. package/src/vendor/fca-unofficial/src/createPoll.js +71 -0
  198. package/src/vendor/fca-unofficial/src/deleteMessage.js +56 -0
  199. package/src/vendor/fca-unofficial/src/deleteThread.js +56 -0
  200. package/src/vendor/fca-unofficial/src/forwardAttachment.js +60 -0
  201. package/src/vendor/fca-unofficial/src/getCurrentUserID.js +7 -0
  202. package/src/vendor/fca-unofficial/src/getEmojiUrl.js +29 -0
  203. package/src/vendor/fca-unofficial/src/getFriendsList.js +84 -0
  204. package/src/vendor/fca-unofficial/src/getThreadHistory.js +645 -0
  205. package/src/vendor/fca-unofficial/src/getThreadHistoryDeprecated.js +93 -0
  206. package/src/vendor/fca-unofficial/src/getThreadInfo.js +201 -0
  207. package/src/vendor/fca-unofficial/src/getThreadInfoDeprecated.js +80 -0
  208. package/src/vendor/fca-unofficial/src/getThreadList.js +238 -0
  209. package/src/vendor/fca-unofficial/src/getThreadListDeprecated.js +75 -0
  210. package/src/vendor/fca-unofficial/src/getThreadPictures.js +79 -0
  211. package/src/vendor/fca-unofficial/src/getUserID.js +66 -0
  212. package/src/vendor/fca-unofficial/src/getUserInfo.js +72 -0
  213. package/src/vendor/fca-unofficial/src/handleFriendRequest.js +61 -0
  214. package/src/vendor/fca-unofficial/src/handleMessageRequest.js +65 -0
  215. package/src/vendor/fca-unofficial/src/httpGet.js +52 -0
  216. package/src/vendor/fca-unofficial/src/httpPost.js +52 -0
  217. package/src/vendor/fca-unofficial/src/listenMqtt.js +788 -0
  218. package/src/vendor/fca-unofficial/src/logout.js +75 -0
  219. package/src/vendor/fca-unofficial/src/markAsDelivered.js +58 -0
  220. package/src/vendor/fca-unofficial/src/markAsRead.js +80 -0
  221. package/src/vendor/fca-unofficial/src/markAsReadAll.js +50 -0
  222. package/src/vendor/fca-unofficial/src/markAsSeen.js +59 -0
  223. package/src/vendor/fca-unofficial/src/muteThread.js +52 -0
  224. package/src/vendor/fca-unofficial/src/removeUserFromGroup.js +79 -0
  225. package/src/vendor/fca-unofficial/src/resolvePhotoUrl.js +45 -0
  226. package/src/vendor/fca-unofficial/src/searchForThread.js +53 -0
  227. package/src/vendor/fca-unofficial/src/sendMessage.js +459 -0
  228. package/src/vendor/fca-unofficial/src/sendTypingIndicator.js +103 -0
  229. package/src/vendor/fca-unofficial/src/setMessageReaction.js +117 -0
  230. package/src/vendor/fca-unofficial/src/setPostReaction.js +76 -0
  231. package/src/vendor/fca-unofficial/src/setTitle.js +86 -0
  232. package/src/vendor/fca-unofficial/src/threadColors.js +57 -0
  233. package/src/vendor/fca-unofficial/src/unfriend.js +52 -0
  234. package/src/vendor/fca-unofficial/src/unsendMessage.js +49 -0
  235. package/src/vendor/fca-unofficial/test/data/shareAttach.js +146 -0
  236. package/src/vendor/fca-unofficial/test/data/something.mov +0 -0
  237. package/src/vendor/fca-unofficial/test/data/test.png +0 -0
  238. package/src/vendor/fca-unofficial/test/data/test.txt +7 -0
  239. package/src/vendor/fca-unofficial/test/example-config.json +18 -0
  240. package/src/vendor/fca-unofficial/test/test-page.js +140 -0
  241. package/src/vendor/fca-unofficial/test/test.js +385 -0
  242. package/src/vendor/fca-unofficial/utils.js +1358 -0
@@ -0,0 +1,664 @@
1
+ "use strict";
2
+
3
+ const log = require("../../../func/logAdapter");
4
+ const { parseAndCheckLogin } = require("../../utils/client");
5
+ const { getAdminTextMessageType } = require("../../utils/format");
6
+ function getExtension(original_extension, filename = "") {
7
+ if (original_extension) {
8
+ return original_extension;
9
+ } else {
10
+ const extension = filename.split(".").pop();
11
+ if (extension === filename) {
12
+ return "";
13
+ } else {
14
+ return extension;
15
+ }
16
+ }
17
+ }
18
+
19
+ function formatAttachmentsGraphQLResponse(attachment) {
20
+ switch (attachment.__typename) {
21
+ case "MessageImage":
22
+ return {
23
+ type: "photo",
24
+ ID: attachment.legacy_attachment_id,
25
+ filename: attachment.filename,
26
+ original_extension: getExtension(
27
+ attachment.original_extension,
28
+ attachment.filename
29
+ ),
30
+ thumbnailUrl: attachment.thumbnail.uri,
31
+
32
+ previewUrl: attachment.preview.uri,
33
+ previewWidth: attachment.preview.width,
34
+ previewHeight: attachment.preview.height,
35
+
36
+ largePreviewUrl: attachment.large_preview.uri,
37
+ largePreviewHeight: attachment.large_preview.height,
38
+ largePreviewWidth: attachment.large_preview.width,
39
+
40
+ // You have to query for the real image. See below.
41
+ url: attachment.large_preview.uri, // @Legacy
42
+ width: attachment.large_preview.width, // @Legacy
43
+ height: attachment.large_preview.height, // @Legacy
44
+ name: attachment.filename, // @Legacy
45
+
46
+ // @Undocumented
47
+ attributionApp: attachment.attribution_app
48
+ ? {
49
+ attributionAppID: attachment.attribution_app.id,
50
+ name: attachment.attribution_app.name,
51
+ logo: attachment.attribution_app.square_logo
52
+ }
53
+ : null
54
+ };
55
+ case "MessageAnimatedImage":
56
+ return {
57
+ type: "animated_image",
58
+ ID: attachment.legacy_attachment_id,
59
+ filename: attachment.filename,
60
+ original_extension: getExtension(
61
+ attachment.original_extension,
62
+ attachment.filename
63
+ ),
64
+
65
+ previewUrl: attachment.preview_image.uri,
66
+ previewWidth: attachment.preview_image.width,
67
+ previewHeight: attachment.preview_image.height,
68
+
69
+ url: attachment.animated_image.uri,
70
+ width: attachment.animated_image.width,
71
+ height: attachment.animated_image.height,
72
+
73
+ thumbnailUrl: attachment.preview_image.uri, // @Legacy
74
+ name: attachment.filename, // @Legacy
75
+ facebookUrl: attachment.animated_image.uri, // @Legacy
76
+ rawGifImage: attachment.animated_image.uri, // @Legacy
77
+ animatedGifUrl: attachment.animated_image.uri, // @Legacy
78
+ animatedGifPreviewUrl: attachment.preview_image.uri, // @Legacy
79
+ animatedWebpUrl: attachment.animated_image.uri, // @Legacy
80
+ animatedWebpPreviewUrl: attachment.preview_image.uri, // @Legacy
81
+
82
+ // @Undocumented
83
+ attributionApp: attachment.attribution_app
84
+ ? {
85
+ attributionAppID: attachment.attribution_app.id,
86
+ name: attachment.attribution_app.name,
87
+ logo: attachment.attribution_app.square_logo
88
+ }
89
+ : null
90
+ };
91
+ case "MessageVideo":
92
+ return {
93
+ type: "video",
94
+ ID: attachment.legacy_attachment_id,
95
+ filename: attachment.filename,
96
+ original_extension: getExtension(
97
+ attachment.original_extension,
98
+ attachment.filename
99
+ ),
100
+ duration: attachment.playable_duration_in_ms,
101
+
102
+ thumbnailUrl: attachment.large_image.uri, // @Legacy
103
+
104
+ previewUrl: attachment.large_image.uri,
105
+ previewWidth: attachment.large_image.width,
106
+ previewHeight: attachment.large_image.height,
107
+
108
+ url: attachment.playable_url,
109
+ width: attachment.original_dimensions.x,
110
+ height: attachment.original_dimensions.y,
111
+
112
+ videoType: attachment.video_type.toLowerCase()
113
+ };
114
+ case "MessageFile":
115
+ return {
116
+ type: "file",
117
+ ID: attachment.message_file_fbid,
118
+ filename: attachment.filename,
119
+ original_extension: getExtension(
120
+ attachment.original_extension,
121
+ attachment.filename
122
+ ),
123
+
124
+ url: attachment.url,
125
+ isMalicious: attachment.is_malicious,
126
+ contentType: attachment.content_type,
127
+
128
+ name: attachment.filename, // @Legacy
129
+ mimeType: "", // @Legacy
130
+ fileSize: -1 // @Legacy
131
+ };
132
+ case "MessageAudio":
133
+ return {
134
+ type: "audio",
135
+ ID: attachment.url_shimhash, // Not fowardable
136
+ filename: attachment.filename,
137
+ original_extension: getExtension(
138
+ attachment.original_extension,
139
+ attachment.filename
140
+ ),
141
+
142
+ duration: attachment.playable_duration_in_ms,
143
+ audioType: attachment.audio_type,
144
+ url: attachment.playable_url,
145
+
146
+ isVoiceMail: attachment.is_voicemail
147
+ };
148
+ default:
149
+ return {
150
+ error: "Don't know about attachment type " + attachment.__typename
151
+ };
152
+ }
153
+ }
154
+
155
+ function formatExtensibleAttachment(attachment) {
156
+ if (attachment.story_attachment) {
157
+ return {
158
+ type: "share",
159
+ ID: attachment.legacy_attachment_id,
160
+ url: attachment.story_attachment.url,
161
+
162
+ title: attachment.story_attachment.title_with_entities.text,
163
+ description:
164
+ attachment.story_attachment.description &&
165
+ attachment.story_attachment.description.text,
166
+ source:
167
+ attachment.story_attachment.source == null
168
+ ? null
169
+ : attachment.story_attachment.source.text,
170
+
171
+ image:
172
+ attachment.story_attachment.media == null
173
+ ? null
174
+ : attachment.story_attachment.media.animated_image == null &&
175
+ attachment.story_attachment.media.image == null
176
+ ? null
177
+ : (
178
+ attachment.story_attachment.media.animated_image ||
179
+ attachment.story_attachment.media.image
180
+ ).uri,
181
+ width:
182
+ attachment.story_attachment.media == null
183
+ ? null
184
+ : attachment.story_attachment.media.animated_image == null &&
185
+ attachment.story_attachment.media.image == null
186
+ ? null
187
+ : (
188
+ attachment.story_attachment.media.animated_image ||
189
+ attachment.story_attachment.media.image
190
+ ).width,
191
+ height:
192
+ attachment.story_attachment.media == null
193
+ ? null
194
+ : attachment.story_attachment.media.animated_image == null &&
195
+ attachment.story_attachment.media.image == null
196
+ ? null
197
+ : (
198
+ attachment.story_attachment.media.animated_image ||
199
+ attachment.story_attachment.media.image
200
+ ).height,
201
+ playable:
202
+ attachment.story_attachment.media == null
203
+ ? null
204
+ : attachment.story_attachment.media.is_playable,
205
+ duration:
206
+ attachment.story_attachment.media == null
207
+ ? null
208
+ : attachment.story_attachment.media.playable_duration_in_ms,
209
+ playableUrl:
210
+ attachment.story_attachment.media == null
211
+ ? null
212
+ : attachment.story_attachment.media.playable_url,
213
+
214
+ subattachments: attachment.story_attachment.subattachments,
215
+
216
+ // Format example:
217
+ //
218
+ // [{
219
+ // key: "width",
220
+ // value: { text: "1280" }
221
+ // }]
222
+ //
223
+ // That we turn into:
224
+ //
225
+ // {
226
+ // width: "1280"
227
+ // }
228
+ //
229
+ properties: attachment.story_attachment.properties.reduce(function(
230
+ obj,
231
+ cur
232
+ ) {
233
+ obj[cur.key] = cur.value.text;
234
+ return obj;
235
+ },
236
+ {}),
237
+
238
+ // Deprecated fields
239
+ animatedImageSize: "", // @Legacy
240
+ facebookUrl: "", // @Legacy
241
+ styleList: "", // @Legacy
242
+ target: "", // @Legacy
243
+ thumbnailUrl:
244
+ attachment.story_attachment.media == null
245
+ ? null
246
+ : attachment.story_attachment.media.animated_image == null &&
247
+ attachment.story_attachment.media.image == null
248
+ ? null
249
+ : (
250
+ attachment.story_attachment.media.animated_image ||
251
+ attachment.story_attachment.media.image
252
+ ).uri, // @Legacy
253
+ thumbnailWidth:
254
+ attachment.story_attachment.media == null
255
+ ? null
256
+ : attachment.story_attachment.media.animated_image == null &&
257
+ attachment.story_attachment.media.image == null
258
+ ? null
259
+ : (
260
+ attachment.story_attachment.media.animated_image ||
261
+ attachment.story_attachment.media.image
262
+ ).width, // @Legacy
263
+ thumbnailHeight:
264
+ attachment.story_attachment.media == null
265
+ ? null
266
+ : attachment.story_attachment.media.animated_image == null &&
267
+ attachment.story_attachment.media.image == null
268
+ ? null
269
+ : (
270
+ attachment.story_attachment.media.animated_image ||
271
+ attachment.story_attachment.media.image
272
+ ).height // @Legacy
273
+ };
274
+ } else {
275
+ return { error: "Don't know what to do with extensible_attachment." };
276
+ }
277
+ }
278
+
279
+ function formatReactionsGraphQL(reaction) {
280
+ return {
281
+ reaction: reaction.reaction,
282
+ userID: reaction.user.id
283
+ };
284
+ }
285
+
286
+ function formatEventData(event) {
287
+ if (event == null) {
288
+ return {};
289
+ }
290
+
291
+ switch (event.__typename) {
292
+ case "ThemeColorExtensibleMessageAdminText":
293
+ return {
294
+ color: event.theme_color
295
+ };
296
+ case "ThreadNicknameExtensibleMessageAdminText":
297
+ return {
298
+ nickname: event.nickname,
299
+ participantID: event.participant_id
300
+ };
301
+ case "ThreadIconExtensibleMessageAdminText":
302
+ return {
303
+ threadIcon: event.thread_icon
304
+ };
305
+ case "InstantGameUpdateExtensibleMessageAdminText":
306
+ return {
307
+ gameID: event.game == null ? null : event.game.id,
308
+ update_type: event.update_type,
309
+ collapsed_text: event.collapsed_text,
310
+ expanded_text: event.expanded_text,
311
+ instant_game_update_data: event.instant_game_update_data
312
+ };
313
+ case "GameScoreExtensibleMessageAdminText":
314
+ return {
315
+ game_type: event.game_type
316
+ };
317
+ case "RtcCallLogExtensibleMessageAdminText":
318
+ return {
319
+ event: event.event,
320
+ is_video_call: event.is_video_call,
321
+ server_info_data: event.server_info_data
322
+ };
323
+ case "GroupPollExtensibleMessageAdminText":
324
+ return {
325
+ event_type: event.event_type,
326
+ total_count: event.total_count,
327
+ question: event.question
328
+ };
329
+ case "AcceptPendingThreadExtensibleMessageAdminText":
330
+ return {
331
+ accepter_id: event.accepter_id,
332
+ requester_id: event.requester_id
333
+ };
334
+ case "ConfirmFriendRequestExtensibleMessageAdminText":
335
+ return {
336
+ friend_request_recipient: event.friend_request_recipient,
337
+ friend_request_sender: event.friend_request_sender
338
+ };
339
+ case "AddContactExtensibleMessageAdminText":
340
+ return {
341
+ contact_added_id: event.contact_added_id,
342
+ contact_adder_id: event.contact_adder_id
343
+ };
344
+ case "AdExtensibleMessageAdminText":
345
+ return {
346
+ ad_client_token: event.ad_client_token,
347
+ ad_id: event.ad_id,
348
+ ad_preferences_link: event.ad_preferences_link,
349
+ ad_properties: event.ad_properties
350
+ };
351
+ // never data
352
+ case "ParticipantJoinedGroupCallExtensibleMessageAdminText":
353
+ case "ThreadEphemeralTtlModeExtensibleMessageAdminText":
354
+ case "StartedSharingVideoExtensibleMessageAdminText":
355
+ case "LightweightEventCreateExtensibleMessageAdminText":
356
+ case "LightweightEventNotifyExtensibleMessageAdminText":
357
+ case "LightweightEventNotifyBeforeEventExtensibleMessageAdminText":
358
+ case "LightweightEventUpdateTitleExtensibleMessageAdminText":
359
+ case "LightweightEventUpdateTimeExtensibleMessageAdminText":
360
+ case "LightweightEventUpdateLocationExtensibleMessageAdminText":
361
+ case "LightweightEventDeleteExtensibleMessageAdminText":
362
+ return {};
363
+ default:
364
+ return {
365
+ error: "Don't know what to with event data type " + event.__typename
366
+ };
367
+ }
368
+ }
369
+
370
+ function formatMessagesGraphQLResponse(data) {
371
+ const messageThread = data.o0.data.message_thread;
372
+ const threadID = messageThread.thread_key.thread_fbid
373
+ ? messageThread.thread_key.thread_fbid
374
+ : messageThread.thread_key.other_user_id;
375
+
376
+ const messages = messageThread.messages.nodes.map(function(d) {
377
+ switch (d.__typename) {
378
+ case "UserMessage":
379
+ // Give priority to stickers. They're seen as normal messages but we've
380
+ // been considering them as attachments.
381
+ var maybeStickerAttachment;
382
+ if (d.sticker) {
383
+ maybeStickerAttachment = [
384
+ {
385
+ type: "sticker",
386
+ ID: d.sticker.id,
387
+ url: d.sticker.url,
388
+
389
+ packID: d.sticker.pack ? d.sticker.pack.id : null,
390
+ spriteUrl: d.sticker.sprite_image,
391
+ spriteUrl2x: d.sticker.sprite_image_2x,
392
+ width: d.sticker.width,
393
+ height: d.sticker.height,
394
+
395
+ caption: d.snippet, // Not sure what the heck caption was.
396
+ description: d.sticker.label, // Not sure about this one either.
397
+
398
+ frameCount: d.sticker.frame_count,
399
+ frameRate: d.sticker.frame_rate,
400
+ framesPerRow: d.sticker.frames_per_row,
401
+ framesPerCol: d.sticker.frames_per_col,
402
+
403
+ stickerID: d.sticker.id, // @Legacy
404
+ spriteURI: d.sticker.sprite_image, // @Legacy
405
+ spriteURI2x: d.sticker.sprite_image_2x // @Legacy
406
+ }
407
+ ];
408
+ }
409
+
410
+ var mentionsObj = {};
411
+ if (d.message !== null) {
412
+ d.message.ranges.forEach(e => {
413
+ mentionsObj[e.entity.id] = d.message.text.substr(
414
+ e.offset,
415
+ e.length
416
+ );
417
+ });
418
+ }
419
+
420
+ return {
421
+ type: "message",
422
+ attachments: maybeStickerAttachment
423
+ ? maybeStickerAttachment
424
+ : d.blob_attachments && d.blob_attachments.length > 0
425
+ ? d.blob_attachments.map(formatAttachmentsGraphQLResponse)
426
+ : d.extensible_attachment
427
+ ? [formatExtensibleAttachment(d.extensible_attachment)]
428
+ : [],
429
+ body: d.message !== null ? d.message.text : "",
430
+ isGroup: messageThread.thread_type === "GROUP",
431
+ messageID: d.message_id,
432
+ senderID: d.message_sender.id,
433
+ threadID: threadID,
434
+ timestamp: d.timestamp_precise,
435
+
436
+ mentions: mentionsObj,
437
+ isUnread: d.unread,
438
+
439
+ // New
440
+ messageReactions: d.message_reactions
441
+ ? d.message_reactions.map(formatReactionsGraphQL)
442
+ : null,
443
+ isSponsored: d.is_sponsored,
444
+ snippet: d.snippet
445
+ };
446
+ case "ThreadNameMessage":
447
+ return {
448
+ type: "event",
449
+ messageID: d.message_id,
450
+ threadID: threadID,
451
+ isGroup: messageThread.thread_type === "GROUP",
452
+ senderID: d.message_sender.id,
453
+ timestamp: d.timestamp_precise,
454
+ eventType: "change_thread_name",
455
+ snippet: d.snippet,
456
+ eventData: {
457
+ threadName: d.thread_name
458
+ },
459
+
460
+ // @Legacy
461
+ author: d.message_sender.id,
462
+ logMessageType: "log:thread-name",
463
+ logMessageData: { name: d.thread_name }
464
+ };
465
+ case "ThreadImageMessage":
466
+ return {
467
+ type: "event",
468
+ messageID: d.message_id,
469
+ threadID: threadID,
470
+ isGroup: messageThread.thread_type === "GROUP",
471
+ senderID: d.message_sender.id,
472
+ timestamp: d.timestamp_precise,
473
+ eventType: "change_thread_image",
474
+ snippet: d.snippet,
475
+ eventData:
476
+ d.image_with_metadata == null
477
+ ? {} /* removed image */
478
+ : {
479
+ /* image added */
480
+ threadImage: {
481
+ attachmentID: d.image_with_metadata.legacy_attachment_id,
482
+ width: d.image_with_metadata.original_dimensions.x,
483
+ height: d.image_with_metadata.original_dimensions.y,
484
+ url: d.image_with_metadata.preview.uri
485
+ }
486
+ },
487
+
488
+ // @Legacy
489
+ logMessageType: "log:thread-icon",
490
+ logMessageData: {
491
+ thread_icon: d.image_with_metadata
492
+ ? d.image_with_metadata.preview.uri
493
+ : null
494
+ }
495
+ };
496
+ case "ParticipantLeftMessage":
497
+ return {
498
+ type: "event",
499
+ messageID: d.message_id,
500
+ threadID: threadID,
501
+ isGroup: messageThread.thread_type === "GROUP",
502
+ senderID: d.message_sender.id,
503
+ timestamp: d.timestamp_precise,
504
+ eventType: "remove_participants",
505
+ snippet: d.snippet,
506
+ eventData: {
507
+ // Array of IDs.
508
+ participantsRemoved: d.participants_removed.map(function(p) {
509
+ return p.id;
510
+ })
511
+ },
512
+
513
+ // @Legacy
514
+ logMessageType: "log:unsubscribe",
515
+ logMessageData: {
516
+ leftParticipantFbId: d.participants_removed.map(function(p) {
517
+ return p.id;
518
+ })
519
+ }
520
+ };
521
+ case "ParticipantsAddedMessage":
522
+ return {
523
+ type: "event",
524
+ messageID: d.message_id,
525
+ threadID: threadID,
526
+ isGroup: messageThread.thread_type === "GROUP",
527
+ senderID: d.message_sender.id,
528
+ timestamp: d.timestamp_precise,
529
+ eventType: "add_participants",
530
+ snippet: d.snippet,
531
+ eventData: {
532
+ // Array of IDs.
533
+ participantsAdded: d.participants_added.map(function(p) {
534
+ return p.id;
535
+ })
536
+ },
537
+
538
+ // @Legacy
539
+ logMessageType: "log:subscribe",
540
+ logMessageData: {
541
+ addedParticipants: d.participants_added.map(function(p) {
542
+ return p.id;
543
+ })
544
+ }
545
+ };
546
+ case "VideoCallMessage":
547
+ return {
548
+ type: "event",
549
+ messageID: d.message_id,
550
+ threadID: threadID,
551
+ isGroup: messageThread.thread_type === "GROUP",
552
+ senderID: d.message_sender.id,
553
+ timestamp: d.timestamp_precise,
554
+ eventType: "video_call",
555
+ snippet: d.snippet,
556
+
557
+ // @Legacy
558
+ logMessageType: "other"
559
+ };
560
+ case "VoiceCallMessage":
561
+ return {
562
+ type: "event",
563
+ messageID: d.message_id,
564
+ threadID: threadID,
565
+ isGroup: messageThread.thread_type === "GROUP",
566
+ senderID: d.message_sender.id,
567
+ timestamp: d.timestamp_precise,
568
+ eventType: "voice_call",
569
+ snippet: d.snippet,
570
+
571
+ // @Legacy
572
+ logMessageType: "other"
573
+ };
574
+ case "GenericAdminTextMessage":
575
+ return {
576
+ type: "event",
577
+ messageID: d.message_id,
578
+ threadID: threadID,
579
+ isGroup: messageThread.thread_type === "GROUP",
580
+ senderID: d.message_sender.id,
581
+ timestamp: d.timestamp_precise,
582
+ snippet: d.snippet,
583
+ eventType: d.extensible_message_admin_text_type.toLowerCase(),
584
+ eventData: formatEventData(d.extensible_message_admin_text),
585
+
586
+ // @Legacy
587
+ logMessageType: getAdminTextMessageType(
588
+ d.extensible_message_admin_text_type
589
+ ),
590
+ logMessageData: d.extensible_message_admin_text // Maybe different?
591
+ };
592
+ default:
593
+ return { error: "Don't know about message type " + d.__typename };
594
+ }
595
+ });
596
+ return messages;
597
+ }
598
+
599
+ module.exports = function(defaultFuncs, api, ctx) {
600
+ return function getThreadHistoryGraphQL(
601
+ threadID,
602
+ amount,
603
+ timestamp,
604
+ callback
605
+ ) {
606
+ let resolveFunc = function() {};
607
+ let rejectFunc = function() {};
608
+ const returnPromise = new Promise(function(resolve, reject) {
609
+ resolveFunc = resolve;
610
+ rejectFunc = reject;
611
+ });
612
+
613
+ if (!callback) {
614
+ callback = function(err, data) {
615
+ if (err) {
616
+ return rejectFunc(err);
617
+ }
618
+ resolveFunc(data);
619
+ };
620
+ }
621
+
622
+ // `queries` has to be a string. I couldn't tell from the dev console. This
623
+ // took me a really long time to figure out. I deserve a cookie for this.
624
+ const form = {
625
+ av: ctx.userID,
626
+ queries: JSON.stringify({
627
+ o0: {
628
+ // This doc_id was valid on February 2nd 2017.
629
+ doc_id: "1498317363570230",
630
+ query_params: {
631
+ id: threadID,
632
+ message_limit: amount,
633
+ load_messages: 1,
634
+ load_read_receipts: false,
635
+ before: timestamp
636
+ }
637
+ }
638
+ })
639
+ };
640
+
641
+ defaultFuncs
642
+ .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, form)
643
+ .then(parseAndCheckLogin(ctx, defaultFuncs))
644
+ .then(function(resData) {
645
+ if (resData.error) {
646
+ throw resData;
647
+ }
648
+ // This returns us an array of things. The last one is the success /
649
+ // failure one.
650
+ // @TODO What do we do in this case?
651
+ if (resData[resData.length - 1].error_results !== 0) {
652
+ throw new Error("There was an error_result.");
653
+ }
654
+
655
+ callback(null, formatMessagesGraphQLResponse(resData[0]));
656
+ })
657
+ .catch(function(err) {
658
+ log.error("getThreadHistoryGraphQL", err);
659
+ return callback(err);
660
+ });
661
+
662
+ return returnPromise;
663
+ };
664
+ };