fca-orion-api 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/config.js +5 -0
- package/data/fcaVersion.json +0 -0
- package/index.js +417 -0
- package/instantUpdate.js +40 -0
- package/package.json +30 -0
- package/src/addExternalModule.js +19 -0
- package/src/addUserToGroup.js +113 -0
- package/src/changeAdminStatus.js +79 -0
- package/src/changeArchivedStatus.js +55 -0
- package/src/changeAvatar.js +126 -0
- package/src/changeBio.js +77 -0
- package/src/changeBlockedStatus.js +47 -0
- package/src/changeGroupImage.js +132 -0
- package/src/changeNickname.js +59 -0
- package/src/changeThreadColor.js +65 -0
- package/src/changeThreadEmoji.js +55 -0
- package/src/createNewGroup.js +86 -0
- package/src/createPoll.js +71 -0
- package/src/deleteMessage.js +56 -0
- package/src/deleteThread.js +56 -0
- package/src/forwardAttachment.js +60 -0
- package/src/getCurrentUserID.js +7 -0
- package/src/getEmojiUrl.js +29 -0
- package/src/getFriendsList.js +83 -0
- package/src/getMessage.js +796 -0
- package/src/getThreadHistory.js +666 -0
- package/src/getThreadInfo.js +232 -0
- package/src/getThreadList.js +241 -0
- package/src/getThreadPictures.js +79 -0
- package/src/getUserID.js +66 -0
- package/src/getUserInfo.js +74 -0
- package/src/handleFriendRequest.js +61 -0
- package/src/handleMessageRequest.js +65 -0
- package/src/httpGet.js +57 -0
- package/src/httpPost.js +57 -0
- package/src/httpPostFormData.js +63 -0
- package/src/listenMqtt.js +853 -0
- package/src/logout.js +75 -0
- package/src/markAsDelivered.js +58 -0
- package/src/markAsRead.js +80 -0
- package/src/markAsReadAll.js +50 -0
- package/src/markAsSeen.js +59 -0
- package/src/muteThread.js +52 -0
- package/src/refreshFb_dtsg.js +81 -0
- package/src/removeUserFromGroup.js +79 -0
- package/src/resolvePhotoUrl.js +45 -0
- package/src/searchForThread.js +53 -0
- package/src/sendMessage.js +477 -0
- package/src/sendTypingIndicator.js +103 -0
- package/src/setMessageReaction.js +121 -0
- package/src/setPostReaction.js +109 -0
- package/src/setTitle.js +86 -0
- package/src/threadColors.js +131 -0
- package/src/unfriend.js +52 -0
- package/src/unsendMessage.js +49 -0
- package/src/uploadAttachment.js +95 -0
- package/utils.js +1545 -0
package/config.js
ADDED
File without changes
|
package/index.js
ADDED
@@ -0,0 +1,417 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
const utils = require("./utils");
|
4
|
+
const log = require("npmlog");
|
5
|
+
const fs = require('fs');
|
6
|
+
const gradient = require("gradient-string");
|
7
|
+
|
8
|
+
const checkVerified = null;
|
9
|
+
|
10
|
+
const defaultLogRecordSize = 100;
|
11
|
+
log.maxRecordSize = defaultLogRecordSize;
|
12
|
+
|
13
|
+
const chalk = require('chalk');
|
14
|
+
|
15
|
+
const error = chalk.bold.red;
|
16
|
+
const warning = chalk.hex('#FFA500');
|
17
|
+
const success = chalk.greenBright;
|
18
|
+
|
19
|
+
const configContent = `
|
20
|
+
module.exports = {
|
21
|
+
MainName: "[ test ]",
|
22
|
+
AutoUpdate: true
|
23
|
+
};
|
24
|
+
`;
|
25
|
+
|
26
|
+
const configPath = 'config.js';
|
27
|
+
|
28
|
+
if (!fs.existsSync(configPath)) {
|
29
|
+
fs.writeFileSync(configPath, configContent);
|
30
|
+
}
|
31
|
+
|
32
|
+
const { MainName } = configPath;
|
33
|
+
const InstantUpdate = require('./instantUpdate.js');
|
34
|
+
|
35
|
+
function setOptions(globalOptions, options) {
|
36
|
+
Object.keys(options).map(function (key) {
|
37
|
+
switch (key) {
|
38
|
+
case 'online':
|
39
|
+
globalOptions.online = Boolean(options.online);
|
40
|
+
break;
|
41
|
+
case 'logLevel':
|
42
|
+
log.level = options.logLevel;
|
43
|
+
globalOptions.logLevel = options.logLevel;
|
44
|
+
break;
|
45
|
+
case 'logRecordSize':
|
46
|
+
log.maxRecordSize = options.logRecordSize;
|
47
|
+
globalOptions.logRecordSize = options.logRecordSize;
|
48
|
+
break;
|
49
|
+
case 'selfListen':
|
50
|
+
globalOptions.selfListen = Boolean(options.selfListen);
|
51
|
+
break;
|
52
|
+
case 'selfListenEvent':
|
53
|
+
globalOptions.selfListenEvent = options.selfListenEvent;
|
54
|
+
break;
|
55
|
+
case 'listenEvents':
|
56
|
+
globalOptions.listenEvents = Boolean(options.listenEvents);
|
57
|
+
break;
|
58
|
+
case 'pageID':
|
59
|
+
globalOptions.pageID = options.pageID.toString();
|
60
|
+
break;
|
61
|
+
case 'updatePresence':
|
62
|
+
globalOptions.updatePresence = Boolean(options.updatePresence);
|
63
|
+
break;
|
64
|
+
case 'forceLogin':
|
65
|
+
globalOptions.forceLogin = Boolean(options.forceLogin);
|
66
|
+
break;
|
67
|
+
case 'userAgent':
|
68
|
+
globalOptions.userAgent = options.userAgent;
|
69
|
+
break;
|
70
|
+
case 'autoMarkDelivery':
|
71
|
+
globalOptions.autoMarkDelivery = Boolean(options.autoMarkDelivery);
|
72
|
+
break;
|
73
|
+
case 'autoMarkRead':
|
74
|
+
globalOptions.autoMarkRead = Boolean(options.autoMarkRead);
|
75
|
+
break;
|
76
|
+
case 'listenTyping':
|
77
|
+
globalOptions.listenTyping = Boolean(options.listenTyping);
|
78
|
+
break;
|
79
|
+
case 'proxy':
|
80
|
+
if (typeof options.proxy != "string") {
|
81
|
+
delete globalOptions.proxy;
|
82
|
+
utils.setProxy();
|
83
|
+
} else {
|
84
|
+
globalOptions.proxy = options.proxy;
|
85
|
+
utils.setProxy(globalOptions.proxy);
|
86
|
+
}
|
87
|
+
break;
|
88
|
+
case 'autoReconnect':
|
89
|
+
globalOptions.autoReconnect = Boolean(options.autoReconnect);
|
90
|
+
break;
|
91
|
+
case 'emitReady':
|
92
|
+
globalOptions.emitReady = Boolean(options.emitReady);
|
93
|
+
break;
|
94
|
+
default:
|
95
|
+
console.log(gradient('orange', 'yellow')('setOptions') + chalk.warning("Unrecognized option given to setOptions: " + key));
|
96
|
+
break;
|
97
|
+
}
|
98
|
+
});
|
99
|
+
}
|
100
|
+
|
101
|
+
function buildAPI(globalOptions, html, jar) {
|
102
|
+
const maybeCookie = jar.getCookies("https://www.facebook.com").filter(function (val) {
|
103
|
+
return val.cookieString().split("=")[0] === "c_user";
|
104
|
+
});
|
105
|
+
|
106
|
+
const objCookie = jar.getCookies("https://www.facebook.com").reduce(function (obj, val) {
|
107
|
+
obj[val.cookieString().split("=")[0]] = val.cookieString().split("=")[1];
|
108
|
+
return obj;
|
109
|
+
}, {});
|
110
|
+
|
111
|
+
if (maybeCookie.length === 0) {
|
112
|
+
throw { error: "Error retrieving userID. This can be caused by a lot of things, including getting blocked by Facebook for logging in from an unknown location. Try logging in with a browser to verify." };
|
113
|
+
}
|
114
|
+
|
115
|
+
if (html.indexOf("/checkpoint/block/?next") > -1) {
|
116
|
+
console.log(warning("Checkpoint detected. Please log in with a browser to verify."));
|
117
|
+
}
|
118
|
+
|
119
|
+
console.log(gradient('orange', 'yellow').multiline(["▒█▀▄▒█▀▄░▄▀▄░░▒█▒██▀░▄▀▀░▀█▀░░░▄▀▄▒█▀▄░█░▄▀▄░█▄░█", "░█▀▒░█▀▄░▀▄▀░▀▄█░█▄▄░▀▄▄░▒█▒▒░░▀▄▀░█▀▄░█░▀▄▀░█▒▀█",].join('\n')));
|
120
|
+
console.log('');
|
121
|
+
|
122
|
+
const userID = maybeCookie[0].cookieString().split("=")[1].toString();
|
123
|
+
const i_userID = objCookie.i_user || null;
|
124
|
+
const localVersion = require('../package.json').version;
|
125
|
+
console.log(gradient('orange', 'yellow')(`${MainName || "[ FCA-ORION ]"}`) + chalk.white(` Logged in as ${userID}`));
|
126
|
+
console.log(gradient('orange', 'yellow')(`${MainName || "[ FCA-ORION ]"}`) + chalk.white(` The version of FCA-ORION you currently have is`) + chalk.greenBright(` ${localVersion}`));
|
127
|
+
|
128
|
+
try {
|
129
|
+
clearInterval(checkVerified);
|
130
|
+
} catch (_) { }
|
131
|
+
|
132
|
+
const clientID = (Math.random() * 2147483648 | 0).toString(16);
|
133
|
+
|
134
|
+
|
135
|
+
const oldFBMQTTMatch = html.match(/irisSeqID:"(.+?)",appID:219994525426954,endpoint:"(.+?)"/);
|
136
|
+
let mqttEndpoint = null;
|
137
|
+
let region = null;
|
138
|
+
let irisSeqID = null;
|
139
|
+
let noMqttData = null;
|
140
|
+
|
141
|
+
if (oldFBMQTTMatch) {
|
142
|
+
irisSeqID = oldFBMQTTMatch[1];
|
143
|
+
mqttEndpoint = oldFBMQTTMatch[2];
|
144
|
+
region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
|
145
|
+
console.log(gradient('orange', 'yellow')(`${MainName || "[ FCA-ORION ]"}`) + chalk.white(` Got this account's message region: ${region}`));
|
146
|
+
} else {
|
147
|
+
const newFBMQTTMatch = html.match(/{"app_id":"219994525426954","endpoint":"(.+?)","iris_seq_id":"(.+?)"}/);
|
148
|
+
if (newFBMQTTMatch) {
|
149
|
+
irisSeqID = newFBMQTTMatch[2];
|
150
|
+
mqttEndpoint = newFBMQTTMatch[1].replace(/\\\//g, "/");
|
151
|
+
region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
|
152
|
+
console.log(gradient('orange', 'yellow')(`${MainName || "[ FCA-ORION ]"}`) + chalk.white(` Got this account's message region: ${region}`));
|
153
|
+
} else {
|
154
|
+
const legacyFBMQTTMatch = html.match(/(\["MqttWebConfig",\[\],{fbid:")(.+?)(",appID:219994525426954,endpoint:")(.+?)(",pollingEndpoint:")(.+?)(3790])/);
|
155
|
+
if (legacyFBMQTTMatch) {
|
156
|
+
mqttEndpoint = legacyFBMQTTMatch[4];
|
157
|
+
region = new URL(mqttEndpoint).searchParams.get("region").toUpperCase();
|
158
|
+
console.log(warning('Cannot get sequence ID with new RegExp. Fallback to old RegExp (without seqID)...'));
|
159
|
+
console.log(gradient('orange', 'yellow')(`${MainName || "[ FCA-ORION ]"}`) + chalk.white(` Got this account's message region: ${region}`));
|
160
|
+
console.log(gradient('orange', 'yellow')(`${MainName || "[ FCA-ORION ]"}`) + chalk.white(` [Unused] Polling endpoint: ${legacyFBMQTTMatch[6]}`));
|
161
|
+
} else {
|
162
|
+
console.log(warning('Cannot get MQTT region & sequence ID.'));
|
163
|
+
noMqttData = html;
|
164
|
+
}
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
// All data available to api functions
|
169
|
+
const ctx = {
|
170
|
+
userID: userID,
|
171
|
+
i_userID: i_userID,
|
172
|
+
jar: jar,
|
173
|
+
clientID: clientID,
|
174
|
+
globalOptions: globalOptions,
|
175
|
+
loggedIn: true,
|
176
|
+
access_token: 'NONE',
|
177
|
+
clientMutationId: 0,
|
178
|
+
mqttClient: undefined,
|
179
|
+
lastSeqId: irisSeqID,
|
180
|
+
syncToken: undefined,
|
181
|
+
mqttEndpoint,
|
182
|
+
region,
|
183
|
+
firstListen: true
|
184
|
+
};
|
185
|
+
|
186
|
+
const api = {
|
187
|
+
setOptions: setOptions.bind(null, globalOptions),
|
188
|
+
getAppState: function getAppState() {
|
189
|
+
const appState = utils.getAppState(jar);
|
190
|
+
// filter duplicate
|
191
|
+
return appState.filter((item, index, self) => self.findIndex((t) => { return t.key === item.key; }) === index);
|
192
|
+
}
|
193
|
+
};
|
194
|
+
|
195
|
+
if (noMqttData) {
|
196
|
+
api["htmlData"] = noMqttData;
|
197
|
+
}
|
198
|
+
|
199
|
+
const apiFuncNames = [
|
200
|
+
'addExternalModule',
|
201
|
+
'addUserToGroup',
|
202
|
+
'changeAdminStatus',
|
203
|
+
'changeArchivedStatus',
|
204
|
+
'changeAvatar',
|
205
|
+
'changeBio',
|
206
|
+
'changeBlockedStatus',
|
207
|
+
'changeGroupImage',
|
208
|
+
'changeNickname',
|
209
|
+
'changeThreadColor',
|
210
|
+
'changeThreadEmoji',
|
211
|
+
'createNewGroup',
|
212
|
+
'createPoll',
|
213
|
+
'deleteMessage',
|
214
|
+
'deleteThread',
|
215
|
+
'forwardAttachment',
|
216
|
+
'getCurrentUserID',
|
217
|
+
'getEmojiUrl',
|
218
|
+
'getFriendsList',
|
219
|
+
'getMessage',
|
220
|
+
'getThreadHistory',
|
221
|
+
'getThreadInfo',
|
222
|
+
'getThreadList',
|
223
|
+
'getThreadPictures',
|
224
|
+
'getUserID',
|
225
|
+
'getUserInfo',
|
226
|
+
'handleMessageRequest',
|
227
|
+
'listenMqtt',
|
228
|
+
'logout',
|
229
|
+
'markAsDelivered',
|
230
|
+
'markAsRead',
|
231
|
+
'markAsReadAll',
|
232
|
+
'markAsSeen',
|
233
|
+
'muteThread',
|
234
|
+
'refreshFb_dtsg',
|
235
|
+
'removeUserFromGroup',
|
236
|
+
'resolvePhotoUrl',
|
237
|
+
'searchForThread',
|
238
|
+
'sendMessage',
|
239
|
+
'sendTypingIndicator',
|
240
|
+
'setMessageReaction',
|
241
|
+
'setPostReaction',
|
242
|
+
'setTitle',
|
243
|
+
'threadColors',
|
244
|
+
'unsendMessage',
|
245
|
+
'unfriend',
|
246
|
+
|
247
|
+
// HTTP
|
248
|
+
'httpGet',
|
249
|
+
'httpPost',
|
250
|
+
'httpPostFormData',
|
251
|
+
|
252
|
+
'uploadAttachment'
|
253
|
+
];
|
254
|
+
|
255
|
+
const defaultFuncs = utils.makeDefaults(html, i_userID || userID, ctx);
|
256
|
+
|
257
|
+
// Load all api functions in a loop
|
258
|
+
apiFuncNames.map(function (v) {
|
259
|
+
api[v] = require('./src/' + v)(defaultFuncs, api, ctx);
|
260
|
+
});
|
261
|
+
|
262
|
+
//Removing original `listen` that uses pull.
|
263
|
+
//Map it to listenMqtt instead for backward compatibly.
|
264
|
+
api.listen = api.listenMqtt;
|
265
|
+
|
266
|
+
return [ctx, defaultFuncs, api];
|
267
|
+
}
|
268
|
+
|
269
|
+
// Helps the login
|
270
|
+
function loginHelper(appState, email, password, globalOptions, callback, prCallback) {
|
271
|
+
let mainPromise = null;
|
272
|
+
const jar = utils.getJar();
|
273
|
+
|
274
|
+
// If we're given an appState we loop through it and save each cookie
|
275
|
+
// back into the jar.
|
276
|
+
if (appState) {
|
277
|
+
// check and convert cookie to appState
|
278
|
+
if (utils.getType(appState) === 'Array' && appState.some(c => c.name)) {
|
279
|
+
appState = appState.map(c => {
|
280
|
+
c.key = c.name;
|
281
|
+
delete c.name;
|
282
|
+
return c;
|
283
|
+
});
|
284
|
+
}
|
285
|
+
else if (utils.getType(appState) === 'String') {
|
286
|
+
const arrayAppState = [];
|
287
|
+
appState.split(';').forEach(c => {
|
288
|
+
const [key, value] = c.split('=');
|
289
|
+
|
290
|
+
arrayAppState.push({
|
291
|
+
key: (key || "").trim(),
|
292
|
+
value: (value || "").trim(),
|
293
|
+
domain: "facebook.com",
|
294
|
+
path: "/",
|
295
|
+
expires: new Date().getTime() + 1000 * 60 * 60 * 24 * 365
|
296
|
+
});
|
297
|
+
});
|
298
|
+
appState = arrayAppState;
|
299
|
+
}
|
300
|
+
|
301
|
+
appState.map(function (c) {
|
302
|
+
const str = c.key + "=" + c.value + "; expires=" + c.expires + "; domain=" + c.domain + "; path=" + c.path + ";";
|
303
|
+
jar.setCookie(str, "http://" + c.domain);
|
304
|
+
});
|
305
|
+
|
306
|
+
// Load the main page.
|
307
|
+
mainPromise = utils
|
308
|
+
.get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true })
|
309
|
+
.then(utils.saveCookies(jar));
|
310
|
+
} else {
|
311
|
+
if (email) {
|
312
|
+
throw { error: "Currently, the login method by email and password is no longer supported, please use the login method by appState" };
|
313
|
+
}
|
314
|
+
else {
|
315
|
+
throw { error: "No appState given." };
|
316
|
+
}
|
317
|
+
}
|
318
|
+
|
319
|
+
let ctx = null;
|
320
|
+
let _defaultFuncs = null;
|
321
|
+
let api = null;
|
322
|
+
|
323
|
+
mainPromise = mainPromise
|
324
|
+
.then(function (res) {
|
325
|
+
// Hacky check for the redirection that happens on some ISPs, which doesn't return statusCode 3xx
|
326
|
+
const reg = /<meta http-equiv="refresh" content="0;url=([^"]+)[^>]+>/;
|
327
|
+
const redirect = reg.exec(res.body);
|
328
|
+
if (redirect && redirect[1]) {
|
329
|
+
return utils
|
330
|
+
.get(redirect[1], jar, null, globalOptions)
|
331
|
+
.then(utils.saveCookies(jar));
|
332
|
+
}
|
333
|
+
return res;
|
334
|
+
})
|
335
|
+
.then(function (res) {
|
336
|
+
const html = res.body;
|
337
|
+
const stuff = buildAPI(globalOptions, html, jar);
|
338
|
+
ctx = stuff[0];
|
339
|
+
_defaultFuncs = stuff[1];
|
340
|
+
api = stuff[2];
|
341
|
+
return res;
|
342
|
+
});
|
343
|
+
|
344
|
+
// given a pageID we log in as a page
|
345
|
+
if (globalOptions.pageID) {
|
346
|
+
mainPromise = mainPromise
|
347
|
+
.then(function () {
|
348
|
+
return utils
|
349
|
+
.get('https://www.facebook.com/' + ctx.globalOptions.pageID + '/messages/?section=messages&subsection=inbox', ctx.jar, null, globalOptions);
|
350
|
+
})
|
351
|
+
.then(function (resData) {
|
352
|
+
let url = utils.getFrom(resData.body, 'window.location.replace("https:\\/\\/www.facebook.com\\', '");').split('\\').join('');
|
353
|
+
url = url.substring(0, url.length - 1);
|
354
|
+
|
355
|
+
return utils
|
356
|
+
.get('https://www.facebook.com' + url, ctx.jar, null, globalOptions);
|
357
|
+
});
|
358
|
+
}
|
359
|
+
|
360
|
+
// At the end we call the callback or catch an exception
|
361
|
+
mainPromise
|
362
|
+
.then(function () {
|
363
|
+
console.log(gradient('orange', 'yellow')(`${MainName || "[ FCA-ORION ]"}`) + chalk.white(` Done logging in.`));
|
364
|
+
return callback(null, api);
|
365
|
+
})
|
366
|
+
.catch(function (e) {
|
367
|
+
console.log(error(e.error || e));
|
368
|
+
callback(e);
|
369
|
+
});
|
370
|
+
}
|
371
|
+
|
372
|
+
function login(loginData, options, callback) {
|
373
|
+
if (utils.getType(options) === 'Function' || utils.getType(options) === 'AsyncFunction') {
|
374
|
+
callback = options;
|
375
|
+
options = {};
|
376
|
+
}
|
377
|
+
|
378
|
+
const globalOptions = {
|
379
|
+
selfListen: false,
|
380
|
+
selfListenEvent: false,
|
381
|
+
listenEvents: false,
|
382
|
+
listenTyping: false,
|
383
|
+
updatePresence: false,
|
384
|
+
forceLogin: false,
|
385
|
+
autoMarkDelivery: true,
|
386
|
+
autoMarkRead: false,
|
387
|
+
autoReconnect: true,
|
388
|
+
logRecordSize: defaultLogRecordSize,
|
389
|
+
online: true,
|
390
|
+
emitReady: false,
|
391
|
+
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/600.3.18 (KHTML, like Gecko) Version/8.0.3 Safari/600.3.18"
|
392
|
+
};
|
393
|
+
|
394
|
+
setOptions(globalOptions, options);
|
395
|
+
|
396
|
+
let prCallback = null;
|
397
|
+
if (utils.getType(callback) !== "Function" && utils.getType(callback) !== "AsyncFunction") {
|
398
|
+
let rejectFunc = null;
|
399
|
+
let resolveFunc = null;
|
400
|
+
var returnPromise = new Promise(function (resolve, reject) {
|
401
|
+
resolveFunc = resolve;
|
402
|
+
rejectFunc = reject;
|
403
|
+
});
|
404
|
+
prCallback = function (error, api) {
|
405
|
+
if (error) {
|
406
|
+
return rejectFunc(error);
|
407
|
+
}
|
408
|
+
return resolveFunc(api);
|
409
|
+
};
|
410
|
+
callback = prCallback;
|
411
|
+
}
|
412
|
+
loginHelper(loginData.appState, loginData.email, loginData.password, globalOptions, callback, prCallback);
|
413
|
+
return returnPromise;
|
414
|
+
}
|
415
|
+
|
416
|
+
InstantUpdate();
|
417
|
+
module.exports = login;
|
package/instantUpdate.js
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module.exports = async function() {
|
2
|
+
const got = require('got');
|
3
|
+
const chalk = require('chalk');
|
4
|
+
const error = chalk.bold.red;
|
5
|
+
const warning = chalk.hex('#FFA500');
|
6
|
+
const success = chalk.greenBright;
|
7
|
+
const { execSync } = require('child_process');
|
8
|
+
const { body } = await got('https://raw.githubusercontent.com/ivancotacte/Global_fca-project-orion/main/InstantAction.json');
|
9
|
+
const json = JSON.parse(body);
|
10
|
+
const LocalVersion = require('./package.json').version;
|
11
|
+
if (Number(LocalVersion.replace(/\./g,"")) < Number(json.Version.replace(/\./g,"")) ) {
|
12
|
+
console.log(warning(`[ FCA-UPDATE ] `) + chalk.white("To avoid errors, update FCA-ORIONS: " + LocalVersion + " -> " + json.Version));
|
13
|
+
console.log(warning(`[ FCA-UPDATE ] `) + chalk.white("Problem Description: " + json.Problem));
|
14
|
+
console.log(warning("[ FCA-UPDATE ] ") + chalk.white("Please contact to owner about update failed and screentshot error log at https://www.facebook.com/icotacteeee"));
|
15
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
16
|
+
try {
|
17
|
+
execSync(`npm install fca-project-orion@${json.Version}`, { stdio: 'inherit' });
|
18
|
+
console.log(success("[ FCA-UPDATE ] ","Update Complete, Restarting..."));
|
19
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
20
|
+
process.exit(1);
|
21
|
+
} catch (err) {
|
22
|
+
try {
|
23
|
+
console.log(error("[ FCA-UPDATE ] ") + chalk.white("Update Failed, Trying Another Method 1..."));
|
24
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
25
|
+
execSync(`npm install fca-project-orion@${json.Version} --force`, { stdio: 'inherit' });
|
26
|
+
console.log(success("[ FCA-UPDATE ] ","Update Complete, Restarting..."));
|
27
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
28
|
+
process.exit(1);
|
29
|
+
} catch (err) {
|
30
|
+
console.log(e);
|
31
|
+
console.log(warning("[ FCA-UPDATE ] ") + chalk.white("Update Failed, Please Update Manually"));
|
32
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
33
|
+
console.log(warning("[ FCA-UPDATE ] ") + chalk.white("Please contact to owner about update failed and screentshot error log at https://www.facebook.com/icotacteeee"));
|
34
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
35
|
+
process.exit(1);
|
36
|
+
}
|
37
|
+
}
|
38
|
+
} else {
|
39
|
+
}
|
40
|
+
}
|
package/package.json
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
{
|
2
|
+
"name": "fca-orion-api",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "",
|
5
|
+
"main": "index.js",
|
6
|
+
"scripts": {
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
8
|
+
},
|
9
|
+
"repository": {
|
10
|
+
"type": "git",
|
11
|
+
"url": "git://github.com/ivancotacte/fca-orion-api.git"
|
12
|
+
},
|
13
|
+
"keywords": [
|
14
|
+
"facebook",
|
15
|
+
"chat",
|
16
|
+
"api",
|
17
|
+
"fca"
|
18
|
+
],
|
19
|
+
"bugs": {
|
20
|
+
"url": "https://github.com/ivancotacte/fca-orion-api/issues"
|
21
|
+
},
|
22
|
+
"author": "Avery, David, Maude, Benjamin, UIRI",
|
23
|
+
"license": "MIT",
|
24
|
+
"dependencies": {
|
25
|
+
"got": "^11.8.6",
|
26
|
+
"gradient-string": "^2.0.2",
|
27
|
+
"npmlog": "^1.2.0",
|
28
|
+
"request": "^2.53.0"
|
29
|
+
}
|
30
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
const utils = require("../utils");
|
4
|
+
|
5
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
6
|
+
return function addExternalModule(moduleObj) {
|
7
|
+
if (utils.getType(moduleObj) == "Object") {
|
8
|
+
for (const apiName in moduleObj) {
|
9
|
+
if (utils.getType(moduleObj[apiName]) == "Function") {
|
10
|
+
api[apiName] = moduleObj[apiName](defaultFuncs, api, ctx);
|
11
|
+
} else {
|
12
|
+
throw new Error(`Item "${apiName}" in moduleObj must be a function, not ${utils.getType(moduleObj[apiName])}!`);
|
13
|
+
}
|
14
|
+
}
|
15
|
+
} else {
|
16
|
+
throw new Error(`moduleObj must be an object, not ${utils.getType(moduleObj)}!`);
|
17
|
+
}
|
18
|
+
};
|
19
|
+
};
|
@@ -0,0 +1,113 @@
|
|
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 addUserToGroup(userID, threadID, callback) {
|
8
|
+
let resolveFunc = function () { };
|
9
|
+
let rejectFunc = function () { };
|
10
|
+
const 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 new utils.CustomError({ 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 new utils.CustomError({
|
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
|
+
const messageAndOTID = utils.generateOfflineThreadingID();
|
49
|
+
const form = {
|
50
|
+
client: "mercury",
|
51
|
+
action_type: "ma-type:log-message",
|
52
|
+
author: "fbid:" + (ctx.i_userID || 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 (let i = 0; i < userID.length; i++) {
|
77
|
+
if (
|
78
|
+
utils.getType(userID[i]) !== "Number" &&
|
79
|
+
utils.getType(userID[i]) !== "String"
|
80
|
+
) {
|
81
|
+
throw new utils.CustomError({
|
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 new utils.CustomError({ error: "Add to group failed." });
|
99
|
+
}
|
100
|
+
if (resData.error) {
|
101
|
+
throw new utils.CustomError(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
|
+
};
|