@vangbanlanhat/fca-unofficial 1.4.2

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 (115) hide show
  1. package/.gitattributes +2 -0
  2. package/.github/workflows/nodejs.yml +26 -0
  3. package/.github/workflows/npmpublish.yml +30 -0
  4. package/.travis.yml +6 -0
  5. package/CHANGELOG.md +2 -0
  6. package/DOCS.md +1932 -0
  7. package/LICENSE-MIT +21 -0
  8. package/README.md +198 -0
  9. package/jest.config.js +10 -0
  10. package/package.json +86 -0
  11. package/pnpm-workspace.yaml +3 -0
  12. package/src/actions/addExternalModule.js +34 -0
  13. package/src/actions/addUserToGroup.js +113 -0
  14. package/src/actions/changeAdminStatus.js +79 -0
  15. package/src/actions/changeArchivedStatus.js +55 -0
  16. package/src/actions/changeBio.js +77 -0
  17. package/src/actions/changeBlockedStatus.js +47 -0
  18. package/src/actions/changeGroupImage.js +129 -0
  19. package/src/actions/changeNickname.js +59 -0
  20. package/src/actions/changeThreadColor.js +71 -0
  21. package/src/actions/changeThreadEmoji.js +55 -0
  22. package/src/actions/createNewGroup.js +86 -0
  23. package/src/actions/createPoll.js +71 -0
  24. package/src/actions/deleteMessage.js +56 -0
  25. package/src/actions/deleteThread.js +56 -0
  26. package/src/actions/editMessage.js +81 -0
  27. package/src/actions/forwardAttachment.js +60 -0
  28. package/src/actions/getAvatarUser.js +77 -0
  29. package/src/actions/getCurrentUserID.js +11 -0
  30. package/src/actions/getEmojiUrl.js +37 -0
  31. package/src/actions/getFriendsList.js +84 -0
  32. package/src/actions/getMessage.js +833 -0
  33. package/src/actions/getRegion.js +11 -0
  34. package/src/actions/getThreadHistory.js +702 -0
  35. package/src/actions/getThreadHistoryDeprecated.js +93 -0
  36. package/src/actions/getThreadInfo.js +265 -0
  37. package/src/actions/getThreadInfoDeprecated.js +80 -0
  38. package/src/actions/getThreadList.js +274 -0
  39. package/src/actions/getThreadListDeprecated.js +91 -0
  40. package/src/actions/getThreadPictures.js +79 -0
  41. package/src/actions/getUserID.js +66 -0
  42. package/src/actions/getUserInfo.js +92 -0
  43. package/src/actions/handleFriendRequest.js +61 -0
  44. package/src/actions/handleMessageRequest.js +65 -0
  45. package/src/actions/httpGet.js +70 -0
  46. package/src/actions/httpPost.js +70 -0
  47. package/src/actions/index.js +69 -0
  48. package/src/actions/listenMqtt.js +818 -0
  49. package/src/actions/logout.js +136 -0
  50. package/src/actions/markAsDelivered.js +58 -0
  51. package/src/actions/markAsRead.js +92 -0
  52. package/src/actions/markAsReadAll.js +50 -0
  53. package/src/actions/markAsSeen.js +59 -0
  54. package/src/actions/muteThread.js +52 -0
  55. package/src/actions/pinMessage.js +86 -0
  56. package/src/actions/refreshFb_dtsg.js +89 -0
  57. package/src/actions/removeUserFromGroup.js +79 -0
  58. package/src/actions/resolvePhotoUrl.js +45 -0
  59. package/src/actions/searchForThread.js +53 -0
  60. package/src/actions/searchStickers.js +53 -0
  61. package/src/actions/sendMessage.js +490 -0
  62. package/src/actions/sendMessageMqtt.js +235 -0
  63. package/src/actions/sendTypingIndicator.js +59 -0
  64. package/src/actions/setMessageReaction.js +140 -0
  65. package/src/actions/setMessageReactionMqtt.js +72 -0
  66. package/src/actions/setPostReaction.js +76 -0
  67. package/src/actions/setTitle.js +86 -0
  68. package/src/actions/stopListenMqtt.js +63 -0
  69. package/src/actions/threadColors.js +57 -0
  70. package/src/actions/unfriend.js +52 -0
  71. package/src/actions/unsendMessage.js +61 -0
  72. package/src/index.js +659 -0
  73. package/src/service/uploadAttachment.js +318 -0
  74. package/src/utils/base-parts/auth.js +286 -0
  75. package/src/utils/base-parts/formatters.js +751 -0
  76. package/src/utils/base-parts/identity.js +169 -0
  77. package/src/utils/base-parts/network.js +159 -0
  78. package/src/utils/base-parts/parsing.js +53 -0
  79. package/src/utils/base-parts/type.js +9 -0
  80. package/src/utils/base.js +18 -0
  81. package/src/utils/defaults.js +10 -0
  82. package/src/utils/format-attachments.js +7 -0
  83. package/src/utils/format-core.js +8 -0
  84. package/src/utils/format-events.js +11 -0
  85. package/src/utils/format-messages.js +10 -0
  86. package/src/utils/format-presence.js +9 -0
  87. package/src/utils/format-threads.js +8 -0
  88. package/src/utils/formatters.js +18 -0
  89. package/src/utils/identity.js +12 -0
  90. package/src/utils/index.js +15 -0
  91. package/src/utils/network.js +12 -0
  92. package/src/utils/parsing.js +11 -0
  93. package/src/utils.js +3 -0
  94. package/test/config.env.example +30 -0
  95. package/test/data/shareAttach.js +146 -0
  96. package/test/data/something.mov +0 -0
  97. package/test/data/test.png +0 -0
  98. package/test/data/test.txt +7 -0
  99. package/test/example-appstate.txt +11 -0
  100. package/test/integration/actions.appstate.integration.test.js +233 -0
  101. package/test/integration/api.integration.test.js +387 -0
  102. package/test/integration/env-test-config.js +46 -0
  103. package/test/integration/login.appstate.integration.test.js +47 -0
  104. package/test/integration/page.integration.test.js +139 -0
  105. package/test/jest.setup.js +54 -0
  106. package/test/unit/actions/actions.basic.test.js +116 -0
  107. package/test/unit/actions/actions.registry.test.js +36 -0
  108. package/test/unit/index/index.test.js +109 -0
  109. package/test/unit/utils/base-parts/auth.test.js +92 -0
  110. package/test/unit/utils/base-parts/formatters.test.js +53 -0
  111. package/test/unit/utils/base-parts/identity.test.js +43 -0
  112. package/test/unit/utils/base-parts/parsing.test.js +38 -0
  113. package/test/unit/utils/base-parts/type.test.js +23 -0
  114. package/test/unit/utils/base.test.js +35 -0
  115. package/vangbanlanhat-fca-unofficial-1.4.2.tgz +0 -0
package/LICENSE-MIT ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Avery, Benjamin, David, Maude
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,198 @@
1
+ # Unofficial Facebook Chat API
2
+
3
+ <div align="center">
4
+ <a href="https://www.npmjs.com/package/fca-unofficial"><img alt="npm version" src="https://img.shields.io/npm/v/fca-unofficial.svg?style=flat-square"></a>
5
+ <img alt="version" src="https://img.shields.io/github/package-json/v/VangBanLaNhat/fca-unofficial?label=github&style=flat-square">
6
+ <a href="https://www.npmjs.com/package/fca-unofficial"><img src="https://img.shields.io/npm/dm/fca-unofficial.svg?style=flat-square" alt="npm downloads"></a>
7
+ <a href="https://github.com/prettier/prettier"><img alt="code style: prettier" src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square"></a>
8
+ </div>
9
+
10
+ This project provides an unofficial API for automating Facebook chat and Messenger functionalities. Facebook has deprecated their XMPP chat interface, leaving emulating a browser as the only viable method for account automation.
11
+
12
+ This API simulates exact GET/POST requests and MQTT connections, tricking Facebook into thinking it's a legitimate browser session.
13
+
14
+ > **Disclaimer:** We are not responsible if your account gets banned for spammy activities (sending messages too quickly, spamming strangers, logging in/out rapidly). Be a responsible Facebook citizen. Use [Facebook Whitehat Accounts](https://www.facebook.com/whitehat/accounts/) for safe testing.
15
+
16
+ ---
17
+
18
+ ## Documentation
19
+
20
+ For a comprehensive list of all available API methods, options, and parameters, please see the **[Full API Documentation (DOCS.md)](DOCS.md)**.
21
+
22
+ ## Tech Stack
23
+
24
+ - **Language**: JavaScript (Node.js)
25
+ - **Real-time Protocol**: MQTT (`mqtt` package)
26
+ - **HTML Parsing**: `cheerio`
27
+ - **Networking**: Built-in HTTP/HTTPS + `https-proxy-agent`
28
+ - **Testing Framework**: Jest
29
+
30
+ ## Prerequisites
31
+
32
+ - **Node.js**: v14.0.0 or higher
33
+ - **NPM or Yarn**: To install dependencies
34
+ - A valid Facebook account or a Facebook Whitehat Account for testing.
35
+
36
+ ## Getting Started
37
+
38
+ ### 1. Installation
39
+
40
+ Install the package via NPM:
41
+
42
+ ```bash
43
+ npm install @VangBanLaNhat/fca-unofficial
44
+ ```
45
+
46
+ ### 2. Basic Echo Bot Example
47
+
48
+ Create an `index.js` file and add the following code to create a bot that echoes messages back to the sender:
49
+
50
+ ```javascript
51
+ const login = require("@VangBanLaNhat/fca-unofficial");
52
+
53
+ // Login using your Facebook credentials
54
+ login({email: "FB_EMAIL", password: "FB_PASSWORD"}, (err, api) => {
55
+ if(err) return console.error("Login failed:", err);
56
+
57
+ console.log("Bot successfully logged in!");
58
+
59
+ // Start listening for incoming messages
60
+ api.listen((err, message) => {
61
+ if(err) return console.error(err);
62
+
63
+ // Echo the message back to the same chat thread
64
+ api.sendMessage("Echo: " + message.body, message.threadID);
65
+ });
66
+ });
67
+ ```
68
+
69
+ Run your bot:
70
+ ```bash
71
+ node index.js
72
+ ```
73
+
74
+ ### 3. Saving the Session (Avoiding Bans & Re-logins)
75
+
76
+ Logging in repeatedly with an email and password is a massive red flag for Facebook's anti-spam systems. **You must save and reuse your session (AppState).**
77
+
78
+ ```javascript
79
+ const fs = require("fs");
80
+ const login = require("@VangBanLaNhat/fca-unofficial");
81
+
82
+ // 1. Try to load an existing session
83
+ let appState = null;
84
+ try {
85
+ appState = JSON.parse(fs.readFileSync('appstate.json', 'utf8'));
86
+ } catch (e) {
87
+ console.log("No saved session found. Logging in with credentials...");
88
+ }
89
+
90
+ const credentials = appState
91
+ ? { appState: appState }
92
+ : { email: "FB_EMAIL", password: "FB_PASSWORD" };
93
+
94
+ login(credentials, (err, api) => {
95
+ if(err) return console.error(err);
96
+
97
+ // 2. Save the session for the next run
98
+ fs.writeFileSync('appstate.json', JSON.stringify(api.getAppState()));
99
+ console.log("Logged in and session saved!");
100
+
101
+ // ... continue with your bot logic ...
102
+ });
103
+ ```
104
+
105
+ *Alternative:* You can use browser extensions like [c3c-fbstate](https://github.com/lequanglam/c3c-fbstate) to manually extract your `fbstate.json` (appstate) directly from your browser.
106
+
107
+ ## Architecture Overview
108
+
109
+ This library essentially functions as a headless Facebook web client.
110
+
111
+ ### Request Lifecycle
112
+ 1. **Login:** The library performs a sequence of GET/POST requests to Facebook's login endpoints, mimicking a real browser login to acquire authentication cookies (`c_user`, `xs`, etc.).
113
+ 2. **Context Creation:** It builds an internal `ctx` (context) object containing your User ID, Client ID, and cookies.
114
+ 3. **MQTT Connection:** It establishes an MQTT over WebSockets connection to Facebook's servers to receive real-time events (new messages, typing indicators, read receipts).
115
+ 4. **Action Execution:** When you call an API method (like `sendMessage`), the library constructs the exact GraphQL or form-data HTTP request that the Messenger web app would send, and dispatches it.
116
+
117
+ ### Core Directory Structure
118
+
119
+ ```text
120
+ src/
121
+ ├── index.js # Main entrypoint and API builder
122
+ ├── actions/ # Contains all the individual API methods
123
+ │ ├── listenMqtt.js # Manages the real-time MQTT socket
124
+ │ ├── sendMessage.js# Handles message formatting and sending
125
+ │ └── ... # Other actions (reactions, unsending, etc.)
126
+ └── utils/ # Shared utilities
127
+ ├── auth.js # Cookie formatting and session extraction
128
+ ├── base.js # Core network request wrappers (get, post)
129
+ ├── formatters.js # Parsers that turn raw FB payloads into clean JSON
130
+ └── identity.js # Generators for IDs, GUIDs, and timestamps
131
+ ```
132
+
133
+ ## Available Scripts
134
+
135
+ | Command | Description |
136
+ | --- | --- |
137
+ | `npm run test` | Runs the full Jest test suite |
138
+ | `npm run test:unit` | Runs only unit tests |
139
+ | `npm run test:integration`| Runs integration tests (requires active config) |
140
+ | `npm run lint` | Runs ESLint to check for syntax/style issues |
141
+ | `npm run prettier` | Formats all code using Prettier |
142
+
143
+ ## Testing
144
+
145
+ The project uses **Jest** for unit and integration testing.
146
+
147
+ To run the unit tests:
148
+ ```bash
149
+ npm run test:unit
150
+ ```
151
+
152
+ To run integration tests (which actually hit Facebook endpoints), you must first create a valid config:
153
+ 1. Copy `example-config.json` to `test-config.json` inside the `test` directory.
154
+ 2. Fill in your test account credentials or appState.
155
+ 3. Run: `npm run test:integration`
156
+
157
+ ## Deployment
158
+
159
+ Since this is a standard Node.js application, you can deploy your bot anywhere Node.js runs (VPS, Heroku, Render, AWS, Docker).
160
+
161
+ **Important Deployment Tips:**
162
+ 1. **Do not commit `appstate.json` or passwords to Git.** Use environment variables for sensitive data.
163
+ 2. **IP Changes:** If you deploy your bot to a cloud server in a different country, Facebook might temporarily lock the account due to a "Suspicious Login". You may need to log into the account manually and approve the new location.
164
+
165
+ ## Troubleshooting
166
+
167
+ ### 1. "Login failed" or getting prompted for a code
168
+ If you have Two-Factor Authentication (2FA) or Login Approvals enabled, you must handle the approval step. Read the specific guide on [handling login approvals](DOCS.md#login).
169
+
170
+ ### 2. My account got locked/banned!
171
+ This happens if you send messages too fast or to people who are not your friends.
172
+ - Use `setTimeout` to add human-like delays.
173
+ - Always use cached sessions (`appState`) instead of logging in repeatedly.
174
+ - Use a throwaway account for development.
175
+
176
+ ### 3. `sendMessage` isn't working when logged in as a Page
177
+ Facebook Pages cannot initiate conversations with users to prevent spam. Your bot can only reply to users who have messaged the Page first within the last 24 hours.
178
+
179
+ ### 4. How do I stop the spammy console logs?
180
+ Pass a `logLevel` option when configuring the API:
181
+ ```javascript
182
+ api.setOptions({
183
+ logLevel: "silent" // Options: "silly", "verbose", "info", "warn", "error", "silent"
184
+ });
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Projects using this API
190
+
191
+ - [c3c](https://github.com/lequanglam/c3c) - A bot that can be customizable using plugins. Support Facebook & Discord.
192
+
193
+ **Historical Projects (from the original `facebook-chat-api`):**
194
+ - [Messer](https://github.com/mjkaufer/Messer) - Command-line messaging for Facebook Messenger
195
+ - [messen](https://github.com/tomquirk/messen) - Rapidly build Facebook Messenger apps in Node.js
196
+ - [Concierge](https://github.com/concierge/Concierge) - Modular chat bot with a package manager
197
+ - [Botium](https://github.com/codeforequity-at/botium-core) - The Selenium for Chatbots
198
+ - [Miscord](https://github.com/Bjornskjald/miscord) - Facebook bridge for Discord.
package/jest.config.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ module.exports = {
4
+ testEnvironment: "node",
5
+ testMatch: ["<rootDir>/test/**/*.test.js"],
6
+ setupFiles: ["<rootDir>/test/jest.setup.js"],
7
+ clearMocks: true,
8
+ restoreMocks: true,
9
+ verbose: true
10
+ };
package/package.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "@vangbanlanhat/fca-unofficial",
3
+ "version": "1.4.2",
4
+ "main": "src/index.js",
5
+ "description": "A Facebook chat API that doesn't rely on XMPP. Will NOT be deprecated after April 30th 2015.",
6
+ "scripts": {
7
+ "test": "jest --runInBand --testPathIgnorePatterns=\"/test/integration/\"",
8
+ "test:unit": "jest --runInBand",
9
+ "test:integration": "jest --runInBand --testPathPattern=\"test/integration\"",
10
+ "lint": "eslint \"src/**/*.js\" && eslint --env jest \"test/**/*.js\"",
11
+ "prettier": "prettier \"src/**/*.js\" \"test/**/*.js\" --write"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/VangBanLaNhat/fca-unofficial"
16
+ },
17
+ "keywords": [
18
+ "facebook",
19
+ "chat",
20
+ "api",
21
+ "fca"
22
+ ],
23
+ "bugs": {
24
+ "url": "https://github.com/VangBanLaNhat/fca-unofficial/issues"
25
+ },
26
+ "author": "Avery, David, Maude, Benjamin, UIRI, HerokeyVN",
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "bluebird": "^2.11.0",
30
+ "cheerio": "^0.22.0",
31
+ "https-proxy-agent": "^4.0.0",
32
+
33
+ "mqtt": "^3.0.0",
34
+ "npmlog": "^1.2.1",
35
+ "request": "^2.88.2",
36
+ "websocket-stream": "^5.5.2"
37
+ },
38
+ "pnpm": {
39
+ "overrides": {
40
+ "request@2.88.2>form-data": "2.5.5"
41
+ }
42
+ },
43
+ "engines": {
44
+ "node": ">=22.0.0"
45
+ },
46
+ "devDependencies": {
47
+ "dotenv": "^16.6.1",
48
+ "eslint": "^7.32.0",
49
+ "jest": "^27.5.1",
50
+ "prettier": "^1.19.1"
51
+ },
52
+ "eslintConfig": {
53
+ "env": {
54
+ "es6": true,
55
+ "es2017": true,
56
+ "node": true
57
+ },
58
+ "extends": "eslint:recommended",
59
+ "parserOptions": {
60
+ "sourceType": "module"
61
+ },
62
+ "rules": {
63
+ "linebreak-style": [
64
+ "error",
65
+ "unix"
66
+ ],
67
+ "semi": [
68
+ "error",
69
+ "always"
70
+ ],
71
+ "no-unused-vars": [
72
+ 1,
73
+ {
74
+ "argsIgnorePattern": "^_",
75
+ "varsIgnorePattern": "^_"
76
+ }
77
+ ],
78
+ "no-empty": [
79
+ "error",
80
+ {
81
+ "allowEmptyCatch": true
82
+ }
83
+ ]
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,3 @@
1
+ onlyBuiltDependencies:
2
+ - koffi
3
+ - meta-messenger.js
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+
5
+ module.exports = function(defaultFuncs, api, ctx) {
6
+ return function addExternalModule(moduleObj, callback) {
7
+ var done = typeof callback === "function" ? callback : null;
8
+
9
+ if (utils.getType(moduleObj) == "Object") {
10
+ for (let apiName in moduleObj) {
11
+ if (
12
+ utils.getType(moduleObj[apiName]) == "Function" ||
13
+ utils.getType(moduleObj[apiName]) == "AsyncFunction"
14
+ ) {
15
+ api[apiName] = moduleObj[apiName](defaultFuncs, api, ctx);
16
+ } else {
17
+ var err = new Error(`Item "${apiName}" in moduleObj must be a function, not ${utils.getType(moduleObj[apiName])}!`);
18
+ if (done) done(err);
19
+ throw err;
20
+ }
21
+ }
22
+ } else {
23
+ var typeErr = new Error(`moduleObj must be an object, not ${utils.getType(moduleObj)}!`);
24
+ if (done) done(typeErr);
25
+ throw typeErr;
26
+ }
27
+
28
+ if (done) {
29
+ done(null, true);
30
+ }
31
+
32
+ return true;
33
+ };
34
+ };
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+
6
+ module.exports = function(defaultFuncs, api, ctx) {
7
+ return function addUserToGroup(userID, threadID, callback) {
8
+ var resolveFunc = function(){};
9
+ var rejectFunc = function(){};
10
+ var returnPromise = new Promise(function (resolve, reject) {
11
+ resolveFunc = resolve;
12
+ rejectFunc = reject;
13
+ });
14
+
15
+ if (
16
+ !callback &&
17
+ (utils.getType(threadID) === "Function" ||
18
+ utils.getType(threadID) === "AsyncFunction")
19
+ ) {
20
+ throw { error: "please pass a threadID as a second argument." };
21
+ }
22
+
23
+ if (!callback) {
24
+ callback = function(err) {
25
+ if (err) {
26
+ return rejectFunc(err);
27
+ }
28
+ resolveFunc();
29
+ };
30
+ }
31
+
32
+ if (
33
+ utils.getType(threadID) !== "Number" &&
34
+ utils.getType(threadID) !== "String"
35
+ ) {
36
+ throw {
37
+ error:
38
+ "ThreadID should be of type Number or String and not " +
39
+ utils.getType(threadID) +
40
+ "."
41
+ };
42
+ }
43
+
44
+ if (utils.getType(userID) !== "Array") {
45
+ userID = [userID];
46
+ }
47
+
48
+ var messageAndOTID = utils.generateOfflineThreadingID();
49
+ var form = {
50
+ client: "mercury",
51
+ action_type: "ma-type:log-message",
52
+ author: "fbid:" + ctx.userID,
53
+ thread_id: "",
54
+ timestamp: Date.now(),
55
+ timestamp_absolute: "Today",
56
+ timestamp_relative: utils.generateTimestampRelative(),
57
+ timestamp_time_passed: "0",
58
+ is_unread: false,
59
+ is_cleared: false,
60
+ is_forward: false,
61
+ is_filtered_content: false,
62
+ is_filtered_content_bh: false,
63
+ is_filtered_content_account: false,
64
+ is_spoof_warning: false,
65
+ source: "source:chat:web",
66
+ "source_tags[0]": "source:chat",
67
+ log_message_type: "log:subscribe",
68
+ status: "0",
69
+ offline_threading_id: messageAndOTID,
70
+ message_id: messageAndOTID,
71
+ threading_id: utils.generateThreadingID(ctx.clientID),
72
+ manual_retry_cnt: "0",
73
+ thread_fbid: threadID
74
+ };
75
+
76
+ for (var i = 0; i < userID.length; i++) {
77
+ if (
78
+ utils.getType(userID[i]) !== "Number" &&
79
+ utils.getType(userID[i]) !== "String"
80
+ ) {
81
+ throw {
82
+ error:
83
+ "Elements of userID should be of type Number or String and not " +
84
+ utils.getType(userID[i]) +
85
+ "."
86
+ };
87
+ }
88
+
89
+ form["log_message_data[added_participants][" + i + "]"] =
90
+ "fbid:" + userID[i];
91
+ }
92
+
93
+ defaultFuncs
94
+ .post("https://www.facebook.com/messaging/send/", ctx.jar, form)
95
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
96
+ .then(function(resData) {
97
+ if (!resData) {
98
+ throw { error: "Add to group failed." };
99
+ }
100
+ if (resData.error) {
101
+ throw resData;
102
+ }
103
+
104
+ return callback();
105
+ })
106
+ .catch(function(err) {
107
+ log.error("addUserToGroup", err);
108
+ return callback(err);
109
+ });
110
+
111
+ return returnPromise;
112
+ };
113
+ };
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+
3
+ const utils = require("../utils");
4
+ const log = require("npmlog");
5
+
6
+ module.exports = function(defaultFuncs, api, ctx) {
7
+ return function changeAdminStatus(threadID, adminIDs, adminStatus, callback) {
8
+ if (utils.getType(threadID) !== "String") {
9
+ throw {error: "changeAdminStatus: threadID must be a string"};
10
+ }
11
+
12
+ if (utils.getType(adminIDs) === "String") {
13
+ adminIDs = [adminIDs];
14
+ }
15
+
16
+ if (utils.getType(adminIDs) !== "Array") {
17
+ throw {error: "changeAdminStatus: adminIDs must be an array or string"};
18
+ }
19
+
20
+ if (utils.getType(adminStatus) !== "Boolean") {
21
+ throw {error: "changeAdminStatus: adminStatus must be a string"};
22
+ }
23
+
24
+ var resolveFunc = function(){};
25
+ var rejectFunc = function(){};
26
+ var returnPromise = new Promise(function (resolve, reject) {
27
+ resolveFunc = resolve;
28
+ rejectFunc = reject;
29
+ });
30
+
31
+ if (!callback) {
32
+ callback = function (err) {
33
+ if (err) {
34
+ return rejectFunc(err);
35
+ }
36
+ resolveFunc();
37
+ };
38
+ }
39
+
40
+ if (utils.getType(callback) !== "Function" && utils.getType(callback) !== "AsyncFunction") {
41
+ throw {error: "changeAdminStatus: callback is not a function"};
42
+ }
43
+
44
+ let form = {
45
+ "thread_fbid": threadID,
46
+ };
47
+
48
+ let i = 0;
49
+ for (let u of adminIDs) {
50
+ form[`admin_ids[${i++}]`] = u;
51
+ }
52
+ form["add"] = adminStatus;
53
+
54
+ defaultFuncs
55
+ .post("https://www.facebook.com/messaging/save_admins/?dpr=1", ctx.jar, form)
56
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
57
+ .then(function(resData) {
58
+ if (resData.error) {
59
+ switch (resData.error) {
60
+ case 1976004:
61
+ throw { error: "Cannot alter admin status: you are not an admin.", rawResponse: resData };
62
+ case 1357031:
63
+ throw { error: "Cannot alter admin status: this thread is not a group chat.", rawResponse: resData };
64
+ default:
65
+ throw { error: "Cannot alter admin status: unknown error.", rawResponse: resData };
66
+ }
67
+ }
68
+
69
+ callback();
70
+ })
71
+ .catch(function(err) {
72
+ log.error("changeAdminStatus", err);
73
+ return callback(err);
74
+ });
75
+
76
+ return returnPromise;
77
+ };
78
+ };
79
+
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+
6
+ module.exports = function(defaultFuncs, api, ctx) {
7
+ return function changeArchivedStatus(threadOrThreads, archive, callback) {
8
+ var resolveFunc = function(){};
9
+ var rejectFunc = function(){};
10
+ var returnPromise = new Promise(function (resolve, reject) {
11
+ resolveFunc = resolve;
12
+ rejectFunc = reject;
13
+ });
14
+
15
+ if (!callback) {
16
+ callback = function(err) {
17
+ if (err) {
18
+ return rejectFunc(err);
19
+ }
20
+ resolveFunc();
21
+ };
22
+ }
23
+
24
+ var form = {};
25
+
26
+ if (utils.getType(threadOrThreads) === "Array") {
27
+ for (var i = 0; i < threadOrThreads.length; i++) {
28
+ form["ids[" + threadOrThreads[i] + "]"] = archive;
29
+ }
30
+ } else {
31
+ form["ids[" + threadOrThreads + "]"] = archive;
32
+ }
33
+
34
+ defaultFuncs
35
+ .post(
36
+ "https://www.facebook.com/ajax/mercury/change_archived_status.php",
37
+ ctx.jar,
38
+ form
39
+ )
40
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
41
+ .then(function(resData) {
42
+ if (resData.error) {
43
+ throw resData;
44
+ }
45
+
46
+ return callback();
47
+ })
48
+ .catch(function(err) {
49
+ log.error("changeArchivedStatus", err);
50
+ return callback(err);
51
+ });
52
+
53
+ return returnPromise;
54
+ };
55
+ };
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+
3
+ var utils = require("../utils");
4
+ var log = require("npmlog");
5
+
6
+ module.exports = function (defaultFuncs, api, ctx) {
7
+ return function changeBio(bio, publish, callback) {
8
+ var resolveFunc = function () { };
9
+ var rejectFunc = function () { };
10
+ var returnPromise = new Promise(function (resolve, reject) {
11
+ resolveFunc = resolve;
12
+ rejectFunc = reject;
13
+ });
14
+
15
+ if (!callback) {
16
+ if (utils.getType(publish) == "Function" || utils.getType(publish) == "AsyncFunction") {
17
+ callback = publish;
18
+ } else {
19
+ callback = function (err) {
20
+ if (err) {
21
+ return rejectFunc(err);
22
+ }
23
+ resolveFunc();
24
+ };
25
+ }
26
+ }
27
+
28
+ if (utils.getType(publish) != "Boolean") {
29
+ publish = false;
30
+ }
31
+
32
+ if (utils.getType(bio) != "String") {
33
+ bio = "";
34
+ publish = false;
35
+ }
36
+
37
+ var form = {
38
+ fb_api_caller_class: "RelayModern",
39
+ fb_api_req_friendly_name: "ProfileCometSetBioMutation",
40
+ // This doc_is is valid as of May 23, 2020
41
+ doc_id: "2725043627607610",
42
+ variables: JSON.stringify({
43
+ input: {
44
+ bio: bio,
45
+ publish_bio_feed_story: publish,
46
+ actor_id: ctx.userID,
47
+ client_mutation_id: Math.round(Math.random() * 1024).toString()
48
+ },
49
+ hasProfileTileViewID: false,
50
+ profileTileViewID: null,
51
+ scale: 1
52
+ }),
53
+ av: ctx.userID
54
+ };
55
+
56
+ defaultFuncs
57
+ .post(
58
+ "https://www.facebook.com/api/graphql/",
59
+ ctx.jar,
60
+ form
61
+ )
62
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
63
+ .then(function (resData) {
64
+ if (resData.errors) {
65
+ throw resData;
66
+ }
67
+
68
+ return callback();
69
+ })
70
+ .catch(function (err) {
71
+ log.error("changeBio", err);
72
+ return callback(err);
73
+ });
74
+
75
+ return returnPromise;
76
+ };
77
+ };