stfca 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 (82) hide show
  1. package/LICENSE-MIT +4 -0
  2. package/README.md +325 -0
  3. package/index.d.ts +615 -0
  4. package/index.js +1 -0
  5. package/module/config.js +33 -0
  6. package/module/login.js +48 -0
  7. package/module/loginHelper.js +722 -0
  8. package/module/options.js +44 -0
  9. package/package.json +69 -0
  10. package/src/api/action/addExternalModule.js +25 -0
  11. package/src/api/action/changeAvatar.js +137 -0
  12. package/src/api/action/changeBio.js +75 -0
  13. package/src/api/action/getCurrentUserID.js +7 -0
  14. package/src/api/action/handleFriendRequest.js +57 -0
  15. package/src/api/action/logout.js +76 -0
  16. package/src/api/action/refreshFb_dtsg.js +71 -0
  17. package/src/api/action/setPostReaction.js +106 -0
  18. package/src/api/action/unfriend.js +54 -0
  19. package/src/api/http/httpGet.js +46 -0
  20. package/src/api/http/httpPost.js +52 -0
  21. package/src/api/http/postFormData.js +47 -0
  22. package/src/api/messaging/addUserToGroup.js +68 -0
  23. package/src/api/messaging/changeAdminStatus.js +122 -0
  24. package/src/api/messaging/changeArchivedStatus.js +55 -0
  25. package/src/api/messaging/changeBlockedStatus.js +48 -0
  26. package/src/api/messaging/changeGroupImage.js +90 -0
  27. package/src/api/messaging/changeNickname.js +70 -0
  28. package/src/api/messaging/changeThreadColor.js +79 -0
  29. package/src/api/messaging/changeThreadEmoji.js +106 -0
  30. package/src/api/messaging/createNewGroup.js +88 -0
  31. package/src/api/messaging/createPoll.js +43 -0
  32. package/src/api/messaging/deleteMessage.js +56 -0
  33. package/src/api/messaging/deleteThread.js +56 -0
  34. package/src/api/messaging/editMessage.js +68 -0
  35. package/src/api/messaging/forwardAttachment.js +51 -0
  36. package/src/api/messaging/getEmojiUrl.js +29 -0
  37. package/src/api/messaging/getFriendsList.js +82 -0
  38. package/src/api/messaging/getMessage.js +829 -0
  39. package/src/api/messaging/handleMessageRequest.js +65 -0
  40. package/src/api/messaging/markAsDelivered.js +57 -0
  41. package/src/api/messaging/markAsRead.js +88 -0
  42. package/src/api/messaging/markAsReadAll.js +49 -0
  43. package/src/api/messaging/markAsSeen.js +61 -0
  44. package/src/api/messaging/muteThread.js +50 -0
  45. package/src/api/messaging/removeUserFromGroup.js +105 -0
  46. package/src/api/messaging/resolvePhotoUrl.js +43 -0
  47. package/src/api/messaging/searchForThread.js +52 -0
  48. package/src/api/messaging/sendMessage.js +379 -0
  49. package/src/api/messaging/sendMessageMqtt.js +323 -0
  50. package/src/api/messaging/sendTypingIndicator.js +67 -0
  51. package/src/api/messaging/setMessageReaction.js +75 -0
  52. package/src/api/messaging/setTitle.js +119 -0
  53. package/src/api/messaging/shareContact.js +49 -0
  54. package/src/api/messaging/threadColors.js +128 -0
  55. package/src/api/messaging/unsendMessage.js +81 -0
  56. package/src/api/messaging/uploadAttachment.js +95 -0
  57. package/src/api/socket/core/connectMqtt.js +179 -0
  58. package/src/api/socket/core/getSeqID.js +25 -0
  59. package/src/api/socket/core/getTaskResponseData.js +22 -0
  60. package/src/api/socket/core/markDelivery.js +12 -0
  61. package/src/api/socket/core/parseDelta.js +351 -0
  62. package/src/api/socket/detail/buildStream.js +208 -0
  63. package/src/api/socket/detail/constants.js +24 -0
  64. package/src/api/socket/listenMqtt.js +133 -0
  65. package/src/api/threads/getThreadHistory.js +664 -0
  66. package/src/api/threads/getThreadInfo.js +358 -0
  67. package/src/api/threads/getThreadList.js +248 -0
  68. package/src/api/threads/getThreadPictures.js +78 -0
  69. package/src/api/users/getUserID.js +65 -0
  70. package/src/api/users/getUserInfo.js +319 -0
  71. package/src/api/users/getUserInfoV2.js +133 -0
  72. package/src/core/sendReqMqtt.js +63 -0
  73. package/src/database/models/index.js +49 -0
  74. package/src/database/models/thread.js +31 -0
  75. package/src/database/models/user.js +32 -0
  76. package/src/database/threadData.js +98 -0
  77. package/src/database/userData.js +89 -0
  78. package/src/utils/client.js +214 -0
  79. package/src/utils/constants.js +23 -0
  80. package/src/utils/format.js +1111 -0
  81. package/src/utils/headers.js +41 -0
  82. package/src/utils/request.js +215 -0
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ function getHeaders(url, options, ctx, customHeader) {
4
+ const u = new URL(url);
5
+ const ua = options?.userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36";
6
+ const referer = options?.referer || "https://www.facebook.com/";
7
+ const origin = referer.replace(/\/+$/, "");
8
+ const contentType = options?.contentType || "application/x-www-form-urlencoded";
9
+ const acceptLang = options?.acceptLanguage || "en-US,en;q=0.9,vi;q=0.8";
10
+ const headers = {
11
+ Host: u.host,
12
+ Origin: origin,
13
+ Referer: referer,
14
+ "User-Agent": ua,
15
+ Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,application/json;q=0.8,*/*;q=0.7",
16
+ "Accept-Language": acceptLang,
17
+ "Accept-Encoding": "gzip, deflate, br",
18
+ "Content-Type": contentType,
19
+ Connection: "keep-alive",
20
+ DNT: "1",
21
+ "Upgrade-Insecure-Requests": "1",
22
+ "sec-ch-ua": "\"Chromium\";v=\"139\", \"Not;A=Brand\";v=\"24\", \"Google Chrome\";v=\"139\"",
23
+ "sec-ch-ua-mobile": "?0",
24
+ "sec-ch-ua-platform": "\"Windows\"",
25
+ "sec-ch-ua-arch": "\"x86\"",
26
+ "sec-ch-ua-bitness": "\"64\"",
27
+ "sec-ch-ua-full-version-list": "\"Chromium\";v=\"139.0.0.0\", \"Not;A=Brand\";v=\"24.0.0.0\", \"Google Chrome\";v=\"139.0.0.0\"",
28
+ "sec-ch-ua-platform-version": "\"15.0.0\"",
29
+ "Sec-Fetch-Site": "same-origin",
30
+ "Sec-Fetch-Mode": "cors",
31
+ "Sec-Fetch-Dest": "empty",
32
+ "X-Requested-With": "XMLHttpRequest",
33
+ Pragma: "no-cache",
34
+ "Cache-Control": "no-cache"
35
+ };
36
+ if (ctx?.region) headers["X-MSGR-Region"] = ctx.region;
37
+ if (customHeader && typeof customHeader === "object") Object.assign(headers, customHeader);
38
+ return headers;
39
+ }
40
+
41
+ module.exports = { getHeaders };
@@ -0,0 +1,215 @@
1
+ const axios = require("axios");
2
+ const { CookieJar } = require("tough-cookie");
3
+ const { wrapper } = require("axios-cookiejar-support");
4
+ const FormData = require("form-data");
5
+ const { HttpsProxyAgent } = require("https-proxy-agent");
6
+ const { Readable } = require("stream");
7
+
8
+ const headersMod = require("./headers");
9
+ const getHeaders = headersMod.getHeaders || headersMod;
10
+ const formatMod = require("./format");
11
+ const getType = formatMod.getType || formatMod;
12
+ const constMod = require("./constants");
13
+ const getFrom = constMod.getFrom || constMod;
14
+
15
+ const jar = new CookieJar();
16
+ const client = wrapper(axios.create({
17
+ jar,
18
+ withCredentials: true,
19
+ timeout: 60000,
20
+ validateStatus: s => s >= 200 && s < 600
21
+ }));
22
+
23
+ const delay = ms => new Promise(r => setTimeout(r, ms));
24
+
25
+ async function requestWithRetry(fn, retries = 3) {
26
+ let err;
27
+ for (let i = 0; i < retries; i++) {
28
+ try { return await fn(); } catch (e) {
29
+ err = e;
30
+ if (i === retries - 1) return e.response ? e.response : Promise.reject(e);
31
+ await delay((1 << i) * 1000 + Math.floor(Math.random() * 200));
32
+ }
33
+ }
34
+ throw err;
35
+ }
36
+
37
+ function cfg(base = {}) {
38
+ const { reqJar, headers, params, agent, timeout } = base;
39
+ return {
40
+ headers,
41
+ params,
42
+ jar: reqJar || jar,
43
+ withCredentials: true,
44
+ timeout: timeout || 60000,
45
+ httpAgent: agent || client.defaults.httpAgent,
46
+ httpsAgent: agent || client.defaults.httpsAgent,
47
+ proxy: false,
48
+ validateStatus: s => s >= 200 && s < 600
49
+ };
50
+ }
51
+
52
+ function toStringVal(v) {
53
+ if (v === undefined || v === null) return "";
54
+ if (typeof v === "bigint") return v.toString();
55
+ if (typeof v === "boolean") return v ? "true" : "false";
56
+ return String(v);
57
+ }
58
+
59
+ function isStream(v) {
60
+ return v && typeof v === "object" && typeof v.pipe === "function" && typeof v.on === "function";
61
+ }
62
+
63
+ function isBlobLike(v) {
64
+ return v && typeof v.arrayBuffer === "function" && (typeof v.type === "string" || typeof v.name === "string");
65
+ }
66
+
67
+ function isPairArrayList(arr) {
68
+ return Array.isArray(arr) && arr.length > 0 && arr.every(x => Array.isArray(x) && x.length === 2 && typeof x[0] === "string");
69
+ }
70
+
71
+ function cleanGet(url) {
72
+ return requestWithRetry(() => client.get(url, cfg()));
73
+ }
74
+
75
+ function get(url, reqJar, qs, options, ctx, customHeader) {
76
+ const headers = getHeaders(url, options, ctx, customHeader);
77
+ return requestWithRetry(() => client.get(url, cfg({ reqJar, headers, params: qs })));
78
+ }
79
+
80
+ function post(url, reqJar, form, options, ctx, customHeader) {
81
+ const headers = getHeaders(url, options, ctx, customHeader);
82
+ const ct = String(headers["Content-Type"] || headers["content-type"] || "application/x-www-form-urlencoded").toLowerCase();
83
+ let data;
84
+ if (ct.includes("json")) {
85
+ data = JSON.stringify(form || {});
86
+ headers["Content-Type"] = "application/json";
87
+ } else {
88
+ const p = new URLSearchParams();
89
+ if (form && typeof form === "object") {
90
+ for (const k of Object.keys(form)) {
91
+ let v = form[k];
92
+ if (isPairArrayList(v)) {
93
+ for (const [kk, vv] of v) p.append(`${k}[${kk}]`, toStringVal(vv));
94
+ continue;
95
+ }
96
+ if (Array.isArray(v)) {
97
+ for (const x of v) {
98
+ if (Array.isArray(x) && x.length === 2 && typeof x[1] !== "object") p.append(k, toStringVal(x[1]));
99
+ else p.append(k, toStringVal(x));
100
+ }
101
+ continue;
102
+ }
103
+ if (getType(v) === "Object") v = JSON.stringify(v);
104
+ p.append(k, toStringVal(v));
105
+ }
106
+ }
107
+ data = p.toString();
108
+ headers["Content-Type"] = "application/x-www-form-urlencoded";
109
+ }
110
+ return requestWithRetry(() => client.post(url, data, cfg({ reqJar, headers })));
111
+ }
112
+
113
+ async function postFormData(url, reqJar, form, qs, options, ctx) {
114
+ const fd = new FormData();
115
+ if (form && typeof form === "object") {
116
+ for (const k of Object.keys(form)) {
117
+ const v = form[k];
118
+ if (v === undefined || v === null) continue;
119
+ if (isPairArrayList(v)) {
120
+ for (const [kk, vv] of v) fd.append(`${k}[${kk}]`, typeof vv === "object" && !Buffer.isBuffer(vv) && !isStream(vv) ? JSON.stringify(vv) : vv);
121
+ continue;
122
+ }
123
+ if (Array.isArray(v)) {
124
+ for (const x of v) {
125
+ if (Array.isArray(x) && x.length === 2 && x[1] && typeof x[1] === "object" && !Buffer.isBuffer(x[1]) && !isStream(x[1])) {
126
+ fd.append(k, x[0], x[1]);
127
+ } else if (Array.isArray(x) && x.length === 2 && typeof x[1] !== "object") {
128
+ fd.append(k, toStringVal(x[1]));
129
+ } else if (x && typeof x === "object" && "value" in x && "options" in x) {
130
+ fd.append(k, x.value, x.options || {});
131
+ } else if (isStream(x) || Buffer.isBuffer(x) || typeof x === "string") {
132
+ fd.append(k, x);
133
+ } else if (isBlobLike(x)) {
134
+ const buf = Buffer.from(await x.arrayBuffer());
135
+ fd.append(k, buf, { filename: x.name || k, contentType: x.type || undefined });
136
+ } else {
137
+ fd.append(k, JSON.stringify(x));
138
+ }
139
+ }
140
+ continue;
141
+ }
142
+ if (v && typeof v === "object" && "value" in v && "options" in v) {
143
+ fd.append(k, v.value, v.options || {});
144
+ continue;
145
+ }
146
+ if (isStream(v) || Buffer.isBuffer(v) || typeof v === "string") {
147
+ fd.append(k, v);
148
+ continue;
149
+ }
150
+ if (isBlobLike(v)) {
151
+ const buf = Buffer.from(await v.arrayBuffer());
152
+ fd.append(k, buf, { filename: v.name || k, contentType: v.type || undefined });
153
+ continue;
154
+ }
155
+ if (typeof v === "number" || typeof v === "boolean") {
156
+ fd.append(k, toStringVal(v));
157
+ continue;
158
+ }
159
+ fd.append(k, JSON.stringify(v));
160
+ }
161
+ }
162
+ const headers = { ...getHeaders(url, options, ctx), ...fd.getHeaders() };
163
+ return requestWithRetry(() => client.post(url, fd, cfg({ reqJar, headers, params: qs })));
164
+ }
165
+
166
+ function makeDefaults(html, userID, ctx) {
167
+ let reqCounter = 1;
168
+ const revision = getFrom(html || "", 'revision":', ",") || getFrom(html || "", '"client_revision":', ",") || "";
169
+ function mergeWithDefaults(obj) {
170
+ const base = {
171
+ av: userID,
172
+ __user: userID,
173
+ __req: (reqCounter++).toString(36),
174
+ __rev: revision,
175
+ __a: 1
176
+ };
177
+ if (ctx?.fb_dtsg) base.fb_dtsg = ctx.fb_dtsg;
178
+ if (ctx?.jazoest) base.jazoest = ctx.jazoest;
179
+ if (!obj) return base;
180
+ for (const k of Object.keys(obj)) if (!(k in base)) base[k] = obj[k];
181
+ return base;
182
+ }
183
+ return {
184
+ get: (url, j, qs, ctxx, customHeader = {}) =>
185
+ get(url, j, mergeWithDefaults(qs), ctx?.globalOptions, ctxx || ctx, customHeader),
186
+ post: (url, j, form, ctxx, customHeader = {}) =>
187
+ post(url, j, mergeWithDefaults(form), ctx?.globalOptions, ctxx || ctx, customHeader),
188
+ postFormData: (url, j, form, qs, ctxx) =>
189
+ postFormData(url, j, mergeWithDefaults(form), mergeWithDefaults(qs), ctx?.globalOptions, ctxx || ctx)
190
+ };
191
+ }
192
+
193
+ function setProxy(proxyUrl) {
194
+ if (!proxyUrl) {
195
+ client.defaults.httpAgent = undefined;
196
+ client.defaults.httpsAgent = undefined;
197
+ client.defaults.proxy = false;
198
+ return;
199
+ }
200
+ const agent = new HttpsProxyAgent(proxyUrl);
201
+ client.defaults.httpAgent = agent;
202
+ client.defaults.httpsAgent = agent;
203
+ client.defaults.proxy = false;
204
+ }
205
+
206
+ module.exports = {
207
+ cleanGet,
208
+ get,
209
+ post,
210
+ postFormData,
211
+ jar,
212
+ setProxy,
213
+ makeDefaults,
214
+ client
215
+ };