ayman-fca 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 (124) hide show
  1. package/README.md +81 -0
  2. package/func/checkUpdate.js +13 -0
  3. package/func/logAdapter.js +30 -0
  4. package/func/logger.js +66 -0
  5. package/index.d.ts +751 -0
  6. package/index.js +15 -0
  7. package/module/config.js +38 -0
  8. package/module/login.js +111 -0
  9. package/module/loginHelper.js +1296 -0
  10. package/module/options.js +37 -0
  11. package/package.json +78 -0
  12. package/src/api/action/addExternalModule.js +19 -0
  13. package/src/api/action/changeAvatar.js +137 -0
  14. package/src/api/action/changeBio.js +48 -0
  15. package/src/api/action/enableAutoSaveAppState.js +72 -0
  16. package/src/api/action/getCurrentUserID.js +11 -0
  17. package/src/api/action/handleFriendRequest.js +33 -0
  18. package/src/api/action/logout.js +76 -0
  19. package/src/api/action/refreshFb_dtsg.js +62 -0
  20. package/src/api/action/setPostReaction.js +106 -0
  21. package/src/api/action/story.js +118 -0
  22. package/src/api/action/unfriend.js +30 -0
  23. package/src/api/http/httpGet.js +28 -0
  24. package/src/api/http/httpPost.js +32 -0
  25. package/src/api/http/postFormData.js +23 -0
  26. package/src/api/messaging/J +1 -0
  27. package/src/api/messaging/addUserToGroup.js +70 -0
  28. package/src/api/messaging/changeAdminStatus.js +72 -0
  29. package/src/api/messaging/changeArchivedStatus.js +31 -0
  30. package/src/api/messaging/changeBlockedStatus.js +27 -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 +44 -0
  34. package/src/api/messaging/changeThreadEmoji.js +111 -0
  35. package/src/api/messaging/createNewGroup.js +50 -0
  36. package/src/api/messaging/createPoll.js +52 -0
  37. package/src/api/messaging/createThemeAI.js +98 -0
  38. package/src/api/messaging/deleteMessage.js +73 -0
  39. package/src/api/messaging/deleteThread.js +29 -0
  40. package/src/api/messaging/editMessage.js +67 -0
  41. package/src/api/messaging/forwardAttachment.js +55 -0
  42. package/src/api/messaging/forwardMessage.js +73 -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/groupActions.js +119 -0
  48. package/src/api/messaging/handleMessageRequest.js +31 -0
  49. package/src/api/messaging/markAsDelivered.js +31 -0
  50. package/src/api/messaging/markAsRead.js +88 -0
  51. package/src/api/messaging/markAsReadAll.js +28 -0
  52. package/src/api/messaging/markAsSeen.js +30 -0
  53. package/src/api/messaging/muteThread.js +27 -0
  54. package/src/api/messaging/notes.js +101 -0
  55. package/src/api/messaging/removeUserFromGroup.js +51 -0
  56. package/src/api/messaging/resolvePhotoUrl.js +29 -0
  57. package/src/api/messaging/scheduler.js +100 -0
  58. package/src/api/messaging/searchForThread.js +32 -0
  59. package/src/api/messaging/sendMessage.js +270 -0
  60. package/src/api/messaging/sendTypingIndicator.js +62 -0
  61. package/src/api/messaging/setMessageReaction.js +91 -0
  62. package/src/api/messaging/setTitle.js +86 -0
  63. package/src/api/messaging/shareContact.js +47 -0
  64. package/src/api/messaging/threadColors.js +128 -0
  65. package/src/api/messaging/unsendMessage.js +73 -0
  66. package/src/api/messaging/uploadAttachment.js +492 -0
  67. package/src/api/socket/core/connectMqtt.js +259 -0
  68. package/src/api/socket/core/emitAuth.js +79 -0
  69. package/src/api/socket/core/getSeqID.js +170 -0
  70. package/src/api/socket/core/getTaskResponseData.js +27 -0
  71. package/src/api/socket/core/parseDelta.js +377 -0
  72. package/src/api/socket/detail/buildStream.js +215 -0
  73. package/src/api/socket/detail/constants.js +29 -0
  74. package/src/api/socket/listenMqtt.js +377 -0
  75. package/src/api/socket/middleware/index.js +80 -0
  76. package/src/api/threads/getThreadHistory.js +664 -0
  77. package/src/api/threads/getThreadInfo.js +296 -0
  78. package/src/api/threads/getThreadList.js +293 -0
  79. package/src/api/threads/getThreadPictures.js +43 -0
  80. package/src/api/user/J +1 -0
  81. package/src/api/user/getUserID.js +48 -0
  82. package/src/api/user/getUserInfo.js +402 -0
  83. package/src/api/user/getUserInfoV2.js +134 -0
  84. package/src/core/sendReqMqtt.js +69 -0
  85. package/src/database/helpers.js +36 -0
  86. package/src/database/models/index.js +55 -0
  87. package/src/database/models/thread.js +44 -0
  88. package/src/database/models/user.js +39 -0
  89. package/src/database/threadData.js +92 -0
  90. package/src/database/userData.js +88 -0
  91. package/src/remote/remoteClient.js +71 -0
  92. package/src/utils/broadcast.js +62 -0
  93. package/src/utils/client.js +10 -0
  94. package/src/utils/constants.js +53 -0
  95. package/src/utils/cookies.js +73 -0
  96. package/src/utils/format/attachment.js +357 -0
  97. package/src/utils/format/cookie.js +9 -0
  98. package/src/utils/format/date.js +50 -0
  99. package/src/utils/format/decode.js +44 -0
  100. package/src/utils/format/delta.js +194 -0
  101. package/src/utils/format/ids.js +64 -0
  102. package/src/utils/format/index.js +64 -0
  103. package/src/utils/format/message.js +88 -0
  104. package/src/utils/format/presence.js +132 -0
  105. package/src/utils/format/readTyp.js +44 -0
  106. package/src/utils/format/thread.js +42 -0
  107. package/src/utils/format/utils.js +141 -0
  108. package/src/utils/headers.js +96 -0
  109. package/src/utils/loginParser/autoLogin.js +125 -0
  110. package/src/utils/loginParser/helpers.js +43 -0
  111. package/src/utils/loginParser/index.js +10 -0
  112. package/src/utils/loginParser/parseAndCheckLogin.js +220 -0
  113. package/src/utils/loginParser/textUtils.js +28 -0
  114. package/src/utils/request/H +1 -0
  115. package/src/utils/request/client.js +33 -0
  116. package/src/utils/request/config.js +25 -0
  117. package/src/utils/request/defaults.js +40 -0
  118. package/src/utils/request/helpers.js +31 -0
  119. package/src/utils/request/index.js +12 -0
  120. package/src/utils/request/methods.js +92 -0
  121. package/src/utils/request/proxy.js +23 -0
  122. package/src/utils/request/retry.js +87 -0
  123. package/src/utils/request/sanitize.js +41 -0
  124. package/src/utils/sessionKeeper.js +275 -0
@@ -0,0 +1,44 @@
1
+ // ============================================================
2
+ // AYMAN-FCA v2.0 — Thread Model
3
+ // © 2025 Ayman. All Rights Reserved.
4
+ // ============================================================
5
+ "use strict";
6
+
7
+ module.exports = function(sequelize) {
8
+ const { Model, DataTypes } = require("sequelize");
9
+
10
+ class Thread extends Model {}
11
+
12
+ Thread.init({
13
+ num: {
14
+ type: DataTypes.INTEGER,
15
+ allowNull: false,
16
+ autoIncrement: true,
17
+ primaryKey: true
18
+ },
19
+ threadID: {
20
+ type: DataTypes.STRING,
21
+ allowNull: false,
22
+ unique: true
23
+ },
24
+ messageCount: {
25
+ type: DataTypes.INTEGER,
26
+ allowNull: false,
27
+ defaultValue: 0
28
+ },
29
+ data: {
30
+ type: DataTypes.TEXT,
31
+ allowNull: true,
32
+ get() {
33
+ const v = this.getDataValue("data");
34
+ if (typeof v === "string") { try { return JSON.parse(v); } catch { return v; } }
35
+ return v;
36
+ },
37
+ set(v) {
38
+ this.setDataValue("data", typeof v === "string" ? v : JSON.stringify(v));
39
+ }
40
+ }
41
+ }, { sequelize, modelName: "Thread", timestamps: true });
42
+
43
+ return Thread;
44
+ };
@@ -0,0 +1,39 @@
1
+ // ============================================================
2
+ // AYMAN-FCA v2.0 — User Model
3
+ // © 2025 Ayman. All Rights Reserved.
4
+ // ============================================================
5
+ "use strict";
6
+
7
+ module.exports = function(sequelize) {
8
+ const { Model, DataTypes } = require("sequelize");
9
+
10
+ class User extends Model {}
11
+
12
+ User.init({
13
+ num: {
14
+ type: DataTypes.INTEGER,
15
+ allowNull: false,
16
+ autoIncrement: true,
17
+ primaryKey: true
18
+ },
19
+ userID: {
20
+ type: DataTypes.STRING,
21
+ allowNull: false,
22
+ unique: true
23
+ },
24
+ data: {
25
+ type: DataTypes.TEXT,
26
+ allowNull: true,
27
+ get() {
28
+ const v = this.getDataValue("data");
29
+ if (typeof v === "string") { try { return JSON.parse(v); } catch { return v; } }
30
+ return v;
31
+ },
32
+ set(v) {
33
+ this.setDataValue("data", typeof v === "string" ? v : JSON.stringify(v));
34
+ }
35
+ }
36
+ }, { sequelize, modelName: "User", timestamps: true });
37
+
38
+ return User;
39
+ };
@@ -0,0 +1,92 @@
1
+ // ============================================================
2
+ // AYMAN-FCA v2.0 — Thread Data
3
+ // © 2025 Ayman. All Rights Reserved.
4
+ // ============================================================
5
+ "use strict";
6
+
7
+ const models = require("./models");
8
+ const { DB_NOT_INIT, validateId, validateData, normalizeAttributes, wrapError } = require("./helpers");
9
+
10
+ const Thread = models.Thread;
11
+ const ID_FIELD = "threadID";
12
+
13
+ module.exports = function(bot) {
14
+ return {
15
+ async create(threadID, data) {
16
+ if (!Thread) return { thread: { threadID: validateId(threadID, ID_FIELD), ...(data || {}) }, created: true };
17
+ try {
18
+ threadID = validateId(threadID, ID_FIELD);
19
+ let thread = await Thread.findOne({ where: { threadID } });
20
+ if (thread) return { thread: thread.get(), created: false };
21
+ thread = await Thread.create({ threadID, ...(data || {}) });
22
+ return { thread: thread.get(), created: true };
23
+ } catch (err) { throw wrapError("Failed to create thread", err); }
24
+ },
25
+
26
+ async get(threadID) {
27
+ if (!Thread) return null;
28
+ try {
29
+ threadID = validateId(threadID, ID_FIELD);
30
+ const thread = await Thread.findOne({ where: { threadID } });
31
+ return thread ? thread.get() : null;
32
+ } catch (err) { throw wrapError("Failed to get thread", err); }
33
+ },
34
+
35
+ async update(threadID, data) {
36
+ if (!Thread) return { thread: { threadID: validateId(threadID, ID_FIELD), ...(data || {}) }, created: false };
37
+ try {
38
+ threadID = validateId(threadID, ID_FIELD);
39
+ validateData(data);
40
+ const thread = await Thread.findOne({ where: { threadID } });
41
+ if (thread) { await thread.update(data); return { thread: thread.get(), created: false }; }
42
+ const newT = await Thread.create({ ...data, threadID });
43
+ return { thread: newT.get(), created: true };
44
+ } catch (err) { throw wrapError("Failed to update thread", err); }
45
+ },
46
+
47
+ async del(threadID) {
48
+ if (!Thread) throw new Error(DB_NOT_INIT);
49
+ try {
50
+ threadID = validateId(threadID, ID_FIELD);
51
+ const result = await Thread.destroy({ where: { threadID } });
52
+ if (result === 0) throw new Error("No thread found with the specified threadID");
53
+ return result;
54
+ } catch (err) { throw wrapError("Failed to delete thread", err); }
55
+ },
56
+
57
+ async delAll() {
58
+ if (!Thread) return 0;
59
+ try { return await Thread.destroy({ where: {} }); }
60
+ catch (err) { throw wrapError("Failed to delete all threads", err); }
61
+ },
62
+
63
+ async getAll(options = {}) {
64
+ if (!Thread) return [];
65
+ try {
66
+ const query = {};
67
+ if (options.attributes) query.attributes = normalizeAttributes(options.attributes);
68
+ if (options.limit) query.limit = options.limit;
69
+ if (options.offset) query.offset = options.offset;
70
+ const threads = await Thread.findAll(query);
71
+ return threads.map(t => t.get());
72
+ } catch (err) { throw wrapError("Failed to get all threads", err); }
73
+ },
74
+
75
+ async count() {
76
+ if (!Thread) return 0;
77
+ try { return await Thread.count(); }
78
+ catch (err) { throw wrapError("Failed to count threads", err); }
79
+ },
80
+
81
+ async incrementMessageCount(threadID, amount = 1) {
82
+ if (!Thread) return null;
83
+ try {
84
+ threadID = validateId(threadID, ID_FIELD);
85
+ const thread = await Thread.findOne({ where: { threadID } });
86
+ if (!thread) return null;
87
+ await thread.increment("messageCount", { by: amount });
88
+ return thread.get();
89
+ } catch (err) { throw wrapError("Failed to increment message count", err); }
90
+ }
91
+ };
92
+ };
@@ -0,0 +1,88 @@
1
+ // ============================================================
2
+ // AYMAN-FCA v2.0 — User Data
3
+ // © 2025 Ayman. All Rights Reserved.
4
+ // ============================================================
5
+ "use strict";
6
+
7
+ const models = require("./models");
8
+ const { DB_NOT_INIT, validateId, validateData, normalizeAttributes, normalizePayload, wrapError } = require("./helpers");
9
+
10
+ const User = models.User;
11
+ const ID_FIELD = "userID";
12
+
13
+ function stub(userID, data) {
14
+ return { user: { userID, ...normalizePayload(data || {}, "data") }, created: true };
15
+ }
16
+
17
+ module.exports = function(bot) {
18
+ return {
19
+ async create(userID, data) {
20
+ if (!User) return stub(validateId(userID, ID_FIELD), data);
21
+ try {
22
+ userID = validateId(userID, ID_FIELD);
23
+ validateData(data);
24
+ const payload = normalizePayload(data, "data");
25
+ let user = await User.findOne({ where: { userID } });
26
+ if (user) return { user: user.get(), created: false };
27
+ user = await User.create({ userID, ...payload });
28
+ return { user: user.get(), created: true };
29
+ } catch (err) { throw wrapError("Failed to create user", err); }
30
+ },
31
+
32
+ async get(userID) {
33
+ if (!User) return null;
34
+ try {
35
+ userID = validateId(userID, ID_FIELD);
36
+ const user = await User.findOne({ where: { userID } });
37
+ return user ? user.get() : null;
38
+ } catch (err) { throw wrapError("Failed to get user", err); }
39
+ },
40
+
41
+ async update(userID, data) {
42
+ if (!User) return { user: { userID: validateId(userID, ID_FIELD), ...normalizePayload(data || {}, "data") }, created: false };
43
+ try {
44
+ userID = validateId(userID, ID_FIELD);
45
+ validateData(data);
46
+ const payload = normalizePayload(data, "data");
47
+ const user = await User.findOne({ where: { userID } });
48
+ if (user) { await user.update(payload); return { user: user.get(), created: false }; }
49
+ const newU = await User.create({ userID, ...payload });
50
+ return { user: newU.get(), created: true };
51
+ } catch (err) { throw wrapError("Failed to update user", err); }
52
+ },
53
+
54
+ async del(userID) {
55
+ if (!User) throw new Error(DB_NOT_INIT);
56
+ try {
57
+ userID = validateId(userID, ID_FIELD);
58
+ const result = await User.destroy({ where: { userID } });
59
+ if (result === 0) throw new Error("No user found with the specified userID");
60
+ return result;
61
+ } catch (err) { throw wrapError("Failed to delete user", err); }
62
+ },
63
+
64
+ async delAll() {
65
+ if (!User) return 0;
66
+ try { return await User.destroy({ where: {} }); }
67
+ catch (err) { throw wrapError("Failed to delete all users", err); }
68
+ },
69
+
70
+ async getAll(options = {}) {
71
+ if (!User) return [];
72
+ try {
73
+ const query = {};
74
+ if (options.attributes) query.attributes = normalizeAttributes(options.attributes);
75
+ if (options.limit) query.limit = options.limit;
76
+ if (options.offset) query.offset = options.offset;
77
+ const users = await User.findAll(query);
78
+ return users.map(u => u.get());
79
+ } catch (err) { throw wrapError("Failed to get all users", err); }
80
+ },
81
+
82
+ async count() {
83
+ if (!User) return 0;
84
+ try { return await User.count(); }
85
+ catch (err) { throw wrapError("Failed to count users", err); }
86
+ }
87
+ };
88
+ };
@@ -0,0 +1,71 @@
1
+ // ============================================================
2
+ // AYMAN-FCA v2.0 — Remote Client (معطل افتراضياً)
3
+ // © 2025 Ayman. All Rights Reserved.
4
+ // ============================================================
5
+ "use strict";
6
+
7
+ const WebSocket = require("ws");
8
+ const logger = require("../../func/logger");
9
+
10
+ function createRemoteClient(api, ctx, cfg) {
11
+ if (!cfg || !cfg.enabled || !cfg.url) return null;
12
+
13
+ const url = String(cfg.url);
14
+ const token = cfg.token ? String(cfg.token) : null;
15
+ const autoReconnect= cfg.autoReconnect !== false;
16
+ const emitter = ctx?._emitter;
17
+
18
+ let ws = null;
19
+ let closed = false;
20
+ let reconnectTimer = null;
21
+
22
+ const log = (msg, level = "info") => logger(`[remote] ${msg}`, level);
23
+
24
+ function safeEmit(event, payload) {
25
+ try { if (emitter?.emit) emitter.emit(event, payload); } catch (_) {}
26
+ }
27
+
28
+ function scheduleReconnect() {
29
+ if (!autoReconnect || closed || reconnectTimer) return;
30
+ reconnectTimer = setTimeout(() => { reconnectTimer = null; if (!closed) connect(); }, 5000);
31
+ }
32
+
33
+ function connect() {
34
+ try {
35
+ ws = new WebSocket(url, { headers: token ? { Authorization: `Bearer ${token}` } : undefined });
36
+ } catch (e) {
37
+ log(`connect error: ${e?.message || e}`, "warn");
38
+ scheduleReconnect(); return;
39
+ }
40
+
41
+ ws.on("open", () => {
42
+ log("متصل ✅");
43
+ try { ws.send(JSON.stringify({ type: "hello", userID: ctx?.userID, region: ctx?.region })); } catch (_) {}
44
+ safeEmit("remote:connected", {});
45
+ });
46
+
47
+ ws.on("message", data => {
48
+ try {
49
+ const msg = JSON.parse(data.toString());
50
+ safeEmit("remote:message", msg);
51
+ if (msg.type === "api" && msg.method && typeof api[msg.method] === "function") {
52
+ try { api[msg.method](...(msg.args || [])); } catch (e) {
53
+ log(`api call error: ${e?.message}`, "warn");
54
+ }
55
+ }
56
+ } catch (_) {}
57
+ });
58
+
59
+ ws.on("error", e => { log(`error: ${e?.message || e}`, "warn"); });
60
+ ws.on("close", () => { log("انقطع الاتصال", "warn"); safeEmit("remote:disconnected", {}); scheduleReconnect(); });
61
+ }
62
+
63
+ connect();
64
+
65
+ return {
66
+ send: (data) => { try { if (ws?.readyState === 1) ws.send(JSON.stringify(data)); } catch (_) {} },
67
+ close: () => { closed = true; if (reconnectTimer) clearTimeout(reconnectTimer); try { ws?.close(); } catch (_) {} }
68
+ };
69
+ }
70
+
71
+ module.exports = { createRemoteClient };
@@ -0,0 +1,62 @@
1
+ // ============================================================
2
+ // AYMAN-FCA v2.0 — Smart Broadcast
3
+ // © 2025 Ayman. All Rights Reserved.
4
+ //
5
+ // إرسال رسالة لقائمة threads مع:
6
+ // • Rate limiting ذكي
7
+ // • Retry تلقائي لكل thread
8
+ // • تقرير نتائج مفصل
9
+ //
10
+ // api.broadcast(threadIDs, message, options?)
11
+ // ============================================================
12
+ "use strict";
13
+
14
+ const logger = require("../../func/logger");
15
+ const delay = ms => new Promise(r => setTimeout(r, ms));
16
+
17
+ async function broadcast(api, threadIDs, message, options = {}) {
18
+ const {
19
+ delayMs = 1200,
20
+ retries = 2,
21
+ onResult = null
22
+ } = options;
23
+
24
+ if (!api?.sendMessage) throw new Error("AYMAN-FCA: api.sendMessage مطلوب");
25
+
26
+ const ids = Array.isArray(threadIDs) ? threadIDs : [threadIDs];
27
+ const results = [];
28
+ let sent = 0, failed = 0;
29
+
30
+ for (const id of ids) {
31
+ let ok = false, lastErr;
32
+
33
+ for (let attempt = 0; attempt <= retries; attempt++) {
34
+ try {
35
+ const res = await api.sendMessage(message, id);
36
+ results.push({ threadID: id, ok: true, res });
37
+ if (onResult) onResult(null, { threadID: id, ok: true });
38
+ ok = true;
39
+ sent++;
40
+ break;
41
+ } catch (e) {
42
+ lastErr = e;
43
+ if (attempt < retries) await delay(1500);
44
+ }
45
+ }
46
+
47
+ if (!ok) {
48
+ const errMsg = lastErr?.error || lastErr?.message || String(lastErr);
49
+ logger(`[ AYMAN ] broadcast فشل لـ ${id}: ${errMsg}`, "warn");
50
+ results.push({ threadID: id, ok: false, error: lastErr });
51
+ if (onResult) onResult(lastErr, { threadID: id, ok: false });
52
+ failed++;
53
+ }
54
+
55
+ if (delayMs > 0) await delay(delayMs);
56
+ }
57
+
58
+ logger(`[ AYMAN ] broadcast: ${sent} نجح، ${failed} فشل`, "info");
59
+ return { results, sent, failed, total: ids.length };
60
+ }
61
+
62
+ module.exports = broadcast;
@@ -0,0 +1,10 @@
1
+ // ============================================================
2
+ // AYMAN-FCA v2.0 — Utils Client
3
+ // © 2025 Ayman. All Rights Reserved.
4
+ // ============================================================
5
+ "use strict";
6
+
7
+ const { saveCookies, getAppState } = require("./cookies");
8
+ const { parseAndCheckLogin } = require("./loginParser");
9
+
10
+ module.exports = { saveCookies, getAppState, parseAndCheckLogin };
@@ -0,0 +1,53 @@
1
+ // ============================================================
2
+ // AYMAN-FCA v2.0 — Constants & Utilities
3
+ // © 2025 Ayman. All Rights Reserved.
4
+ // ============================================================
5
+ "use strict";
6
+
7
+ const { getType } = require("./format");
8
+ const stream = require("stream");
9
+
10
+ // ✅ استخراج نص من HTML بكفاءة
11
+ function getFrom(html, a, b) {
12
+ if (!html || !a) return undefined;
13
+ const i = html.indexOf(a);
14
+ if (i < 0) return undefined;
15
+ const start = i + a.length;
16
+ const j = html.indexOf(b, start);
17
+ return j < 0 ? undefined : html.slice(start, j);
18
+ }
19
+
20
+ // ✅ فحص readable stream
21
+ function isReadableStream(obj) {
22
+ return (
23
+ obj instanceof stream.Stream &&
24
+ (getType(obj._read) === "Function" || getType(obj._read) === "AsyncFunction") &&
25
+ getType(obj._readableState) === "Object"
26
+ );
27
+ }
28
+
29
+ // ✅ توليد OfflineThreadingID فريد
30
+ function generateOfflineThreadingID() {
31
+ const ret = [];
32
+ const now = Date.now();
33
+ const str = ("" + now).split("");
34
+ for (let i = 0; i < str.length; i++) ret.push(str[i]);
35
+ ret.push("0".repeat(Math.max(0, 16 - str.length)));
36
+ const val = BigInt(ret.join("")) + BigInt(Math.floor(Math.random() * 4294967295));
37
+ return val.toString();
38
+ }
39
+
40
+ // ✅ UUID v4
41
+ function getGUID() {
42
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, c => {
43
+ const r = Math.random() * 16 | 0;
44
+ return (c === "x" ? r : (r & 0x3 | 0x8)).toString(16);
45
+ });
46
+ }
47
+
48
+ module.exports = {
49
+ getFrom,
50
+ isReadableStream,
51
+ generateOfflineThreadingID,
52
+ getGUID
53
+ };
@@ -0,0 +1,73 @@
1
+ // ============================================================
2
+ // AYMAN-FCA v2.0 — Cookies Helper
3
+ // © 2025 Ayman. All Rights Reserved.
4
+ // تحسين: حفظ cookies من www + m + messenger
5
+ // ============================================================
6
+ "use strict";
7
+
8
+ // ✅ حفظ cookies من كل response — يجدد الجلسة تلقائياً
9
+ function saveCookies(jar) {
10
+ return res => {
11
+ try {
12
+ const setCookie = res?.headers?.["set-cookie"];
13
+ if (!Array.isArray(setCookie) || !setCookie.length) return res;
14
+
15
+ const url =
16
+ res?.request?.res?.responseUrl ||
17
+ (res?.config?.baseURL
18
+ ? new URL(res.config.url || "/", res.config.baseURL).toString()
19
+ : res?.config?.url || "https://www.facebook.com");
20
+
21
+ for (const c of setCookie) {
22
+ // ✅ احفظ في www و m و messenger
23
+ for (const domain of [url, "https://www.facebook.com", "https://m.facebook.com"]) {
24
+ try { jar.setCookieSync(c, domain); } catch (_) {}
25
+ }
26
+ }
27
+ } catch (_) {}
28
+ return res;
29
+ };
30
+ }
31
+
32
+ // ✅ جلب AppState من كل المصادر
33
+ function getAppState(jar) {
34
+ if (!jar || typeof jar.getCookiesSync !== "function") return [];
35
+
36
+ const urls = [
37
+ "https://www.facebook.com",
38
+ "https://m.facebook.com",
39
+ "https://www.messenger.com"
40
+ ];
41
+
42
+ const seen = new Set();
43
+ const out = [];
44
+
45
+ for (const u of urls) {
46
+ let cookies = [];
47
+ try { cookies = jar.getCookiesSync(u) || []; } catch (_) { continue; }
48
+
49
+ for (const c of cookies) {
50
+ const key = c.key || c.name;
51
+ if (!key) continue;
52
+ const id = `${key}|${c.domain || ""}|${c.path || "/"}`;
53
+ if (seen.has(id)) continue;
54
+ seen.add(id);
55
+ out.push({
56
+ key,
57
+ value: c.value,
58
+ domain: c.domain || ".facebook.com",
59
+ path: c.path || "/",
60
+ hostOnly: !!c.hostOnly,
61
+ creation: c.creation || new Date(),
62
+ lastAccessed:c.lastAccessed || new Date(),
63
+ secure: !!c.secure,
64
+ httpOnly: !!c.httpOnly,
65
+ expires: c.expires && c.expires !== "Infinity" ? c.expires : "Infinity"
66
+ });
67
+ }
68
+ }
69
+
70
+ return out;
71
+ }
72
+
73
+ module.exports = { saveCookies, getAppState };