hridoy-ultimate 8.0.2 → 8.0.5
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 +37 -35
- package/LICENSE +23 -0
- package/README.md +135 -115
- package/docs/TEST_RESULTS.md +70 -0
- package/docs/UPSTREAM_API_DOCS.md +2712 -0
- package/func/checkUpdate.js +6 -0
- package/func/logAdapter.js +33 -0
- package/func/logger.js +48 -0
- package/index.d.ts +752 -0
- package/index.js +24 -824
- package/module/config.js +46 -0
- package/module/login.js +135 -0
- package/module/loginHelper.js +1398 -0
- package/module/options.js +49 -0
- package/package.json +75 -24
- package/scripts/run-tests.js +19 -0
- package/scripts/syntax-check.js +22 -0
- package/src/{addExternalModule.js → api/action/addExternalModule.js} +8 -8
- package/src/{changeAvatar.js → api/action/changeAvatar.js} +32 -33
- package/src/{changeBio.js → api/action/changeBio.js} +19 -22
- package/src/api/action/dismissScrapingWarning.js +50 -0
- package/src/api/action/enableAutoSaveAppState.js +73 -0
- package/src/{getCurrentUserID.js → api/action/getCurrentUserID.js} +1 -1
- package/src/api/action/handleFriendRequest.js +57 -0
- package/src/api/action/logout.js +94 -0
- package/src/api/action/refreshFb_dtsg.js +47 -0
- package/src/{setPostReaction.js → api/action/setPostReaction.js} +23 -31
- package/src/{unfriend.js → api/action/unfriend.js} +14 -14
- 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/{changeArchivedStatus.js → api/messaging/changeArchivedStatus.js} +15 -17
- package/src/{changeBlockedStatus.js → api/messaging/changeBlockedStatus.js} +13 -16
- 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/{createNewGroup.js → api/messaging/createNewGroup.js} +24 -26
- 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/{deleteThread.js → api/messaging/deleteThread.js} +14 -16
- 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/{getEmojiUrl.js → api/messaging/getEmojiUrl.js} +2 -2
- package/src/{getFriendsList.js → api/messaging/getFriendsList.js} +16 -19
- package/src/{getMessage.js → api/messaging/getMessage.js} +160 -180
- package/src/api/messaging/getThemePictures.js +62 -0
- package/src/api/messaging/handleMessageRequest.js +65 -0
- package/src/api/messaging/markAsDelivered.js +69 -0
- package/src/api/messaging/markAsRead.js +110 -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/{resolvePhotoUrl.js → api/messaging/resolvePhotoUrl.js} +11 -15
- package/src/api/messaging/scheduler.js +264 -0
- package/src/{searchForThread.js → api/messaging/searchForThread.js} +12 -12
- 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/{threadColors.js → api/messaging/threadColors.js} +2 -5
- package/src/api/messaging/unsendMessage.js +105 -0
- package/src/api/messaging/uploadAttachment.js +493 -0
- package/src/api/socket/OldMessage.js +199 -0
- package/src/api/socket/core/connectMqtt.js +304 -0
- package/src/api/socket/core/emitAuth.js +95 -0
- package/src/api/socket/core/getSeqID.js +331 -0
- package/src/api/socket/core/getTaskResponseData.js +25 -0
- package/src/api/socket/core/lifecycle.js +117 -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 +961 -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/{lib → src/api/socket/e2ee/native/lib}/index.mjs +109 -66
- package/src/api/socket/e2ee/native/nativeMediaBridge.js +273 -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 +87 -0
- package/src/api/socket/listenMqtt.js +486 -0
- package/src/api/socket/middleware/index.js +216 -0
- package/src/api/socket/sendMessage.js +331 -0
- package/src/api/socket/sendMessageMqtt.js +69 -0
- package/src/{getThreadHistory.js → api/threads/getThreadHistory.js} +114 -132
- 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/{getUserID.js → api/users/getUserID.js} +22 -18
- 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/antiSuspension.js +219 -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 +85 -0
- package/src/utils/fingerprint.js +101 -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 +195 -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 +125 -0
- package/src/utils/humanizer.js +256 -0
- package/src/utils/loginParser/autoLogin.js +125 -0
- package/src/utils/loginParser/extractDtsg.js +44 -0
- package/src/utils/loginParser/helpers.js +43 -0
- package/src/utils/loginParser/index.js +10 -0
- package/src/utils/loginParser/parseAndCheckLogin.js +241 -0
- package/src/utils/loginParser/textUtils.js +28 -0
- package/src/utils/nexca-logger.js +144 -0
- package/src/utils/nexca-utils.js +687 -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/test/helpers/stub-modules.js +122 -0
- package/test/integration/logout.test.js +69 -0
- package/test/integration/mqtt-lifecycle.test.js +195 -0
- package/test/integration/package.test.js +106 -0
- package/test/unit/humanizer.test.js +32 -0
- package/test/unit/lifecycle.test.js +92 -0
- package/test/unit/parsers.test.js +43 -0
- package/ANALYSIS.md +0 -31
- package/AUDIT_REPORT.md +0 -57
- package/advancedSystem.js +0 -95
- package/build/messagix.dll +0 -0
- package/build/messagix.so +0 -0
- package/checkUpdate.js +0 -47
- package/config.json +0 -51
- package/e2ee.js +0 -738
- package/examples/basic-bot.js +0 -122
- package/examples/e2ee-bot.js +0 -141
- package/fca-config.example.json +0 -73
- package/scripts/check.js +0 -38
- package/src/OldMessage.js +0 -357
- package/src/addUserToGroup.js +0 -117
- package/src/changeAdminStatus.js +0 -105
- package/src/changeAvatarV2.js +0 -86
- package/src/changeAvt.js +0 -85
- package/src/changeBlockedStatusMqtt.js +0 -75
- package/src/changeCover.js +0 -73
- package/src/changeGroupImage.js +0 -137
- package/src/changeName.js +0 -79
- package/src/changeNickname.js +0 -61
- package/src/changeThreadColor.js +0 -67
- package/src/changeThreadEmoji.js +0 -57
- package/src/changeUsername.js +0 -59
- package/src/createCommentPost.js +0 -232
- package/src/createPoll.js +0 -73
- package/src/createPost.js +0 -276
- package/src/deleteMessage.js +0 -58
- package/src/editMessage.js +0 -76
- package/src/editMessageOld.js +0 -62
- package/src/follow.js +0 -74
- package/src/forwardAttachment.js +0 -62
- package/src/friendList.js +0 -104
- package/src/getAccess.js +0 -112
- package/src/getAvatarUser.js +0 -78
- package/src/getBotInitialData.js +0 -42
- package/src/getCtx.js +0 -5
- package/src/getOptions.js +0 -5
- package/src/getRegion.js +0 -7
- package/src/getThreadHistoryDeprecated.js +0 -71
- package/src/getThreadInfo.js +0 -232
- package/src/getThreadInfoDeprecated.js +0 -56
- package/src/getThreadList.js +0 -213
- package/src/getThreadListDeprecated.js +0 -46
- package/src/getThreadPictures.js +0 -59
- package/src/getThreadTheme.js +0 -81
- package/src/getUID.js +0 -119
- package/src/getUserInfo.js +0 -66
- package/src/handleFriendRequest.js +0 -46
- package/src/handleMessageRequest.js +0 -47
- package/src/httpGet.js +0 -49
- package/src/httpPost.js +0 -48
- package/src/httpPostFormData.js +0 -70
- package/src/listenMqtt.js +0 -1081
- package/src/listenNotification.js +0 -85
- package/src/logout.js +0 -18
- package/src/markAsDelivered.js +0 -47
- package/src/markAsRead.js +0 -72
- package/src/markAsReadAll.js +0 -40
- package/src/markAsSeen.js +0 -48
- package/src/metaTheme.js +0 -189
- package/src/muteThread.js +0 -45
- package/src/note.js +0 -228
- package/src/pinMessage.js +0 -54
- package/src/refreshFb_dtsg.js +0 -49
- package/src/removeSuspiciousAccount.js +0 -78
- package/src/removeUserFromGroup.js +0 -81
- package/src/reply.js +0 -442
- package/src/searchFriends.js +0 -140
- package/src/searchStickers.js +0 -53
- package/src/send.js +0 -46
- package/src/sendButtons.js +0 -163
- package/src/sendComment.js +0 -159
- package/src/sendFriendRequest.js +0 -112
- package/src/sendMessage.js +0 -441
- package/src/sendMessageMqtt.js +0 -323
- package/src/sendTypingIndicator.js +0 -68
- package/src/sendTypingIndicatorV2.js +0 -22
- package/src/setActiveStatus.js +0 -92
- package/src/setMessageReaction.js +0 -150
- package/src/setMessageReactionMqtt.js +0 -104
- package/src/setMessageReactionSafe.js +0 -44
- package/src/setProfileGuard.js +0 -44
- package/src/setProfileLock.js +0 -97
- package/src/setStoryReaction.js +0 -133
- package/src/setStorySeen.js +0 -108
- package/src/setThreadTheme.js +0 -102
- package/src/setTitle.js +0 -92
- package/src/shareContact.js +0 -110
- package/src/shareLink.js +0 -59
- package/src/stopListenMqtt.js +0 -60
- package/src/storyManager.js +0 -357
- package/src/suggestFriend.js +0 -132
- package/src/unsendMessage.js +0 -68
- package/src/uploadAttachment.js +0 -115
- package/test/fixes-1_2_4.test.js +0 -118
- package/test/mqtt-stop.test.js +0 -32
- package/test/reaction-mqtt.test.js +0 -57
- package/utils.js +0 -3056
package/CHANGELOG.md
CHANGED
|
@@ -1,43 +1,45 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 8.0.
|
|
4
|
-
- Rename: package/branding is now `hridoy-ultimate` (was `toru-fca`) in banner, logs, update check, README, examples and config comments.
|
|
5
|
-
- Update check env var `HRIDOY_ULTIMATE_NO_UPDATE_CHECK` added (old `TORU_FCA_NO_UPDATE_CHECK` still honoured).
|
|
6
|
-
- Internal globals (`global._toruFcaConfig`, `_toruFcaInitDone`) intentionally unchanged for backward compatibility.
|
|
3
|
+
## 8.0.5 - hridoy-ultimate (first release under this name)
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
- Fix: `changeCover` used `log` without requiring `npmlog`.
|
|
11
|
-
- Fix: `createCommentPost` typo `calback`, undefined `image` in attachment error, and `cb(null, err)` resolving errors as success (now rejects).
|
|
12
|
-
- Fix: `package.json` declares `form-data` and `https-proxy-agent` (were required but undeclared); removed unused `chalk`, `tough-cookie`, `protobufjs`.
|
|
13
|
-
- Fix: `checkUpdate.js` hard-coded version 1.2.1; now read from `package.json`.
|
|
14
|
-
- Chore: example config version synced; CRLF -> LF in `reply.js`, `getUID.js`, `httpGet.js`, `httpPost.js`, `changeAvt.js`.
|
|
15
|
-
- Add: `scripts/check.js` (`npm run check`) and `test/fixes-1_2_4.test.js` (6 regression tests, incl. a reconnect test verified to fail on the old code).
|
|
5
|
+
Built by merging the eryxenx-fca 1.0.0 - 1.1.9 lineage. Base tree: 1.1.9, with
|
|
6
|
+
`module/loginHelper.js` from 1.1.8 (1.1.9 regressed it).
|
|
16
7
|
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
8
|
+
### Security
|
|
9
|
+
- Removed the hard-coded third-party credential-login host; `apiServer` is now empty by
|
|
10
|
+
default and credential login refuses to run without one explicitly configured.
|
|
11
|
+
- Removed unverifiable prebuilt native binaries (messagix .so/.dll). Native E2EE engine is
|
|
12
|
+
opt-in (`FCA_E2EE_NATIVE=1` + `FCA_E2EE_NATIVE_LIB`).
|
|
13
|
+
- `autoUpdate` default is now `false` (it was an inert stub upstream).
|
|
23
14
|
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
-
|
|
15
|
+
### Fixed
|
|
16
|
+
- Pending reconnect / getSeqID retry timers could revive the listener after `stopListening()`
|
|
17
|
+
(reproduced on 1.1.9: 30 `getSeqID` calls after stop). Timers are now tracked and
|
|
18
|
+
gated by a `_stopped` flag.
|
|
19
|
+
- Reconnect used a fixed 2 s delay forever. Now bounded exponential backoff with jitter,
|
|
20
|
+
attempt budget (default 10) and a `stop_listen` event when exhausted.
|
|
21
|
+
- Calling listen twice left two live MQTT clients; the old client is now replaced.
|
|
22
|
+
- Events from stale/replaced clients are ignored.
|
|
23
|
+
- Late socket `error` after cleanup could throw (EventEmitter with no error handler).
|
|
24
|
+
- Sync queue is published after SUBACKs instead of immediately after subscribe.
|
|
25
|
+
- `logout()` now stops MQTT, disconnects E2EE and clears all timers.
|
|
26
|
+
- `emitAuth` now clears heartbeat / session-keeper / dtsg timers.
|
|
27
|
+
- Session keeper no longer re-arms after stop; heartbeat no longer fights a pending backoff.
|
|
28
|
+
- Undeclared dependencies (`request`, `tough-cookie`, `form-data`, `undici`) are declared.
|
|
29
|
+
- `index.d.ts` declared the wrong module name and had an `IFCAU_Api` typo.
|
|
30
|
+
- Silent `.catch(() => {})` on E2EE disconnect now logs.
|
|
31
31
|
|
|
32
|
+
### Changed (defaults)
|
|
33
|
+
- Humanizer (reply delay + command cooldown) is opt-in: `humanize: true`.
|
|
34
|
+
- Native E2EE engine is opt-in (reverts 1.0.8 default-on).
|
|
35
|
+
- `t_ms` wait 5 s -> 8 s, MQTT connect timeout 5 s -> 12 s (configurable).
|
|
36
|
+
- Node >= 18 required.
|
|
32
37
|
|
|
33
|
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
- Fix: stale MQTT client events caused duplicate reconnects; old client is now torn down first.
|
|
38
|
-
- Fix: getSeqID transient failure during reconnect no longer kills the listener (backoff retry).
|
|
39
|
-
- Fix: cookie expiry extension edited a copy; now updates the live jar.
|
|
40
|
-
- Fix: login callback double-fire guard.
|
|
41
|
-
- Change: uncaughtException logs stack for non-network errors.
|
|
42
|
-
- Change: e2ee disabled by default; spinner TTY-only; update check opt-out.
|
|
38
|
+
### Added
|
|
39
|
+
- `api.listenMqtt(callback, options)` second argument (reconnect/cycle options).
|
|
40
|
+
- Test suite (36 tests), `scripts/run-tests.js`, `scripts/syntax-check.js`.
|
|
41
|
+
- Docs: README, MERGE_REPORT, THIRD_PARTY_NOTICES, upstream API docs in `docs/`.
|
|
43
42
|
|
|
43
|
+
### Removed
|
|
44
|
+
- `cheerio`, `totp-generator`, `@noble/curves`, `@noble/hashes` (unused in source).
|
|
45
|
+
- Bogus `versionCheck` update notice (it compared against an unrelated npm package).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) EryXenX and contributors (eryxenx-fca 1.0.0 - 1.1.9)
|
|
4
|
+
Copyright (c) DongDev and contributors (original fca-unofficial lineage)
|
|
5
|
+
Copyright (c) 2026 HR ID OY (hridoy-ultimate modifications)
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
in the Software without restriction, including without limitation the rights
|
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,134 +1,154 @@
|
|
|
1
|
-
# hridoy-ultimate
|
|
1
|
+
# hridoy-ultimate
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Version 8.0.5 - Owner/maintainer: HR ID OY**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
An unofficial Facebook Chat API (FCA) for Node.js Messenger bots, unified from the
|
|
6
|
+
`eryxenx-fca` 1.0.0 - 1.1.9 lineage (itself derived from fca-unofficial) with a hardened
|
|
7
|
+
MQTT lifecycle: bounded exponential backoff, a reconnect budget, clean shutdown and no
|
|
8
|
+
timer left behind after `stopListening()` / `logout()`.
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
> **Unofficial.** This automates a personal Facebook account and may violate Facebook's
|
|
11
|
+
> terms. Accounts can be restricted. Use a throwaway account, never one you can't lose.
|
|
8
12
|
|
|
9
|
-
##
|
|
10
|
-
|
|
11
|
-
| Feature | Status |
|
|
13
|
+
## Verification status (read this first)
|
|
14
|
+
| Area | Status |
|
|
12
15
|
|---|---|
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
| E2EE Labyrinth Bridge | ✅ Active |
|
|
22
|
-
| Facebook Protection | ✅ New in v1.0.6 |
|
|
23
|
-
| Human-like Delay | ✅ New in v1.0.6 |
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## 📦 Install
|
|
16
|
+
| Unit tests (backoff, scheduler, parsers, humanizer) | **PASS** (real code, no mocks) |
|
|
17
|
+
| MQTT lifecycle, logout, package surface | **PASS - MOCKED** (fake mqtt/axios; see `test/helpers/stub-modules.js`) |
|
|
18
|
+
| TypeScript typings | **PASS** with `tsc` against a consumer sample (Node types stubbed) |
|
|
19
|
+
| Live Facebook login / MQTT / sending / reactions / attachments | **NOT TESTED** (no network or account in the build environment) |
|
|
20
|
+
| E2EE (encrypted chats) | **NOT TESTED** - needs optional deps and an unbundled native library |
|
|
21
|
+
| `npm install` from a clean registry | **NOT TESTED** (build sandbox was offline) |
|
|
22
|
+
|
|
23
|
+
Full results: `docs/TEST_RESULTS.md`. Honest limits: [Known limitations](#known-limitations).
|
|
28
24
|
|
|
25
|
+
## Install
|
|
26
|
+
Requires Node.js >= 18.
|
|
29
27
|
```bash
|
|
30
|
-
npm install
|
|
28
|
+
npm install hridoy-ultimate # from a registry, or:
|
|
29
|
+
npm install ./hridoy-ultimate-8.0.5.tgz
|
|
31
30
|
```
|
|
31
|
+
`sqlite3` compiles/downloads a native module; E2EE-related packages are optional.
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
## 🚀 Usage (GoatBot / Goat-Bot)
|
|
36
|
-
|
|
33
|
+
## Quick start
|
|
37
34
|
```js
|
|
38
|
-
const login = require("hridoy-ultimate");
|
|
35
|
+
const login = require("hridoy-ultimate"); // also: require(...).login, .default
|
|
39
36
|
const fs = require("fs");
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
listenEvents: true,
|
|
43
|
-
selfListen: false,
|
|
44
|
-
autoReconnect: true,
|
|
45
|
-
online: false
|
|
46
|
-
}, (err, api) => {
|
|
47
|
-
if (err) return console.error(err);
|
|
38
|
+
const appState = JSON.parse(fs.readFileSync("appstate.json", "utf8")); // keep this file secret
|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
login({ appState }, { listenEvents: true, autoReconnect: true }, (err, api) => {
|
|
41
|
+
if (err) return console.error("login failed:", err.error || err.message || err);
|
|
51
42
|
|
|
52
|
-
api.listenMqtt((err, event) => {
|
|
53
|
-
if (
|
|
54
|
-
|
|
43
|
+
const stop = api.listenMqtt((err, event) => {
|
|
44
|
+
if (err) {
|
|
45
|
+
if (err.type === "stop_listen") return console.error("listener gave up:", err.error);
|
|
46
|
+
return console.error(err);
|
|
55
47
|
}
|
|
48
|
+
if (event.type === "message" && event.body === "ping") {
|
|
49
|
+
api.sendMessage("pong", event.threadID, undefined, event.messageID);
|
|
50
|
+
api.setMessageReaction("👍", event.messageID, event.threadID, () => {}, true);
|
|
51
|
+
}
|
|
52
|
+
}, { maxReconnectAttempts: 10 });
|
|
53
|
+
|
|
54
|
+
process.on("SIGINT", async () => {
|
|
55
|
+
stop.stopListening(async () => { await api.logout(); process.exit(0); });
|
|
56
56
|
});
|
|
57
57
|
});
|
|
58
58
|
```
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
59
|
+
(Argument orders (`sendMessage(msg, threadID, callback, replyToMessageID)`,
|
|
60
|
+
`setMessageReaction(reaction, messageID, threadID, callback, force)`) were read from the source; see
|
|
61
|
+
`docs/UPSTREAM_API_DOCS.md` and `index.d.ts`. These calls are **NOT TESTED live**.)
|
|
62
|
+
|
|
63
|
+
## Authentication and session security
|
|
64
|
+
- Prefer **appState/cookie login**. Never commit `appstate.json`, cookies or tokens.
|
|
65
|
+
- Credential (email/password/2FA) login goes through a **third-party HTTP API that you must
|
|
66
|
+
configure** (`apiServer` in `fca-config.json`). It is empty by default because those
|
|
67
|
+
secrets would be sent to that host. Only point it at a server you control.
|
|
68
|
+
- Log lines mention cookie *counts*, but I did not audit every log call; treat console output as sensitive.
|
|
69
|
+
- `api.getAppState()` output equals full account access.
|
|
70
|
+
|
|
71
|
+
## Options
|
|
72
|
+
Login options (`setOptions`): `online`, `selfListen`, `listenEvents`, `updatePresence`,
|
|
73
|
+
`forceLogin`, `autoMarkRead`, `listenTyping`, `autoReconnect`, `emitReady`,
|
|
74
|
+
`selfListenEvent`, `userAgent`, `proxy`, `humanize`.
|
|
75
|
+
|
|
76
|
+
`api.listenMqtt(callback, options)` options (all optional):
|
|
77
|
+
| option | default | meaning |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| `autoReconnect` | `true` | reconnect after socket loss |
|
|
80
|
+
| `reconnectDelayMs` | 2000 | first backoff delay (doubles each attempt) |
|
|
81
|
+
| `maxReconnectDelayMs` | 300000 | backoff ceiling |
|
|
82
|
+
| `reconnectJitter` | 0.3 | +/- fraction randomised |
|
|
83
|
+
| `maxReconnectAttempts` | 10 | `0` = unlimited (explicit opt-in); on exhaustion you get `{type:"stop_listen"}` |
|
|
84
|
+
| `tmsWaitTimeoutMs` | 8000 | wait for first sync response before cycling |
|
|
85
|
+
| `connectTimeoutMs` | 12000 | MQTT connect timeout |
|
|
86
|
+
| `cycleMs` | 0 | periodic forced reconnect (off) |
|
|
87
|
+
| `reconnectAfterStop` | `false` | restart after `stopListening` |
|
|
88
|
+
|
|
89
|
+
The attempt counter resets after the first healthy sync response.
|
|
90
|
+
|
|
91
|
+
## Events and MQTT recovery
|
|
92
|
+
- `callback(err, event)`; events include `message`, `message_reply`, `message_edit`,
|
|
93
|
+
`message_reaction`, `message_unsend`, `event`, `typ`, `presence`, `share`,
|
|
94
|
+
`friend_request_received`, `friend_request_cancel` (type strings found in the source parsers;
|
|
95
|
+
per-type shapes are in the upstream docs; none exercised live).
|
|
96
|
+
- Control events arrive as `err` objects: `{type:"ready"}`, `{type:"account_inactive"}`
|
|
97
|
+
(session lost; everything is stopped), `{type:"stop_listen"}` (retry budget exhausted or stopped).
|
|
98
|
+
- Recovery: socket close/error -> backoff reconnect (reuses sync token) -> on repeated
|
|
99
|
+
failure refresh session/dtsg -> give up with `stop_listen`. Stale clients are ignored.
|
|
100
|
+
- Shutdown: `stopListening(cb)` cancels all timers, ends the client, is idempotent.
|
|
101
|
+
`logout()` additionally disconnects E2EE and clears the dtsg refresh timer.
|
|
102
|
+
|
|
103
|
+
## Opt-in features
|
|
104
|
+
- **Humanizer** (`humanize: true`): delays command replies 2-3 s and *drops* commands inside a
|
|
105
|
+
5.5 s cooldown. Drops are intentional and counted; it is off by default. It contains
|
|
106
|
+
special handling for GoatBot globals.
|
|
107
|
+
- **Optional native E2EE engine**: set `FCA_E2EE_NATIVE=1` and `FCA_E2EE_NATIVE_LIB=/path/to/messagix`.
|
|
108
|
+
The library is **not bundled** (provenance unverifiable). Without it, group E2EE and E2EE media are unavailable.
|
|
109
|
+
|
|
110
|
+
## API surface
|
|
111
|
+
Package exports (verified by test): `login`, `default`, `createFcaClient`, `MessengerBot`,
|
|
112
|
+
`createMessengerBot`, `MessengerContext`, `attachThreadInfoRealtimeSync`,
|
|
113
|
+
`applyThreadInfoRealtimeEvent`, `CommandHumanizer`, `createCommandHumanizer`,
|
|
114
|
+
`createHumanizerMiddleware`, `humanizer`.
|
|
115
|
+
|
|
116
|
+
Methods attached to `api` after login (one per file in `src/api/`; signatures in upstream docs):
|
|
117
|
+
- action: `addExternalModule changeAvatar changeBio dismissScrapingWarning enableAutoSaveAppState getCurrentUserID handleFriendRequest logout refreshFb_dtsg setPostReaction unfriend`
|
|
118
|
+
- http: `httpGet httpPost postFormData`
|
|
119
|
+
- messaging: `addUserToGroup changeAdminStatus changeArchivedStatus changeBlockedStatus changeGroupImage changeNickname changeThreadColor changeThreadEmoji createNewGroup createPoll createThemeAI deleteMessage deleteThread editMessage forwardAttachment forwardMessage getEmojiUrl getFriendsList getMessage getThemePictures handleMessageRequest markAsDelivered markAsRead markAsReadAll markAsSeen muteThread pinMessage removeUserFromGroup resolvePhotoUrl scheduler searchForThread sendBroadcast sendMessage sendTypingIndicator setMessageReaction setTitle shareContact unsendMessage uploadAttachment`
|
|
120
|
+
- threads: `getThreadHistory getThreadInfo getThreadList getThreadPictures`
|
|
121
|
+
- users: `getUserID getUserInfo getUserInfoV2`
|
|
122
|
+
- socket: `listenMqtt` (= `listen`), `listenE2EE`, `stopListening`, `stopListeningAsync`
|
|
123
|
+
(Listed from the source tree; none were exercised against live Facebook.)
|
|
124
|
+
|
|
125
|
+
## Troubleshooting
|
|
126
|
+
- `Cannot find module ...` -> run `npm install`; optional E2EE deps may be absent by design.
|
|
127
|
+
- Login callback error -> appState expired; re-export cookies. Credential login needs `apiServer`.
|
|
128
|
+
- `stop_listen` event -> reconnect budget exhausted; check network/session, then call listen again.
|
|
129
|
+
- `account_inactive` -> Facebook invalidated the session (checkpoint/logout); re-login manually.
|
|
130
|
+
- A `Fca_Database/` folder appears in the working directory on first use (SQLite cache).
|
|
131
|
+
|
|
132
|
+
## Known limitations
|
|
133
|
+
- No live verification of anything that talks to Facebook; Facebook changes endpoints without notice.
|
|
134
|
+
- Subscribe-then-publish ordering and the 8 s / 12 s timeouts follow upstream's changelog
|
|
135
|
+
reasoning and mqtt.js semantics; not confirmed against live servers.
|
|
136
|
+
- Legacy HTTP paths still use the deprecated `request` library (`nexca-utils.js`); porting to axios is future work.
|
|
137
|
+
- `sequelize`+`sqlite3` are hard dependencies (heavy); `index.d.ts` is upstream-derived and not exhaustive.
|
|
138
|
+
- Vendored E2EE bundle has no license header or source.
|
|
139
|
+
|
|
140
|
+
## Migration from eryxenx-fca 1.x
|
|
141
|
+
- Package name `hridoy-ultimate`; Node >= 18.
|
|
142
|
+
- Humanizer and native E2EE are now **opt-in** (they were default-on in 1.1.x / 1.0.8+).
|
|
143
|
+
- `apiServer` has no default; autoUpdate is off.
|
|
144
|
+
- Reconnects are bounded: handle `{type:"stop_listen"}`.
|
|
145
|
+
- `api.listenMqtt(cb, options)` gains an optional second argument.
|
|
146
|
+
|
|
147
|
+
## Develop
|
|
148
|
+
```bash
|
|
149
|
+
npm install
|
|
150
|
+
npm test # unit + integration (mocked) tests
|
|
151
|
+
npm run lint # syntax check of every source file
|
|
152
|
+
npm pack # builds hridoy-ultimate-8.0.5.tgz
|
|
73
153
|
```
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## 🔐 Anti-Logout System
|
|
78
|
-
|
|
79
|
-
Cookie login করলে `api.logout()` automatically blocked হয়।
|
|
80
|
-
- Session refresh does not guarantee that Facebook will preserve a login session
|
|
81
|
-
- `api.logout()` is currently overridden; use `api.forceLogout()` only when you explicitly intend to terminate the session
|
|
82
|
-
- Force logout দরকার হলে: `api.forceLogout()`
|
|
83
|
-
- Anti-logout বন্ধ করতে: `api.stopAntiLogout()`
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
## 📊 API Methods
|
|
88
|
-
|
|
89
|
-
| Method | Description |
|
|
90
|
-
|---|---|
|
|
91
|
-
| `api.sendMessage(msg, threadID)` | Message পাঠাও |
|
|
92
|
-
| `api.listenMqtt(callback)` | Message শোনো |
|
|
93
|
-
| `api.sessionGuard(path, opts)` | Appstate auto-save |
|
|
94
|
-
| `api.saveSession(path)` | Manual session save |
|
|
95
|
-
| `api.getHealth()` | MQTT + session health |
|
|
96
|
-
| `api.forceLogout()` | Force logout (opt-in) |
|
|
97
|
-
| `api.stopAntiLogout()` | Anti-logout timer বন্ধ |
|
|
98
|
-
| `api.refreshFb_dtsg()` | Manual fb_dtsg refresh |
|
|
99
|
-
| `api.sendTypingIndicatorV2(typing, threadID)` | MQTT typing indicator |
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
## 🛡️ Facebook Protection (v1.0.6)
|
|
104
|
-
|
|
105
|
-
- `humanLikeDelay: true` — প্রতিটি message এ random 50-200ms delay, bot traffic pattern unpredictable
|
|
106
|
-
- `blockAutomationDetection: true` — online=false, presence update বন্ধ
|
|
107
|
-
- ফলে Facebook account এ restriction বা ban আসে না
|
|
108
|
-
|
|
109
|
-
---
|
|
110
|
-
|
|
111
|
-
**hridoy-ultimate v8.0.1** — Built on toru-fca 1.2.0 (itself derived from HRIDOY-FCA / ST-FCA). Other packages were analysed and only selected ideas were ported — see ANALYSIS.md
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
## What's new in v1.2.4
|
|
115
|
-
- **Critical fix:** MQTT auto-reconnect crashed with `ReferenceError: getSeqID is not defined` (the reconnect timer called a function that lives in another scope). The factory now exposes it as `ctx._getSeqID` and the timer uses that, guarded by try/catch.
|
|
116
|
-
- `changeCover`: missing `npmlog` import (ReferenceError on every error path) fixed.
|
|
117
|
-
- `createCommentPost`: fixed `calback` typo (crash whenever a callback was passed), undefined `image` in the attachment error, and failures that *resolved* with the error object instead of rejecting.
|
|
118
|
-
- `package.json`: declared `form-data` and `https-proxy-agent` (both were required but missing); removed unused `chalk`, `tough-cookie`, `protobufjs`.
|
|
119
|
-
- `checkUpdate` now reads its version from `package.json` (was hard-coded 1.2.1). Example config version synced. CRLF line endings normalised to LF.
|
|
120
|
-
- New `npm run check` (syntax + relative/undeclared require check on every file) and regression tests in `test/fixes-1_2_4.test.js`.
|
|
121
|
-
|
|
122
|
-
## Earlier: v1.2.3
|
|
123
|
-
- **Reactions:** `message_reaction` events now carry `off`, `action` ("add"/"remove"), `userID` (reactor), `isGroup`, `isSingleUser` (inbox vs group) and are null-safe. `selfListen:false` also ignores the bot's own reactions.
|
|
124
|
-
- **api.setMessageReactionSafe(reaction, messageID, threadID, opts):** MQTT first, HTTP fallback with retry (idea from shadowx `setMessageReactionv2`). `setMessageReaction` now accepts any real emoji and no longer crashes on retry/redirect (it passed `ctx.jar` instead of `ctx` to `parseAndCheckLogin`; same bug fixed in `forwardAttachment`).
|
|
125
|
-
- **api.setMessageReactionMqtt:** the old `isCallable()` helper *called* your callback with no arguments and the call could throw synchronously. Fixed; supports callbacks and Promises; real ack via `/ls_resp`.
|
|
126
|
-
- **MQTT stability:** events from replaced clients are ignored (no double-reconnect loops), a failed `getSeqID` during reconnect now retries with backoff instead of silently killing the listener, spinner only draws on a TTY.
|
|
127
|
-
- **Session safety:** cookie-expiry extension now really works (v1.2.0 edited a throw-away copy). Login callback can no longer fire twice.
|
|
128
|
-
- **Errors:** uncaught exceptions are still non-fatal but now print the stack instead of hiding it.
|
|
129
|
-
- E2EE is off by default (needs the native `messagix` binary which is not bundled).
|
|
130
|
-
- Update check never installs anything; disable with `HRIDOY_ULTIMATE_NO_UPDATE_CHECK=1` (old `TORU_FCA_NO_UPDATE_CHECK` still works).
|
|
131
|
-
|
|
132
|
-
## Honest notes
|
|
133
|
-
- Login: use `appState` (cookie array / cookie string). `api.logout()` is blocked on purpose; use `api.forceLogout()` if you really want to log out.
|
|
134
|
-
- "Facebook protection" (online=false, small delays) only lowers noise. No library can guarantee Facebook will not flag or checkpoint an account that is driven by a bot.
|
|
154
|
+
Credits and licenses: `LICENSE`, `THIRD_PARTY_NOTICES.md`. Merge details: `MERGE_REPORT.md`.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Test results (actual output)
|
|
2
|
+
|
|
3
|
+
Environment: v22.22.2, Linux 6.18.44-fc-v114, no network, third-party modules stubbed (MOCKED where marked).
|
|
4
|
+
Generated: 2026-10-13T00:50Z
|
|
5
|
+
|
|
6
|
+
## npm test (node --test, spec reporter)
|
|
7
|
+
```
|
|
8
|
+
✔ [mocked] logout stops MQTT, disconnects E2EE and clears every timer (34.815074ms)
|
|
9
|
+
✔ [mocked] logout works when no listener was ever started (10.349818ms)
|
|
10
|
+
✔ [mocked] a failed logout request is reported, not swallowed, and the session stays usable (7.042588ms)
|
|
11
|
+
✔ [mocked] sync queue is published only after every SUBACK (35.992484ms)
|
|
12
|
+
✔ [mocked] reconnect after socket close uses backoff, then recovers (12.978848ms)
|
|
13
|
+
✔ [mocked] stopListening during a cycle must not be revived by a pending retry (race regression) (10.298466ms)
|
|
14
|
+
✔ [mocked] stopListening clears timers, ends the client and is safe to call twice (10.426547ms)
|
|
15
|
+
✔ [mocked] late socket 'error' after stopListening does not throw (6.131105ms)
|
|
16
|
+
✔ [mocked] calling listen twice replaces the old client (no duplicate connection) (8.659963ms)
|
|
17
|
+
✔ [mocked] gives up after maxReconnectAttempts and reports stop_listen (no infinite loop) (7.160329ms)
|
|
18
|
+
✔ [mocked] a healthy first sync resets the backoff counter (7.857639ms)
|
|
19
|
+
✔ [mocked] humanizer middleware is NOT installed by default, and is when opted in (14.187447ms)
|
|
20
|
+
✔ [mocked] emitAuth stops everything and reports account_inactive (7.957109ms)
|
|
21
|
+
✔ [mocked] listen(callback, options) applies reconnect options per call (6.735507ms)
|
|
22
|
+
✔ package metadata: name, version, owner, entry points exist (1.135404ms)
|
|
23
|
+
✔ regression: every third-party module the source requires is declared (14.850827ms)
|
|
24
|
+
✔ vendored E2EE bundle: its external requires are declared too (1.810192ms)
|
|
25
|
+
✔ no prebuilt native binaries or default third-party credential host ship in the package (5.439855ms)
|
|
26
|
+
✔ every JS file in the package parses (4215.825382ms)
|
|
27
|
+
✔ [mocked] package loads with consistent exports (19.12184ms)
|
|
28
|
+
✔ [mocked] login with empty options reports an error via callback and never throws (3230.691403ms)
|
|
29
|
+
✔ humanizer: first command accepted with a bounded delay, burst inside cooldown dropped (1.957104ms)
|
|
30
|
+
✔ humanizer: non-command messages pass untouched; per-thread isolation (0.413424ms)
|
|
31
|
+
✔ humanizer: enabled:false never delays or drops (0.980328ms)
|
|
32
|
+
✔ computeBackoff grows exponentially, is bounded and never negative (1.903627ms)
|
|
33
|
+
✔ computeBackoff jitter stays within +/- jitter and clamps to max (0.181485ms)
|
|
34
|
+
✔ computeBackoff tolerates garbage input (0.17167ms)
|
|
35
|
+
✔ scheduleReconnect: single timer, debounce, stop, exhaustion (0.820579ms)
|
|
36
|
+
✔ scheduleReconnect: a timer that fires after stop does nothing (race regression) (0.217074ms)
|
|
37
|
+
✔ maxReconnectAttempts: 0 means unlimited only when explicitly set (1.317064ms)
|
|
38
|
+
✔ clearListenerTimers is idempotent and clears every owned timer (0.41435ms)
|
|
39
|
+
✔ detachClient: a late 'error' after detach must not throw (0.347064ms)
|
|
40
|
+
✔ extractDtsg handles each supported markup shape (1.363764ms)
|
|
41
|
+
✔ extractDtsg: jazoest forms, empty and non-string input (0.821093ms)
|
|
42
|
+
✔ fingerprint: default UA and client hints are mutually consistent (0.728798ms)
|
|
43
|
+
✔ fingerprint: Android UA yields mobile Android hints (no desktop contradiction) (0.272025ms)
|
|
44
|
+
ℹ tests 36
|
|
45
|
+
ℹ pass 36
|
|
46
|
+
ℹ fail 0
|
|
47
|
+
ℹ cancelled 0
|
|
48
|
+
ℹ skipped 0
|
|
49
|
+
ℹ duration_ms 15939.95031
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## npm run lint
|
|
53
|
+
```
|
|
54
|
+
checked 151 files, 0 with syntax errors
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## TypeScript consumer check (tsc, Node types stubbed)
|
|
58
|
+
```
|
|
59
|
+
tsc exit 0
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Same lifecycle tests against original eryxenx-fca 1.1.9
|
|
63
|
+
```
|
|
64
|
+
# tests 11
|
|
65
|
+
# pass 1
|
|
66
|
+
# fail 10
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## NOT TESTED
|
|
70
|
+
Live Facebook login/MQTT/sending/reactions/attachments, E2EE, clean-registry npm install.
|