@dongdev/fca-unofficial 1.0.20 → 2.0.1

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 (128) hide show
  1. package/.gitattributes +1 -0
  2. package/CHANGELOG.md +32 -29
  3. package/DOCS.md +727 -592
  4. package/README.md +94 -97
  5. package/func/logger.js +112 -0
  6. package/html.html +474 -0
  7. package/index.js +1 -379
  8. package/module/config.js +26 -0
  9. package/module/login.js +45 -0
  10. package/module/loginHelper.js +634 -0
  11. package/module/options.js +49 -0
  12. package/package.json +6 -39
  13. package/src/api/action/addExternalModule.js +25 -0
  14. package/src/api/action/changeAvatar.js +136 -0
  15. package/src/api/action/changeBio.js +76 -0
  16. package/src/api/action/getCurrentUserID.js +7 -0
  17. package/src/api/action/handleFriendRequest.js +57 -0
  18. package/src/api/action/logout.js +75 -0
  19. package/src/{refreshFb_dtsg.js → api/action/refreshFb_dtsg.js} +8 -8
  20. package/src/api/action/setPostReaction.js +107 -0
  21. package/src/api/action/unfriend.js +55 -0
  22. package/src/api/http/httpGet.js +65 -0
  23. package/src/api/http/httpPost.js +65 -0
  24. package/src/{postFormData.js → api/http/postFormData.js} +10 -10
  25. package/src/api/messaging/addUserToGroup.js +69 -0
  26. package/src/api/messaging/changeAdminStatus.js +103 -0
  27. package/src/api/messaging/changeArchivedStatus.js +55 -0
  28. package/src/api/messaging/changeBlockedStatus.js +49 -0
  29. package/src/api/messaging/changeGroupImage.js +135 -0
  30. package/src/api/messaging/changeNickname.js +59 -0
  31. package/src/api/messaging/changeThreadColor.js +65 -0
  32. package/src/api/messaging/createNewGroup.js +88 -0
  33. package/src/api/messaging/createPoll.js +70 -0
  34. package/src/api/messaging/deleteMessage.js +56 -0
  35. package/src/api/messaging/deleteThread.js +56 -0
  36. package/src/api/messaging/forwardAttachment.js +60 -0
  37. package/src/api/messaging/getEmojiUrl.js +29 -0
  38. package/src/api/messaging/getFriendsList.js +83 -0
  39. package/src/api/messaging/getMessage.js +834 -0
  40. package/src/api/messaging/getThreadHistory.js +681 -0
  41. package/src/api/messaging/handleMessageRequest.js +65 -0
  42. package/src/api/messaging/markAsDelivered.js +57 -0
  43. package/src/api/messaging/markAsRead.js +88 -0
  44. package/src/api/messaging/markAsReadAll.js +50 -0
  45. package/src/api/messaging/markAsSeen.js +61 -0
  46. package/src/api/messaging/muteThread.js +51 -0
  47. package/src/api/messaging/removeUserFromGroup.js +79 -0
  48. package/src/api/messaging/resolvePhotoUrl.js +44 -0
  49. package/src/api/messaging/searchForThread.js +53 -0
  50. package/src/api/messaging/sendMessage.js +306 -0
  51. package/src/api/messaging/sendMessageMqtt.js +321 -0
  52. package/src/api/messaging/sendTypingIndicator.js +110 -0
  53. package/src/{setMessageReaction.js → api/messaging/setMessageReaction.js} +20 -20
  54. package/src/api/messaging/setTitle.js +90 -0
  55. package/src/api/messaging/shareContact.js +51 -0
  56. package/src/api/messaging/threadColors.js +131 -0
  57. package/src/api/messaging/unsendMessage.js +44 -0
  58. package/src/api/messaging/uploadAttachment.js +93 -0
  59. package/src/api/socket/detail/buildStream.js +100 -0
  60. package/src/{listenMqtt.js → api/socket/listenMqtt.js} +122 -206
  61. package/src/api/threads/changeThreadEmoji.js +55 -0
  62. package/src/api/threads/getThreadInfo.js +572 -0
  63. package/src/{getThreadList.js → api/threads/getThreadList.js} +110 -54
  64. package/src/api/threads/getThreadPictures.js +79 -0
  65. package/src/api/users/getUserID.js +66 -0
  66. package/src/api/users/getUserInfo.js +88 -0
  67. package/src/core/sendReqMqtt.js +63 -0
  68. package/{lib → src}/database/models/index.js +12 -10
  69. package/{lib → src}/database/models/thread.js +5 -5
  70. package/{lib → src}/database/threadData.js +19 -14
  71. package/src/utils/client.js +159 -0
  72. package/src/utils/constants.js +13 -0
  73. package/src/utils/format.js +60 -0
  74. package/src/utils/headers.js +41 -0
  75. package/src/utils/index.js +1497 -0
  76. package/src/utils/request.js +147 -0
  77. package/lib/logger.js +0 -96
  78. package/src/addExternalModule.js +0 -19
  79. package/src/addUserToGroup.js +0 -113
  80. package/src/changeAdminStatus.js +0 -79
  81. package/src/changeArchivedStatus.js +0 -55
  82. package/src/changeAvatar.js +0 -126
  83. package/src/changeBio.js +0 -77
  84. package/src/changeBlockedStatus.js +0 -47
  85. package/src/changeGroupImage.js +0 -132
  86. package/src/changeNickname.js +0 -59
  87. package/src/changeThreadColor.js +0 -65
  88. package/src/changeThreadEmoji.js +0 -55
  89. package/src/createNewGroup.js +0 -86
  90. package/src/createPoll.js +0 -71
  91. package/src/deleteMessage.js +0 -56
  92. package/src/deleteThread.js +0 -56
  93. package/src/forwardAttachment.js +0 -60
  94. package/src/getCurrentUserID.js +0 -7
  95. package/src/getEmojiUrl.js +0 -29
  96. package/src/getFriendsList.js +0 -83
  97. package/src/getMessage.js +0 -796
  98. package/src/getThreadHistory.js +0 -666
  99. package/src/getThreadInfo.js +0 -535
  100. package/src/getThreadPictures.js +0 -79
  101. package/src/getUserID.js +0 -66
  102. package/src/getUserInfo.js +0 -80
  103. package/src/handleFriendRequest.js +0 -61
  104. package/src/handleMessageRequest.js +0 -65
  105. package/src/httpGet.js +0 -57
  106. package/src/httpPost.js +0 -57
  107. package/src/httpPostFormData.js +0 -63
  108. package/src/logout.js +0 -75
  109. package/src/markAsDelivered.js +0 -58
  110. package/src/markAsRead.js +0 -80
  111. package/src/markAsReadAll.js +0 -50
  112. package/src/markAsSeen.js +0 -59
  113. package/src/muteThread.js +0 -52
  114. package/src/removeUserFromGroup.js +0 -79
  115. package/src/resolvePhotoUrl.js +0 -45
  116. package/src/searchForThread.js +0 -53
  117. package/src/sendMessage.js +0 -328
  118. package/src/sendMessageMqtt.js +0 -316
  119. package/src/sendTypingIndicator.js +0 -103
  120. package/src/setPostReaction.js +0 -109
  121. package/src/setTitle.js +0 -86
  122. package/src/shareContact.js +0 -49
  123. package/src/threadColors.js +0 -131
  124. package/src/unfriend.js +0 -52
  125. package/src/unsendMessage.js +0 -49
  126. package/src/uploadAttachment.js +0 -95
  127. package/utils.js +0 -1387
  128. /package/{lib → func}/login.js +0 -0
package/index.js CHANGED
@@ -1,379 +1 @@
1
- "use strict";
2
- const utils = require("./utils");
3
- const log = require("npmlog");
4
- const { execSync, exec } = require('child_process');
5
- const { promises: fsPromises, readFileSync } = require('fs');
6
- const fs = require('fs');
7
- const axios = require('axios');
8
- const path = require('path');
9
- const models = require("./lib/database/models");
10
- const logger = require("./lib/logger");
11
- let checkVerified = null;
12
- const defaultLogRecordSize = 100;
13
- log.maxRecordSize = defaultLogRecordSize;
14
- const defaultConfig = {
15
- autoUpdate: true,
16
- mqtt: {
17
- enabled: true,
18
- reconnectInterval: 3600,
19
- }
20
- };
21
- const configPath = path.join(process.cwd(), "fca-config.json");
22
- let config;
23
- if (!fs.existsSync(configPath)) {
24
- fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
25
- config = defaultConfig;
26
- } else {
27
- try {
28
- const fileContent = fs.readFileSync(configPath, 'utf8');
29
- config = JSON.parse(fileContent);
30
- config = { ...defaultConfig, ...config };
31
- } catch (err) {
32
- logger("Error reading config file, using defaults", "error");
33
- config = defaultConfig;
34
- }
35
- }
36
- global.fca = {
37
- config: config
38
- };
39
- const Boolean_Option = [
40
- "online",
41
- "selfListen",
42
- "listenEvents",
43
- "updatePresence",
44
- "forceLogin",
45
- "autoMarkDelivery",
46
- "autoMarkRead",
47
- "listenTyping",
48
- "autoReconnect",
49
- "emitReady",
50
- ];
51
- function setOptions(globalOptions, options) {
52
- Object.keys(options).map(function (key) {
53
- switch (Boolean_Option.includes(key)) {
54
- case true: {
55
- globalOptions[key] = Boolean(options[key]);
56
- break;
57
- }
58
- case false: {
59
- switch (key) {
60
- case "pauseLog": {
61
- if (options.pauseLog) log.pause();
62
- else log.resume();
63
- break;
64
- }
65
- case "logLevel": {
66
- log.level = options.logLevel;
67
- globalOptions.logLevel = options.logLevel;
68
- break;
69
- }
70
- case "logRecordSize": {
71
- log.maxRecordSize = options.logRecordSize;
72
- globalOptions.logRecordSize = options.logRecordSize;
73
- break;
74
- }
75
- case "pageID": {
76
- globalOptions.pageID = options.pageID.toString();
77
- break;
78
- }
79
- case "userAgent": {
80
- globalOptions.userAgent =
81
- options.userAgent ||
82
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36";
83
- break;
84
- }
85
- case "proxy": {
86
- if (typeof options.proxy != "string") {
87
- delete globalOptions.proxy;
88
- utils.setProxy();
89
- } else {
90
- globalOptions.proxy = options.proxy;
91
- utils.setProxy(globalOptions.proxy);
92
- }
93
- break;
94
- }
95
- default: {
96
- log.warn(
97
- "setOptions",
98
- "Unrecognized option given to setOptions: " + key
99
- );
100
- break;
101
- }
102
- }
103
- break;
104
- }
105
- }
106
- });
107
- }
108
- function buildAPI(globalOptions, html, jar) {
109
- const cookies = jar.getCookies("https://www.facebook.com");
110
- const userCookie = cookies.find(c => c.cookieString().startsWith("c_user="));
111
- const tiktikCookie = cookies.find(c => c.cookieString().startsWith("i_user="));
112
- if (userCookie.length === 0 && tiktikCookie.length === 0) {
113
- return log.error('login', "Không tìm thấy cookie cho người dùng, vui lòng kiểm tra lại thông tin đăng nhập")
114
- } else if (!userCookie && !tiktikCookie) {
115
- return log.error('login', "Không tìm thấy cookie cho người dùng, vui lòng kiểm tra lại thông tin đăng nhập")
116
- } else if (html.includes("/checkpoint/block/?next")) {
117
- return log.error('login', "Appstate die, vui lòng thay cái mới!", 'error');
118
- }
119
- const userID = (tiktikCookie || userCookie).cookieString().split("=")[1];
120
- const i_userID = tiktikCookie ? tiktikCookie.cookieString().split("=")[1] : null;
121
- logger(`Logged in as ${userID}`, 'info');
122
- try {
123
- clearInterval(checkVerified);
124
- } catch (_) { }
125
- const clientID = ((Math.random() * 2147483648) | 0).toString(16);
126
- let mqttEndpoint, region, fb_dtsg, irisSeqID;
127
- try {
128
- const endpointMatch = html.match(/"endpoint":"([^"]+)"/);
129
- if (endpointMatch) {
130
- mqttEndpoint = endpointMatch[1].replace(/\\\//g, "/");
131
- const url = new URL(mqttEndpoint);
132
- region = url.searchParams.get("region")?.toUpperCase() || "PRN";
133
- }
134
- logger(`Sever region ${region}`, 'info');
135
- } catch (e) {
136
- log.warning("login", "Not MQTT endpoint");
137
- }
138
- const tokenMatch = html.match(/DTSGInitialData.*?token":"(.*?)"/);
139
- if (tokenMatch) {
140
- fb_dtsg = tokenMatch[1];
141
- }
142
- (async () => {
143
- try {
144
- await models.sequelize.authenticate();
145
- await models.syncAll();
146
- } catch (error) {
147
- console.error(error);
148
- console.error('Database connection failed:', error.message);
149
- }
150
- })();
151
- logger(`FCA fix by DongDev`, 'info');
152
- const ctx = {
153
- userID: userID,
154
- i_userID: i_userID,
155
- jar: jar,
156
- clientID: clientID,
157
- globalOptions: globalOptions,
158
- loggedIn: true,
159
- access_token: "NONE",
160
- clientMutationId: 0,
161
- mqttClient: undefined,
162
- lastSeqId: irisSeqID,
163
- syncToken: undefined,
164
- mqttEndpoint,
165
- region,
166
- firstListen: true,
167
- fb_dtsg,
168
- wsReqNumber: 0,
169
- wsTaskNumber: 0
170
- };
171
- const api = {
172
- setOptions: setOptions.bind(null, globalOptions),
173
- getAppState: function getAppState() {
174
- const appState = utils.getAppState(jar);
175
- return appState.filter(
176
- (item, index, self) =>
177
- self.findIndex((t) => {
178
- return t.key === item.key;
179
- }) === index
180
- );
181
- },
182
- };
183
- const defaultFuncs = utils.makeDefaults(html, i_userID || userID, ctx);
184
- require("fs")
185
- .readdirSync(__dirname + "/src/")
186
- .filter((v) => v.endsWith(".js"))
187
- .map(function (v) {
188
- api[v.replace(".js", "")] = require("./src/" + v)(defaultFuncs, api, ctx);
189
- });
190
- api.listen = api.listenMqtt;
191
- setInterval(async () => {
192
- api
193
- .refreshFb_dtsg()
194
- .then(() => {
195
- logger("Successfully refreshed fb_dtsg", 'info');
196
- })
197
- .catch((err) => {
198
- console.error("An error occurred while refreshing fb_dtsg", err);
199
- });
200
- }, 1000 * 60 * 60 * 24);
201
- return {
202
- ctx,
203
- defaultFuncs,
204
- api
205
- };
206
- }
207
-
208
- function loginHelper(appState, email, password, globalOptions, callback, prCallback) {
209
- let mainPromise = null;
210
- const jar = utils.getJar();
211
- if (appState) {
212
- try {
213
- appState = JSON.parse(appState);
214
- } catch (e) {
215
- try {
216
- appState = appState;
217
- } catch (e) {
218
- return callback(new Error("Failed to parse appState"));
219
- }
220
- }
221
-
222
- try {
223
- appState.forEach(c => {
224
- const str = `${c.key}=${c.value}; expires=${c.expires}; domain=${c.domain}; path=${c.path};`;
225
- jar.setCookie(str, "http://" + c.domain);
226
- });
227
-
228
- mainPromise = utils.get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true })
229
- .then(utils.saveCookies(jar));
230
- } catch (e) {
231
- process.exit(0);
232
- }
233
- } else {
234
- mainPromise = utils
235
- .get("https://www.facebook.com/", null, null, globalOptions, { noRef: true })
236
- .then(utils.saveCookies(jar))
237
- .then(makeLogin(jar, email, password, globalOptions, callback, prCallback))
238
- .then(() => utils.get('https://www.facebook.com/', jar, null, globalOptions).then(utils.saveCookies(jar)));
239
- }
240
-
241
- function handleRedirect(res) {
242
- const reg = /<meta http-equiv="refresh" content="0;url=([^"]+)[^>]+>/;
243
- const redirect = reg.exec(res.body);
244
- if (redirect && redirect[1]) {
245
- return utils.get(redirect[1], jar, null, globalOptions).then(utils.saveCookies(jar));
246
- }
247
- return res;
248
- }
249
-
250
- let ctx, api;
251
- mainPromise = mainPromise
252
- .then(handleRedirect)
253
- .then(res => {
254
- const mobileAgentRegex = /MPageLoadClientMetrics/gs;
255
- if (!mobileAgentRegex.test(res.body)) {
256
- globalOptions.userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36";
257
- return utils.get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true }).then(utils.saveCookies(jar));
258
- }
259
- return res;
260
- })
261
- .then(handleRedirect)
262
- .then(res => {
263
- const html = res.body;
264
- const Obj = buildAPI(globalOptions, html, jar);
265
- ctx = Obj.ctx;
266
- api = Obj.api;
267
- return res;
268
- });
269
-
270
- if (globalOptions.pageID) {
271
- mainPromise = mainPromise
272
- .then(() => utils.get(`https://www.facebook.com/${globalOptions.pageID}/messages/?section=messages&subsection=inbox`, jar, null, globalOptions))
273
- .then(resData => {
274
- let url = utils.getFrom(resData.body, 'window.location.replace("https:\\/\\/www.facebook.com\\', '");').split('\\').join('');
275
- url = url.substring(0, url.length - 1);
276
- return utils.get('https://www.facebook.com' + url, jar, null, globalOptions);
277
- });
278
- }
279
-
280
- mainPromise
281
- .then(async () => {
282
- // if (global.fca.config.autoUpdate) {
283
- // try {
284
- // exec('npm view @dongdev/fca-unofficial version', async (error, stdout, stderr) => {
285
- // if (error) {
286
- // logger('Error checking version: ' + error, 'error');
287
- // return;
288
- // }
289
- // const npmVersion = stdout.trim();
290
- // const localbrand = JSON.parse(readFileSync('./node_modules/@dongdev/fca-unofficial/package.json')).version;
291
- // if (localbrand !== npmVersion) {
292
- // logger(`New Version Published: ${localbrand} => ${npmVersion}`, 'warn');
293
- // logger(`Perform Automatic Update to the Latest Version !`, 'warn');
294
- // try {
295
- // execSync('npm install @dongdev/fca-unofficial@latest', { stdio: 'inherit' });
296
- // logger("Upgrade Version Successfully!", "[ FCA-UNO ] >")
297
- // logger('Restarting...', '[ FCA-UNO ] >');
298
- // await new Promise(resolve => setTimeout(resolve, 5 * 1000));
299
- // console.clear();
300
- // process.exit(1);
301
- // } catch (err) {
302
- // logger('Error Auto Update ! ' + err, 'error');
303
- // }
304
- // } else {
305
- // logger(`You Are Currently Using Version: ${localbrand} !`, "[ FCA-UNO ] >");
306
- // logger(`Have a good day !`, "[ FCA-UNO ] >")
307
- // await new Promise(resolve => setTimeout(resolve, 5 * 1000));
308
- // callback(null, api);
309
- // }
310
- // });
311
- // } catch (err) {
312
- // logger('Error checking for updates: ' + err, 'error');
313
- // callback(null, api);
314
- // }
315
- // }
316
- logger('Login successful!', '[ FCA-UNO ] >');
317
- callback(null, api);
318
- })
319
- .catch(e => {
320
- callback(e);
321
- });
322
- }
323
-
324
- function login(loginData, options, callback) {
325
- if (
326
- utils.getType(options) === "Function" ||
327
- utils.getType(options) === "AsyncFunction"
328
- ) {
329
- callback = options;
330
- options = {};
331
- }
332
- const globalOptions = {
333
- selfListen: false,
334
- selfListenEvent: false,
335
- listenEvents: false,
336
- listenTyping: false,
337
- updatePresence: false,
338
- forceLogin: false,
339
- autoMarkDelivery: true,
340
- autoMarkRead: false,
341
- autoReconnect: true,
342
- logRecordSize: defaultLogRecordSize,
343
- online: true,
344
- emitReady: false,
345
- userAgent:
346
- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
347
- };
348
- setOptions(globalOptions, options);
349
- let prCallback = null;
350
- if (
351
- utils.getType(callback) !== "Function" &&
352
- utils.getType(callback) !== "AsyncFunction"
353
- ) {
354
- let rejectFunc = null;
355
- let resolveFunc = null;
356
- var returnPromise = new Promise(function (resolve, reject) {
357
- resolveFunc = resolve;
358
- rejectFunc = reject;
359
- });
360
- prCallback = function (error, api) {
361
- if (error) {
362
- return rejectFunc(error);
363
- }
364
- return resolveFunc(api);
365
- };
366
- callback = prCallback;
367
- }
368
- loginHelper(
369
- loginData.appState,
370
- loginData.email,
371
- loginData.password,
372
- globalOptions,
373
- callback,
374
- prCallback
375
- );
376
- return returnPromise;
377
- }
378
-
379
- module.exports = login;
1
+ module.exports = require("./module/login");
@@ -0,0 +1,26 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const logger = require("../func/logger");
4
+ const defaultConfig = {
5
+ autoUpdate: true,
6
+ mqtt: { enabled: true, reconnectInterval: 3600 }
7
+ };
8
+ function loadConfig() {
9
+ const configPath = path.join(process.cwd(), "fca-config.json");
10
+ let config;
11
+ if (!fs.existsSync(configPath)) {
12
+ fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
13
+ config = defaultConfig;
14
+ } else {
15
+ try {
16
+ const fileContent = fs.readFileSync(configPath, "utf8");
17
+ config = JSON.parse(fileContent);
18
+ config = Object.assign({}, defaultConfig, config);
19
+ } catch (err) {
20
+ logger("Error reading config file, using defaults", "error");
21
+ config = defaultConfig;
22
+ }
23
+ }
24
+ return { config, configPath };
25
+ }
26
+ module.exports = { loadConfig, defaultConfig };
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ const utils = require("../src/utils");
3
+ const { setOptions } = require("./options");
4
+ const { loadConfig } = require("./config");
5
+ const loginHelper = require("./loginHelper");
6
+ const { config } = loadConfig();
7
+ global.fca = { config };
8
+ function login(loginData, options, callback) {
9
+ if (utils.getType(options) === "Function" || utils.getType(options) === "AsyncFunction") {
10
+ callback = options;
11
+ options = {};
12
+ }
13
+ const globalOptions = {
14
+ selfListen: false,
15
+ selfListenEvent: false,
16
+ listenEvents: false,
17
+ listenTyping: false,
18
+ updatePresence: false,
19
+ forceLogin: false,
20
+ autoMarkDelivery: true,
21
+ autoMarkRead: false,
22
+ autoReconnect: true,
23
+ online: true,
24
+ emitReady: false,
25
+ userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36"
26
+ };
27
+ setOptions(globalOptions, options);
28
+ let prCallback = null;
29
+ if (utils.getType(callback) !== "Function" && utils.getType(callback) !== "AsyncFunction") {
30
+ let rejectFunc = null;
31
+ let resolveFunc = null;
32
+ var returnPromise = new Promise(function (resolve, reject) {
33
+ resolveFunc = resolve;
34
+ rejectFunc = reject;
35
+ });
36
+ prCallback = function (error, api) {
37
+ if (error) return rejectFunc(error);
38
+ return resolveFunc(api);
39
+ };
40
+ callback = prCallback;
41
+ }
42
+ loginHelper(loginData.appState, loginData.Cookie,loginData.email, loginData.password, globalOptions, callback, prCallback);
43
+ return returnPromise;
44
+ }
45
+ module.exports = login;