@eryxenx/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.
- package/CHANGELOG.md +325 -0
- package/DOCS.md +2712 -0
- package/README.md +455 -0
- package/func/checkUpdate.js +7 -0
- package/func/logAdapter.js +33 -0
- package/func/logger.js +48 -0
- package/index.d.ts +751 -0
- package/index.js +22 -0
- package/module/config.js +40 -0
- package/module/login.js +133 -0
- package/module/loginHelper.js +1365 -0
- package/module/options.js +44 -0
- package/package.json +98 -0
- package/src/api/action/addExternalModule.js +25 -0
- package/src/api/action/changeAvatar.js +137 -0
- package/src/api/action/changeBio.js +75 -0
- package/src/api/action/enableAutoSaveAppState.js +73 -0
- package/src/api/action/getCurrentUserID.js +7 -0
- package/src/api/action/handleFriendRequest.js +57 -0
- package/src/api/action/logout.js +76 -0
- package/src/api/action/refreshFb_dtsg.js +48 -0
- package/src/api/action/setPostReaction.js +106 -0
- package/src/api/action/unfriend.js +54 -0
- package/src/api/http/httpGet.js +46 -0
- package/src/api/http/httpPost.js +52 -0
- package/src/api/http/postFormData.js +47 -0
- package/src/api/messaging/addUserToGroup.js +68 -0
- package/src/api/messaging/changeAdminStatus.js +126 -0
- package/src/api/messaging/changeArchivedStatus.js +55 -0
- package/src/api/messaging/changeBlockedStatus.js +48 -0
- package/src/api/messaging/changeGroupImage.js +91 -0
- package/src/api/messaging/changeNickname.js +70 -0
- package/src/api/messaging/changeThreadColor.js +79 -0
- package/src/api/messaging/changeThreadEmoji.js +111 -0
- package/src/api/messaging/createNewGroup.js +88 -0
- package/src/api/messaging/createPoll.js +46 -0
- package/src/api/messaging/createThemeAI.js +98 -0
- package/src/api/messaging/deleteMessage.js +136 -0
- package/src/api/messaging/deleteThread.js +56 -0
- package/src/api/messaging/editMessage.js +105 -0
- package/src/api/messaging/forwardAttachment.js +57 -0
- package/src/api/messaging/forwardMessage.js +134 -0
- package/src/api/messaging/getEmojiUrl.js +29 -0
- package/src/api/messaging/getFriendsList.js +82 -0
- package/src/api/messaging/getMessage.js +829 -0
- package/src/api/messaging/getThemePictures.js +62 -0
- package/src/api/messaging/handleMessageRequest.js +65 -0
- package/src/api/messaging/markAsDelivered.js +57 -0
- package/src/api/messaging/markAsRead.js +88 -0
- package/src/api/messaging/markAsReadAll.js +56 -0
- package/src/api/messaging/markAsSeen.js +68 -0
- package/src/api/messaging/muteThread.js +50 -0
- package/src/api/messaging/pinMessage.js +115 -0
- package/src/api/messaging/removeUserFromGroup.js +62 -0
- package/src/api/messaging/resolvePhotoUrl.js +43 -0
- package/src/api/messaging/scheduler.js +264 -0
- package/src/api/messaging/searchForThread.js +53 -0
- package/src/api/messaging/sendBroadcast.js +93 -0
- package/src/api/messaging/sendMessage.js +269 -0
- package/src/api/messaging/sendTypingIndicator.js +90 -0
- package/src/api/messaging/sessionGuard.js +130 -0
- package/src/api/messaging/setMessageReaction.js +109 -0
- package/src/api/messaging/setTitle.js +124 -0
- package/src/api/messaging/shareContact.js +98 -0
- package/src/api/messaging/threadColors.js +128 -0
- package/src/api/messaging/unsendMessage.js +105 -0
- package/src/api/messaging/uploadAttachment.js +492 -0
- package/src/api/socket/OldMessage.js +186 -0
- package/src/api/socket/core/connectMqtt.js +269 -0
- package/src/api/socket/core/emitAuth.js +103 -0
- package/src/api/socket/core/getSeqID.js +321 -0
- package/src/api/socket/core/getTaskResponseData.js +25 -0
- package/src/api/socket/core/parseDelta.js +387 -0
- package/src/api/socket/detail/buildStream.js +215 -0
- package/src/api/socket/detail/constants.js +28 -0
- package/src/api/socket/e2ee/crypto.js +173 -0
- package/src/api/socket/e2ee/index.js +925 -0
- package/src/api/socket/e2ee/localMediaServer.js +59 -0
- package/src/api/socket/e2ee/mediaDecode.js +155 -0
- package/src/api/socket/e2ee/native/NOTICE.md +29 -0
- package/src/api/socket/e2ee/native/build/messagix.dll +0 -0
- package/src/api/socket/e2ee/native/build/messagix.so +0 -0
- package/src/api/socket/e2ee/native/lib/index.mjs +1426 -0
- package/src/api/socket/e2ee/native/nativeMediaBridge.js +233 -0
- package/src/api/socket/e2ee/proto/ArmadilloApplication.proto +281 -0
- package/src/api/socket/e2ee/proto/ArmadilloICDC.proto +14 -0
- package/src/api/socket/e2ee/proto/ConsumerApplication.proto +232 -0
- package/src/api/socket/e2ee/proto/MessageApplication.proto +82 -0
- package/src/api/socket/e2ee/proto/MessageTransport.proto +77 -0
- package/src/api/socket/e2ee/proto/WACommon.proto +66 -0
- package/src/api/socket/e2ee/proto/WAMediaTransport.proto +176 -0
- package/src/api/socket/e2ee/proto/proto-writer.ts +76 -0
- package/src/api/socket/e2ee/protocol.js +196 -0
- package/src/api/socket/e2ee/ratchet.js +219 -0
- package/src/api/socket/e2ee/store.js +182 -0
- package/src/api/socket/e2ee/vendor/fme/dist/index.cjs +6477 -0
- package/src/api/socket/e2ee/vendor/fme/proto/ArmadilloApplication.proto +281 -0
- package/src/api/socket/e2ee/vendor/fme/proto/ArmadilloICDC.proto +14 -0
- package/src/api/socket/e2ee/vendor/fme/proto/ConsumerApplication.proto +232 -0
- package/src/api/socket/e2ee/vendor/fme/proto/MessageApplication.proto +82 -0
- package/src/api/socket/e2ee/vendor/fme/proto/MessageTransport.proto +77 -0
- package/src/api/socket/e2ee/vendor/fme/proto/WACommon.proto +66 -0
- package/src/api/socket/e2ee/vendor/fme/proto/WAMediaTransport.proto +176 -0
- package/src/api/socket/listenE2EE.js +75 -0
- package/src/api/socket/listenMqtt.js +436 -0
- package/src/api/socket/middleware/index.js +216 -0
- package/src/api/socket/sendMessage.js +314 -0
- package/src/api/socket/sendMessageMqtt.js +69 -0
- package/src/api/threads/getThreadHistory.js +664 -0
- package/src/api/threads/getThreadInfo.js +329 -0
- package/src/api/threads/getThreadList.js +293 -0
- package/src/api/threads/getThreadPictures.js +78 -0
- package/src/api/users/getUserID.js +65 -0
- package/src/api/users/getUserInfo.js +402 -0
- package/src/api/users/getUserInfoV2.js +134 -0
- package/src/app/MessengerBot.js +209 -0
- package/src/app/MessengerContext.js +32 -0
- package/src/app/createFcaClient.js +136 -0
- package/src/app/threadInfoRealtimeSync.js +284 -0
- package/src/core/sendReqMqtt.js +96 -0
- package/src/database/helpers.js +53 -0
- package/src/database/models/index.js +88 -0
- package/src/database/models/thread.js +50 -0
- package/src/database/models/user.js +46 -0
- package/src/database/threadData.js +94 -0
- package/src/database/userData.js +98 -0
- package/src/remote/remoteClient.js +123 -0
- package/src/utils/broadcast.js +51 -0
- package/src/utils/client.js +10 -0
- package/src/utils/constants.js +23 -0
- package/src/utils/cookies.js +68 -0
- package/src/utils/format/attachment.js +357 -0
- package/src/utils/format/cookie.js +9 -0
- package/src/utils/format/date.js +50 -0
- package/src/utils/format/decode.js +44 -0
- package/src/utils/format/delta.js +194 -0
- package/src/utils/format/ids.js +64 -0
- package/src/utils/format/index.js +64 -0
- package/src/utils/format/message.js +88 -0
- package/src/utils/format/presence.js +132 -0
- package/src/utils/format/readTyp.js +44 -0
- package/src/utils/format/thread.js +42 -0
- package/src/utils/format/utils.js +141 -0
- package/src/utils/headers.js +128 -0
- package/src/utils/loginParser/autoLogin.js +125 -0
- package/src/utils/loginParser/helpers.js +43 -0
- package/src/utils/loginParser/index.js +10 -0
- package/src/utils/loginParser/parseAndCheckLogin.js +220 -0
- package/src/utils/loginParser/textUtils.js +28 -0
- package/src/utils/nexca-logger.js +144 -0
- package/src/utils/nexca-utils.js +686 -0
- package/src/utils/request/client.js +26 -0
- package/src/utils/request/config.js +23 -0
- package/src/utils/request/defaults.js +46 -0
- package/src/utils/request/helpers.js +46 -0
- package/src/utils/request/index.js +17 -0
- package/src/utils/request/methods.js +163 -0
- package/src/utils/request/proxy.js +21 -0
- package/src/utils/request/retry.js +77 -0
- package/src/utils/request/sanitize.js +49 -0
- package/src/utils/versionCheck.js +47 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const http = require("http");
|
|
4
|
+
const crypto = require("crypto");
|
|
5
|
+
|
|
6
|
+
let _server = null;
|
|
7
|
+
let _port = 0;
|
|
8
|
+
const _cache = new Map(); // token -> { buffer, mimeType, expiresAt }
|
|
9
|
+
|
|
10
|
+
const TTL_MS = 15 * 60 * 1000; // 15 min is plenty for a command to fetch it
|
|
11
|
+
|
|
12
|
+
function _cleanup() {
|
|
13
|
+
const now = Date.now();
|
|
14
|
+
for (const [token, entry] of _cache) {
|
|
15
|
+
if (entry.expiresAt < now) _cache.delete(token);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function ensureServer() {
|
|
20
|
+
if (_server) return Promise.resolve(_port);
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
_server = http.createServer((req, res) => {
|
|
23
|
+
const token = (req.url || "").replace(/^\/+/, "").split("?")[0];
|
|
24
|
+
const entry = _cache.get(token);
|
|
25
|
+
if (!entry) {
|
|
26
|
+
res.writeHead(404);
|
|
27
|
+
res.end("not found");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
res.writeHead(200, {
|
|
31
|
+
"Content-Type": entry.mimeType || "application/octet-stream",
|
|
32
|
+
"Content-Length": entry.buffer.length
|
|
33
|
+
});
|
|
34
|
+
res.end(entry.buffer);
|
|
35
|
+
});
|
|
36
|
+
_server.on("error", reject);
|
|
37
|
+
// 127.0.0.1 only — never expose this outside the container
|
|
38
|
+
_server.listen(0, "127.0.0.1", () => {
|
|
39
|
+
_port = _server.address().port;
|
|
40
|
+
setInterval(_cleanup, 60 * 1000).unref();
|
|
41
|
+
resolve(_port);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Stores a decrypted media buffer and returns a short-lived local URL for it.
|
|
48
|
+
* @param {Buffer} buffer
|
|
49
|
+
* @param {string} mimeType
|
|
50
|
+
* @returns {Promise<string>} e.g. http://127.0.0.1:53211/ab12cd34
|
|
51
|
+
*/
|
|
52
|
+
async function serveBuffer(buffer, mimeType) {
|
|
53
|
+
const port = await ensureServer();
|
|
54
|
+
const token = crypto.randomBytes(12).toString("hex");
|
|
55
|
+
_cache.set(token, { buffer, mimeType, expiresAt: Date.now() + TTL_MS });
|
|
56
|
+
return `http://127.0.0.1:${port}/${token}`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = { serveBuffer, getCacheSize: () => _cache.size };
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// Generic protobuf wire-format field reader (varint / length-delimited /
|
|
4
|
+
// fixed32 / fixed64). Returns { fieldNumber: [values...] }.
|
|
5
|
+
function readVarint(buf, offset) {
|
|
6
|
+
let result = 0n, shift = 0n, b;
|
|
7
|
+
do {
|
|
8
|
+
b = buf[offset++];
|
|
9
|
+
result |= BigInt(b & 0x7f) << shift;
|
|
10
|
+
shift += 7n;
|
|
11
|
+
} while (b & 0x80);
|
|
12
|
+
return [result, offset];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function decodeFields(buf) {
|
|
16
|
+
const fields = {};
|
|
17
|
+
let offset = 0;
|
|
18
|
+
while (offset < buf.length) {
|
|
19
|
+
let tag;
|
|
20
|
+
try {
|
|
21
|
+
[tag, offset] = readVarint(buf, offset);
|
|
22
|
+
} catch (_) { break; }
|
|
23
|
+
const fieldNum = Number(tag >> 3n);
|
|
24
|
+
const wireType = Number(tag & 7n);
|
|
25
|
+
let value;
|
|
26
|
+
if (wireType === 0) {
|
|
27
|
+
[value, offset] = readVarint(buf, offset);
|
|
28
|
+
} else if (wireType === 2) {
|
|
29
|
+
let len;
|
|
30
|
+
[len, offset] = readVarint(buf, offset);
|
|
31
|
+
len = Number(len);
|
|
32
|
+
value = buf.slice(offset, offset + len);
|
|
33
|
+
offset += len;
|
|
34
|
+
} else if (wireType === 1) {
|
|
35
|
+
value = buf.readBigUInt64LE(offset); offset += 8;
|
|
36
|
+
} else if (wireType === 5) {
|
|
37
|
+
value = buf.readUInt32LE(offset); offset += 4;
|
|
38
|
+
} else {
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
if (!fields[fieldNum]) fields[fieldNum] = [];
|
|
42
|
+
fields[fieldNum].push(value);
|
|
43
|
+
}
|
|
44
|
+
return fields;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function bytesField(fields, n) { return fields[n] ? fields[n][0] : undefined; }
|
|
48
|
+
function strField(fields, n) {
|
|
49
|
+
const b = bytesField(fields, n);
|
|
50
|
+
return b !== undefined ? Buffer.from(b).toString("utf8") : undefined;
|
|
51
|
+
}
|
|
52
|
+
function numField(fields, n) {
|
|
53
|
+
const v = fields[n] ? fields[n][0] : undefined;
|
|
54
|
+
return v !== undefined ? Number(v) : undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// WACommon.SubProtocol { bytes payload = 1; int32 version = 2; }
|
|
58
|
+
function decodeSubProtocol(buf) {
|
|
59
|
+
const f = decodeFields(buf);
|
|
60
|
+
return { payload: bytesField(f, 1), version: numField(f, 2) };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// WAMediaTransport {
|
|
64
|
+
// Integral { bytes fileSHA256=1; bytes mediaKey=2; bytes fileEncSHA256=3; string directPath=4; int64 mediaKeyTimestamp=5; }
|
|
65
|
+
// Ancillary { uint64 fileLength=1; string mimetype=2; Thumbnail thumbnail=3; string objectID=4; }
|
|
66
|
+
// Integral integral = 1; Ancillary ancillary = 2;
|
|
67
|
+
// }
|
|
68
|
+
function decodeWAMediaTransport(buf) {
|
|
69
|
+
const top = decodeFields(buf);
|
|
70
|
+
const integralBuf = bytesField(top, 1);
|
|
71
|
+
const ancillaryBuf = bytesField(top, 2);
|
|
72
|
+
const integral = integralBuf ? decodeFields(integralBuf) : {};
|
|
73
|
+
const ancillary = ancillaryBuf ? decodeFields(ancillaryBuf) : {};
|
|
74
|
+
return {
|
|
75
|
+
fileSHA256: bytesField(integral, 1),
|
|
76
|
+
mediaKey: bytesField(integral, 2),
|
|
77
|
+
fileEncSHA256: bytesField(integral, 3),
|
|
78
|
+
directPath: strField(integral, 4),
|
|
79
|
+
mediaKeyTimestamp: numField(integral, 5),
|
|
80
|
+
fileLength: numField(ancillary, 1),
|
|
81
|
+
mimeType: strField(ancillary, 2),
|
|
82
|
+
objectId: strField(ancillary, 4)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// {Image,Video,Audio,Document}Transport {
|
|
87
|
+
// Integral { WAMediaTransport transport = 1; }
|
|
88
|
+
// Ancillary { uint32 height=1; uint32 width=2; ... } (varies per type, only
|
|
89
|
+
// height/width are common to image/video and are all we need)
|
|
90
|
+
// Integral integral = 1; Ancillary ancillary = 2;
|
|
91
|
+
// }
|
|
92
|
+
function decodeMediaTransportPayload(buf) {
|
|
93
|
+
const top = decodeFields(buf);
|
|
94
|
+
const integralWrapBuf = bytesField(top, 1);
|
|
95
|
+
const ancillaryBuf = bytesField(top, 2);
|
|
96
|
+
|
|
97
|
+
let transport = {};
|
|
98
|
+
if (integralWrapBuf) {
|
|
99
|
+
const integralWrap = decodeFields(integralWrapBuf);
|
|
100
|
+
const transportBuf = bytesField(integralWrap, 1);
|
|
101
|
+
if (transportBuf) transport = decodeWAMediaTransport(transportBuf);
|
|
102
|
+
}
|
|
103
|
+
let width, height;
|
|
104
|
+
if (ancillaryBuf) {
|
|
105
|
+
const anc = decodeFields(ancillaryBuf);
|
|
106
|
+
height = numField(anc, 1);
|
|
107
|
+
width = numField(anc, 2);
|
|
108
|
+
}
|
|
109
|
+
return { ...transport, width, height };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Decodes a Content.{image,video,audio,document}Message object (as produced
|
|
114
|
+
* by the vendor engine's normalizeE2EEMessage) into flat transport fields
|
|
115
|
+
* usable by client.downloadMedia({directPath, mediaKey, mediaSha256, ...}).
|
|
116
|
+
* @param {"image"|"video"|"audio"|"document"} kind
|
|
117
|
+
* @param {object} mediaMessage e.g. content.imageMessage
|
|
118
|
+
*/
|
|
119
|
+
function decodeIncomingMedia(kind, mediaMessage) {
|
|
120
|
+
if (!mediaMessage) return null;
|
|
121
|
+
const sub = kind === "image" ? mediaMessage.image
|
|
122
|
+
: kind === "video" ? mediaMessage.video
|
|
123
|
+
: kind === "audio" ? mediaMessage.audio
|
|
124
|
+
: mediaMessage.document;
|
|
125
|
+
if (!sub) return null;
|
|
126
|
+
|
|
127
|
+
const subBuf = Buffer.isBuffer(sub) ? sub
|
|
128
|
+
: (sub.payload && Buffer.isBuffer(sub.payload)) ? sub.payload
|
|
129
|
+
: null;
|
|
130
|
+
if (!subBuf) return null;
|
|
131
|
+
|
|
132
|
+
let payload;
|
|
133
|
+
try {
|
|
134
|
+
const proto = decodeSubProtocol(subBuf);
|
|
135
|
+
payload = proto.payload ? decodeMediaTransportPayload(Buffer.from(proto.payload)) : decodeMediaTransportPayload(subBuf);
|
|
136
|
+
} catch (_) {
|
|
137
|
+
try { payload = decodeMediaTransportPayload(subBuf); } catch (__) { return null; }
|
|
138
|
+
}
|
|
139
|
+
if (!payload || !payload.directPath || !payload.mediaKey) return null;
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
kind,
|
|
143
|
+
directPath: payload.directPath,
|
|
144
|
+
mediaKey: payload.mediaKey,
|
|
145
|
+
fileSHA256: payload.fileSHA256,
|
|
146
|
+
fileEncSHA256: payload.fileEncSHA256,
|
|
147
|
+
mimeType: payload.mimeType || (kind === "image" ? "image/jpeg" : kind === "video" ? "video/mp4" : kind === "audio" ? "audio/ogg" : "application/octet-stream"),
|
|
148
|
+
fileLength: payload.fileLength,
|
|
149
|
+
width: payload.width,
|
|
150
|
+
height: payload.height,
|
|
151
|
+
fileName: mediaMessage.fileName || undefined
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
module.exports = { decodeIncomingMedia, decodeFields, decodeSubProtocol, decodeWAMediaTransport };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Third-Party Notice
|
|
2
|
+
|
|
3
|
+
The files in `native/build/messagix.so` and `native/build/messagix.dll`
|
|
4
|
+
are precompiled native binaries built from:
|
|
5
|
+
|
|
6
|
+
- **mautrix-go** — https://github.com/mautrix/go
|
|
7
|
+
- **mautrix-meta** — https://github.com/mautrix/meta
|
|
8
|
+
|
|
9
|
+
Copyright (c) Tulir Asokan and the mautrix-go / mautrix-meta contributors.
|
|
10
|
+
|
|
11
|
+
Both projects are licensed under the **Mozilla Public License 2.0 (MPL-2.0)**.
|
|
12
|
+
A copy of the license is available at:
|
|
13
|
+
https://www.mozilla.org/en-US/MPL/2.0/
|
|
14
|
+
|
|
15
|
+
`native/lib/index.mjs` is the Node.js FFI bridge (via `koffi`) used to call
|
|
16
|
+
into the compiled binary, adapted from the same upstream project's Node
|
|
17
|
+
bindings.
|
|
18
|
+
|
|
19
|
+
fca-eryxenx uses this native engine only for sending E2EE media attachments
|
|
20
|
+
(images/video/audio/documents) in end-to-end encrypted Messenger threads,
|
|
21
|
+
because the project's own hand-written Signal Protocol media encoder
|
|
22
|
+
(`../vendor/fme`) produces payloads that Facebook's servers accept but that
|
|
23
|
+
Messenger clients fail to render. Text messages and all non-media E2EE
|
|
24
|
+
functionality continue to use fca-eryxenx's original implementation.
|
|
25
|
+
|
|
26
|
+
In accordance with MPL-2.0 §3.3, this NOTICE file must be preserved and
|
|
27
|
+
distributed alongside these files, and any modifications to the covered
|
|
28
|
+
source files (if the original `.mjs`/Go source is later vendored here)
|
|
29
|
+
must remain under MPL-2.0 and have their source made available.
|
|
Binary file
|
|
Binary file
|