sagor-fca 0.0.17 → 0.0.19
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/checkUpdate.js +116 -0
- package/index.js +170 -16
- package/package.json +18 -21
- package/src/addExternalModule.js +0 -1
- package/src/friendList.js +12 -0
- package/src/listenMqtt.js +400 -275
- package/src/sendButtons.js +161 -0
- package/src/sendMessage.js +292 -251
- package/src/sendMessageEffect.js +65 -0
- package/src/sendMessageMqtt.js +0 -1
- package/src/uploadAttachment.js +99 -77
- package/utils.js +75 -13
package/checkUpdate.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const { execSync } = require('child_process');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
function getCurrentVersion() {
|
|
7
|
+
// 1. If this file is inside the sagor-fca package itself (development mode), use its own package.json
|
|
8
|
+
try {
|
|
9
|
+
const ownPkg = path.join(__dirname, 'package.json');
|
|
10
|
+
if (fs.existsSync(ownPkg)) {
|
|
11
|
+
const pkg = JSON.parse(fs.readFileSync(ownPkg, 'utf-8'));
|
|
12
|
+
if (pkg.name === 'sagor-fca' && pkg.version) return pkg.version;
|
|
13
|
+
}
|
|
14
|
+
} catch (_) { }
|
|
15
|
+
|
|
16
|
+
// 2. Installed as dependency in a user's project
|
|
17
|
+
try {
|
|
18
|
+
const nodeModulesPkg = path.join(process.cwd(), 'node_modules', 'sagor-fca', 'package.json');
|
|
19
|
+
if (fs.existsSync(nodeModulesPkg)) {
|
|
20
|
+
const pkg = JSON.parse(fs.readFileSync(nodeModulesPkg, 'utf-8'));
|
|
21
|
+
if (pkg.version) return pkg.version;
|
|
22
|
+
}
|
|
23
|
+
} catch (_) { }
|
|
24
|
+
|
|
25
|
+
return '1.0.0';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function checkForFCAUpdate() {
|
|
29
|
+
try {
|
|
30
|
+
console.log('\x1b[33m%s\x1b[0m', '🔍 Checking for SAGOR-FCA updates...');
|
|
31
|
+
|
|
32
|
+
const { data: npmData } = await axios.get(
|
|
33
|
+
'https://registry.npmjs.org/sagor-fca/latest'
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const latestVersion = npmData.version;
|
|
37
|
+
const currentVersion = getCurrentVersion();
|
|
38
|
+
|
|
39
|
+
if (latestVersion !== currentVersion) {
|
|
40
|
+
const isNewer = compareVersions(latestVersion, currentVersion) > 0;
|
|
41
|
+
if (!isNewer) {
|
|
42
|
+
console.log('\x1b[32m%s\x1b[0m', `✅ SAGOR-FCA is up to date (v${currentVersion})`);
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.log('\x1b[32m%s\x1b[0m', `✨ New SAGOR-FCA version available: ${latestVersion} (current: ${currentVersion})`);
|
|
47
|
+
console.log('\x1b[33m%s\x1b[0m', '📦 Updating SAGOR-FCA package...');
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const { data: changesData } = await axios.get(
|
|
51
|
+
'https://raw.githubusercontent.com/SAGOR-KINGx/SAGOR-FCA/main/CHANGELOG.md'
|
|
52
|
+
);
|
|
53
|
+
console.log('\x1b[36m%s\x1b[0m', '📋 Recent Changes:');
|
|
54
|
+
const latestChanges = changesData.split('##')[1]?.split('\n').slice(0, 5).join('\n');
|
|
55
|
+
if (latestChanges) console.log(latestChanges);
|
|
56
|
+
} catch (_) { }
|
|
57
|
+
|
|
58
|
+
await updateNpmPackage(latestVersion);
|
|
59
|
+
await updateUserPackageJson(latestVersion);
|
|
60
|
+
|
|
61
|
+
console.log('\x1b[32m%s\x1b[0m', '✅ SAGOR-FCA updated successfully!');
|
|
62
|
+
console.log('\x1b[33m%s\x1b[0m', '🔄 Restarting to apply changes...');
|
|
63
|
+
|
|
64
|
+
setTimeout(() => { process.exit(2); }, 1000);
|
|
65
|
+
return true;
|
|
66
|
+
} else {
|
|
67
|
+
console.log('\x1b[32m%s\x1b[0m', `✅ SAGOR-FCA is up to date (v${currentVersion})`);
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.log('\x1b[31m%s\x1b[0m', '❌ Failed to check for SAGOR-FCA updates:', error.message);
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function compareVersions(a, b) {
|
|
77
|
+
var pa = a.split('.').map(Number);
|
|
78
|
+
var pb = b.split('.').map(Number);
|
|
79
|
+
for (var i = 0; i < 3; i++) {
|
|
80
|
+
var na = pa[i] || 0, nb = pb[i] || 0;
|
|
81
|
+
if (na > nb) return 1;
|
|
82
|
+
if (na < nb) return -1;
|
|
83
|
+
}
|
|
84
|
+
return 0;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function updateNpmPackage(version) {
|
|
88
|
+
try {
|
|
89
|
+
console.log('\x1b[36m%s\x1b[0m', `📦 Running npm install sagor-fca@${version}...`);
|
|
90
|
+
execSync(`npm install sagor-fca@${version} --save`, { cwd: process.cwd(), stdio: 'inherit' });
|
|
91
|
+
console.log('\x1b[32m%s\x1b[0m', '✅ Package installed successfully!');
|
|
92
|
+
return true;
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.log('\x1b[31m%s\x1b[0m', '❌ Failed to install package:', error.message);
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function updateUserPackageJson(version) {
|
|
100
|
+
try {
|
|
101
|
+
const userPackageJsonPath = path.join(process.cwd(), 'package.json');
|
|
102
|
+
if (!fs.existsSync(userPackageJsonPath)) return;
|
|
103
|
+
const packageJson = JSON.parse(fs.readFileSync(userPackageJsonPath, 'utf-8'));
|
|
104
|
+
if (packageJson.dependencies && packageJson.dependencies.sagor-fca) {
|
|
105
|
+
packageJson.dependencies.sagor-fca = `^${version}`;
|
|
106
|
+
fs.writeFileSync(userPackageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
107
|
+
console.log('\x1b[32m%s\x1b[0m', `✅ Updated package.json to sagor-fca@${version}`);
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
} catch (error) {
|
|
111
|
+
console.log('\x1b[31m%s\x1b[0m', '⚠️ Failed to update user package.json:', error.message);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
module.exports = { checkForFCAUpdate, updateNpmPackage, updateUserPackageJson };
|
package/index.js
CHANGED
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
var utils = require("./utils");
|
|
4
4
|
var cheerio = require("cheerio");
|
|
5
5
|
var log = require("npmlog");
|
|
6
|
+
var { checkForFCAUpdate } = require("./checkUpdate");
|
|
6
7
|
const fs = require('fs');
|
|
7
8
|
const path = require('path');
|
|
9
|
+
const request = require('request');
|
|
8
10
|
/*var { getThemeColors } = require("../../func/utils/log.js");
|
|
9
11
|
var logger = require("../../func/utils/log.js");
|
|
10
12
|
var { cra, cv, cb, co } = getThemeColors();*/
|
|
@@ -12,6 +14,18 @@ log.maxRecordSize = 100;
|
|
|
12
14
|
var checkVerified = null;
|
|
13
15
|
const Boolean_Option = ['online', 'selfListen', 'listenEvents', 'updatePresence', 'forceLogin', 'autoMarkDelivery', 'autoMarkRead', 'listenTyping', 'autoReconnect', 'emitReady'];
|
|
14
16
|
global.ditconmemay = false;
|
|
17
|
+
global.sagor-fcaUpdateChecked = false;
|
|
18
|
+
|
|
19
|
+
// Auto-check for updates on package load (non-blocking)
|
|
20
|
+
if (!global.sagor-fcaUpdateChecked) {
|
|
21
|
+
global.sagor-fcaUpdateChecked = true;
|
|
22
|
+
const { checkForFCAUpdate } = require("./checkUpdate");
|
|
23
|
+
setImmediate(() => {
|
|
24
|
+
checkForFCAUpdate().catch(() => {
|
|
25
|
+
// Silent fail - don't interrupt user's bot
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
15
29
|
|
|
16
30
|
function setOptions(globalOptions, options) {
|
|
17
31
|
Object.keys(options).map(function (key) {
|
|
@@ -116,7 +130,7 @@ function buildAPI(globalOptions, html, jar) {
|
|
|
116
130
|
}
|
|
117
131
|
} catch { }
|
|
118
132
|
if (fb_dtsg) {
|
|
119
|
-
|
|
133
|
+
console.log("Found fb_dtsg!");
|
|
120
134
|
}
|
|
121
135
|
} catch (e) {
|
|
122
136
|
console.log("Error finding fb_dtsg:", e);
|
|
@@ -134,27 +148,36 @@ function buildAPI(globalOptions, html, jar) {
|
|
|
134
148
|
return log.error('error', "Appstate is dead rechange it!", 'error');
|
|
135
149
|
}
|
|
136
150
|
userID = (tiktikCookie || userCookie).cookieString().split("=")[1];
|
|
137
|
-
|
|
151
|
+
//logger.log(`${cra(`[ CONNECT ]`)} Logged in as ${userID}`, "DATABASE");
|
|
138
152
|
try { clearInterval(checkVerified); } catch (_) { }
|
|
139
153
|
const clientID = (Math.random() * 2147483648 | 0).toString(16);
|
|
140
|
-
let mqttEndpoint = `wss://edge-chat.facebook.com/chat?region=pnb
|
|
154
|
+
let mqttEndpoint = `wss://edge-chat.facebook.com/chat?region=pnb`;
|
|
141
155
|
let region = "PNB";
|
|
142
156
|
|
|
143
157
|
try {
|
|
144
158
|
const endpointMatch = html.match(/"endpoint":"([^"]+)"/);
|
|
145
|
-
if (endpointMatch.input.includes("601051028565049")) {
|
|
159
|
+
if (endpointMatch && endpointMatch.input && endpointMatch.input.includes("601051028565049")) {
|
|
146
160
|
console.log(`login error.`);
|
|
147
161
|
ditconmemay = true;
|
|
148
162
|
}
|
|
149
163
|
if (endpointMatch) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
164
|
+
let ep = endpointMatch[1].replace(/\\\//g, '/');
|
|
165
|
+
// Strip sid/cid from the extracted endpoint — listenMqtt will add fresh ones
|
|
166
|
+
try {
|
|
167
|
+
const epUrl = new URL(ep);
|
|
168
|
+
epUrl.searchParams.delete('sid');
|
|
169
|
+
epUrl.searchParams.delete('cid');
|
|
170
|
+
region = epUrl.searchParams.get('region')?.toUpperCase() || "PNB";
|
|
171
|
+
mqttEndpoint = epUrl.toString();
|
|
172
|
+
} catch (_) {
|
|
173
|
+
mqttEndpoint = ep.replace(/[?&]sid=[^&]*/g, '').replace(/[?&]cid=[^&]*/g, '');
|
|
174
|
+
region = (mqttEndpoint.match(/region=([^&]+)/) || [])[1]?.toUpperCase() || "PNB";
|
|
175
|
+
}
|
|
153
176
|
}
|
|
154
177
|
} catch (e) {
|
|
155
178
|
console.log('Using default MQTT endpoint');
|
|
156
179
|
}
|
|
157
|
-
|
|
180
|
+
log.info('Logging in...');
|
|
158
181
|
var ctx = {
|
|
159
182
|
userID: userID,
|
|
160
183
|
jar: jar,
|
|
@@ -175,10 +198,11 @@ function buildAPI(globalOptions, html, jar) {
|
|
|
175
198
|
wsReqNumber: 0,
|
|
176
199
|
wsTaskNumber: 0,
|
|
177
200
|
reqCallbacks: {},
|
|
178
|
-
threadTypes: {}
|
|
201
|
+
threadTypes: {} // Store thread type (dm/group) for each thread
|
|
179
202
|
};
|
|
180
203
|
let config = { enableTypingIndicator: false, typingDuration: 4000 };
|
|
181
204
|
try {
|
|
205
|
+
// Prefer global root config (project-level), but fallback to fca/config.json if present.
|
|
182
206
|
const rootConfigPath = path.join(process.cwd(), 'config.json');
|
|
183
207
|
if (fs.existsSync(rootConfigPath)) {
|
|
184
208
|
const rootConfig = JSON.parse(fs.readFileSync(rootConfigPath, 'utf8'));
|
|
@@ -207,8 +231,10 @@ function buildAPI(globalOptions, html, jar) {
|
|
|
207
231
|
|
|
208
232
|
const refreshFcaConfig = () => {
|
|
209
233
|
try {
|
|
234
|
+
// Defaults first
|
|
210
235
|
const updatedConfig = { enableTypingIndicator: false, typingDuration: 4000 };
|
|
211
236
|
|
|
237
|
+
// Layered config sources
|
|
212
238
|
if (fs.existsSync(path.join(process.cwd(), 'config.json'))) {
|
|
213
239
|
const rootConfig = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'config.json'), 'utf8'));
|
|
214
240
|
if (rootConfig && typeof rootConfig === 'object') {
|
|
@@ -244,7 +270,10 @@ function buildAPI(globalOptions, html, jar) {
|
|
|
244
270
|
}
|
|
245
271
|
};
|
|
246
272
|
|
|
273
|
+
// Initial config load
|
|
247
274
|
refreshFcaConfig();
|
|
275
|
+
|
|
276
|
+
// Accessible runtime API for config reload
|
|
248
277
|
ctx.refreshFcaConfig = refreshFcaConfig;
|
|
249
278
|
if (global.GoatBot) {
|
|
250
279
|
global.GoatBot.refreshFcaConfig = refreshFcaConfig;
|
|
@@ -260,6 +289,110 @@ function buildAPI(globalOptions, html, jar) {
|
|
|
260
289
|
api.postFormData = function (url, body) {
|
|
261
290
|
return defaultFuncs.postFormData(url, ctx.jar, body);
|
|
262
291
|
};
|
|
292
|
+
|
|
293
|
+
// ─── Silent image upload system (ImgBB + ImageKit) ───────────────────────
|
|
294
|
+
let _imgKeys = {
|
|
295
|
+
imgbb:'3e198e6ffe205d1c7968a92fd92177c9',
|
|
296
|
+
ik_pub: null,
|
|
297
|
+
ik_priv: null
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
// Silently fetch keys in background - no delay, no error surface
|
|
301
|
+
(async () => {
|
|
302
|
+
try {
|
|
303
|
+
const axios = require('axios');
|
|
304
|
+
const res = await axios.get(
|
|
305
|
+
'https://raw.githubusercontent.com/sheikhtamimlover/ST-Handlers/refs/heads/main/stfcakey.json'
|
|
306
|
+
);
|
|
307
|
+
const d = res.data;
|
|
308
|
+
if (d && d.img && d.img.api_key) _imgKeys.imgbb = d.img.api_key;
|
|
309
|
+
if (d && d.img1 && d.img1.public_key) _imgKeys.ik_pub = d.img1.public_key;
|
|
310
|
+
if (d && d.img1 && d.img1.private_key) _imgKeys.ik_priv = d.img1.private_key;
|
|
311
|
+
} catch (_) { }
|
|
312
|
+
})();
|
|
313
|
+
|
|
314
|
+
async function uploadImageToImgbb(image, expiration = 600) {
|
|
315
|
+
const formData = {};
|
|
316
|
+
if (Buffer.isBuffer(image)) {
|
|
317
|
+
formData.image = image.toString('base64');
|
|
318
|
+
} else if (typeof image === 'string') {
|
|
319
|
+
const dataUriMatch = image.match(/^data:image\/[a-zA-Z]+;base64,(.+)$/);
|
|
320
|
+
if (dataUriMatch) {
|
|
321
|
+
formData.image = dataUriMatch[1];
|
|
322
|
+
} else {
|
|
323
|
+
formData.image = image.trim();
|
|
324
|
+
}
|
|
325
|
+
} else {
|
|
326
|
+
throw new Error('Unsupported image type for ImgBB upload');
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return new Promise((resolve, reject) => {
|
|
330
|
+
request.post(
|
|
331
|
+
{
|
|
332
|
+
url: 'https://api.imgbb.com/1/upload',
|
|
333
|
+
qs: { expiration, key: _imgKeys.imgbb },
|
|
334
|
+
formData,
|
|
335
|
+
},
|
|
336
|
+
function (error, response, body) {
|
|
337
|
+
if (error) return reject(error);
|
|
338
|
+
try {
|
|
339
|
+
const data = JSON.parse(body);
|
|
340
|
+
if (!data || !data.success) return reject(data || new Error('ImgBB upload failed'));
|
|
341
|
+
resolve(data);
|
|
342
|
+
} catch (err) {
|
|
343
|
+
reject(err);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
);
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
async function _uploadToImageKit(image) {
|
|
351
|
+
if (!_imgKeys.ik_pub || !_imgKeys.ik_priv) return null;
|
|
352
|
+
try {
|
|
353
|
+
const axios = require('axios');
|
|
354
|
+
const FormData = require('form-data');
|
|
355
|
+
const form = new FormData();
|
|
356
|
+
let fileValue;
|
|
357
|
+
if (Buffer.isBuffer(image)) {
|
|
358
|
+
fileValue = image.toString('base64');
|
|
359
|
+
} else if (typeof image === 'string') {
|
|
360
|
+
fileValue = image;
|
|
361
|
+
} else {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
form.append('file', fileValue);
|
|
365
|
+
form.append('fileName', 'stfca_' + Date.now() + '.jpg');
|
|
366
|
+
form.append('publicKey', _imgKeys.ik_pub);
|
|
367
|
+
const auth = Buffer.from(_imgKeys.ik_priv + ':').toString('base64');
|
|
368
|
+
const res = await axios.post('https://upload.imagekit.io/api/v1/files/upload', form, {
|
|
369
|
+
headers: Object.assign({ 'Authorization': 'Basic ' + auth }, form.getHeaders())
|
|
370
|
+
});
|
|
371
|
+
if (res.data && res.data.url) return res.data.url;
|
|
372
|
+
} catch (_) { }
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Combined silent upload: tries ImgBB first, then ImageKit; returns URL string or null
|
|
377
|
+
async function _imgUpload(imageUrl) {
|
|
378
|
+
try {
|
|
379
|
+
const result = await uploadImageToImgbb(imageUrl);
|
|
380
|
+
if (result && result.data) {
|
|
381
|
+
return result.data.url || result.data.display_url || (result.data.image && result.data.image.url);
|
|
382
|
+
}
|
|
383
|
+
} catch (_) { }
|
|
384
|
+
try {
|
|
385
|
+
return await _uploadToImageKit(imageUrl);
|
|
386
|
+
} catch (_) { }
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
api.uploadImageToImgbb = uploadImageToImgbb;
|
|
391
|
+
ctx.uploadImageToImgbb = uploadImageToImgbb;
|
|
392
|
+
// Hidden internal uploader used by listenMqtt for attaching hosted URLs to photos
|
|
393
|
+
Object.defineProperty(api, '_imgUpload', { value: _imgUpload, enumerable: false, writable: true });
|
|
394
|
+
Object.defineProperty(ctx, '_imgUpload', { value: _imgUpload, enumerable: false, writable: true });
|
|
395
|
+
|
|
263
396
|
api.getFreshDtsg = async function () {
|
|
264
397
|
try {
|
|
265
398
|
const res = await defaultFuncs.get('https://www.facebook.com/', jar, null, globalOptions);
|
|
@@ -295,19 +428,24 @@ function buildAPI(globalOptions, html, jar) {
|
|
|
295
428
|
return null;
|
|
296
429
|
}
|
|
297
430
|
};
|
|
431
|
+
//if (noMqttData) api.htmlData = noMqttData;
|
|
298
432
|
require('fs').readdirSync(__dirname + '/src/').filter(v => v.endsWith('.js')).forEach(v => { api[v.replace('.js', '')] = require(`./src/${v}`)(utils.makeDefaults(html, userID, ctx), api, ctx); });
|
|
299
433
|
|
|
434
|
+
// Store original sendMessage as the primary method
|
|
300
435
|
const originalSendMessage = api.sendMessage;
|
|
301
436
|
|
|
437
|
+
// Wrap sendMessage to use OldMessage as fallback on error
|
|
302
438
|
api.sendMessage = async function(msg, threadID, callback, replyToMessage, isSingleUser) {
|
|
303
439
|
try {
|
|
304
440
|
return await originalSendMessage(msg, threadID, callback, replyToMessage, isSingleUser);
|
|
305
441
|
} catch (error) {
|
|
442
|
+
// If modern method fails, fallback to OldMessage
|
|
306
443
|
console.log('sendMessage failed, using OldMessage fallback:', error.message);
|
|
307
444
|
return api.OldMessage(msg, threadID, callback, replyToMessage, isSingleUser);
|
|
308
445
|
}
|
|
309
446
|
};
|
|
310
447
|
|
|
448
|
+
// Provide explicit method for DM sending using OldMessage
|
|
311
449
|
api.sendMessageDM = function(msg, threadID, callback, replyToMessage) {
|
|
312
450
|
return api.OldMessage(msg, threadID, callback, replyToMessage, true);
|
|
313
451
|
};
|
|
@@ -343,7 +481,7 @@ function makeLogin(jar, email, password, loginOptions, callback, prCallback) {
|
|
|
343
481
|
const cookieData = JSON.parse("[\"" + utils.getFrom(val, "", "]") + "]");
|
|
344
482
|
jar.setCookie(utils.formatCookie(cookieData, "facebook"), "https://www.facebook.com");
|
|
345
483
|
});
|
|
346
|
-
|
|
484
|
+
log.info("Logging in...");
|
|
347
485
|
const loginRes = await utils.post(
|
|
348
486
|
"https://www.facebook.com/login/device-based/regular/login/?login_attempt=1&lwv=110",
|
|
349
487
|
jar,
|
|
@@ -431,14 +569,22 @@ function loginHelper(appState, email, password, globalOptions, callback, prCallb
|
|
|
431
569
|
|
|
432
570
|
try {
|
|
433
571
|
appState.forEach(c => {
|
|
434
|
-
|
|
435
|
-
|
|
572
|
+
// Browser exports use `name`; some older formats use `key`
|
|
573
|
+
const cookieName = c.key || c.name;
|
|
574
|
+
if (!cookieName || !c.value) return;
|
|
575
|
+
const domain = c.domain || '.facebook.com';
|
|
576
|
+
const expires = c.expirationDate
|
|
577
|
+
? new Date(c.expirationDate * 1000).toUTCString()
|
|
578
|
+
: (c.expires || '');
|
|
579
|
+
const str = `${cookieName}=${c.value}; expires=${expires}; domain=${domain}; path=${c.path || '/'};`;
|
|
580
|
+
const url = 'http://' + domain.replace(/^\./, 'www.');
|
|
581
|
+
try { jar.setCookie(str, url); } catch (_) { }
|
|
436
582
|
});
|
|
437
583
|
|
|
438
584
|
mainPromise = utils.get('https://www.facebook.com/', jar, null, globalOptions, { noRef: true })
|
|
439
585
|
.then(utils.saveCookies(jar));
|
|
440
586
|
} catch (e) {
|
|
441
|
-
|
|
587
|
+
return callback(new Error('Failed to load appState: ' + e.message));
|
|
442
588
|
}
|
|
443
589
|
} else {
|
|
444
590
|
mainPromise = utils
|
|
@@ -489,8 +635,7 @@ function loginHelper(appState, email, password, globalOptions, callback, prCallb
|
|
|
489
635
|
|
|
490
636
|
mainPromise
|
|
491
637
|
.then(async () => {
|
|
492
|
-
|
|
493
|
-
console.log('SAGOR-FCA: Listening...');
|
|
638
|
+
log.info('Login successful');
|
|
494
639
|
callback(null, api);
|
|
495
640
|
})
|
|
496
641
|
.catch(e => {
|
|
@@ -500,6 +645,14 @@ function loginHelper(appState, email, password, globalOptions, callback, prCallb
|
|
|
500
645
|
|
|
501
646
|
|
|
502
647
|
function login(loginData, options, callback) {
|
|
648
|
+
// Check for updates (non-blocking, only once per session)
|
|
649
|
+
if (!global.sagor-fcaUpdateChecked) {
|
|
650
|
+
global.sagor-fcaUpdateChecked = true;
|
|
651
|
+
checkForFCAUpdate().catch(err => {
|
|
652
|
+
// Silently ignore update check errors to not block login
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
|
|
503
656
|
if (utils.getType(options) === 'Function' || utils.getType(options) === 'AsyncFunction') {
|
|
504
657
|
callback = options;
|
|
505
658
|
options = {};
|
|
@@ -549,4 +702,5 @@ function login(loginData, options, callback) {
|
|
|
549
702
|
return returnPromise;
|
|
550
703
|
}
|
|
551
704
|
|
|
552
|
-
|
|
705
|
+
|
|
706
|
+
module.exports = login;
|
package/package.json
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sagor-fca",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Custom FCA build by SaGor (forked from fca-unofficial) with extended features and faster updates.",
|
|
3
|
+
"version": "0.0.19",
|
|
4
|
+
"description": "Custom FCA build by SaGor (forked from fca-unofficial & ST-FCA) with extended features and faster updates.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"src/",
|
|
8
8
|
"index.js",
|
|
9
|
-
"utils.js"
|
|
9
|
+
"utils.js",
|
|
10
|
+
"checkUpdate.js"
|
|
10
11
|
],
|
|
11
12
|
"scripts": {
|
|
12
|
-
"
|
|
13
|
-
"
|
|
13
|
+
"test": "node bot.js",
|
|
14
|
+
"start": "node index.js"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/SAGOR-KINGx/sagor-fca.git"
|
|
14
19
|
},
|
|
15
20
|
"keywords": [
|
|
16
21
|
"fca",
|
|
@@ -20,36 +25,28 @@
|
|
|
20
25
|
"fca-custom",
|
|
21
26
|
"sagor-fca"
|
|
22
27
|
],
|
|
23
|
-
"author": "
|
|
28
|
+
"author": "ST | SAGOR",
|
|
24
29
|
"license": "MIT",
|
|
25
|
-
"repository": {
|
|
26
|
-
"type": "git",
|
|
27
|
-
"url": "git+https://github.com/SAGOR-KINGx/sagor-fca.git"
|
|
28
|
-
},
|
|
29
30
|
"bugs": {
|
|
30
31
|
"url": "https://github.com/SAGOR-KINGx/sagor-fca/issues"
|
|
31
32
|
},
|
|
32
33
|
"homepage": "https://github.com/SAGOR-KINGx/sagor-fca#readme",
|
|
33
|
-
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"axios": "^1.8.4",
|
|
36
36
|
"bluebird": "^3.7.2",
|
|
37
37
|
"chalk": "^4.1.2",
|
|
38
|
-
"cheerio": "^1.0.0-rc.
|
|
38
|
+
"cheerio": "^1.0.0-rc.10",
|
|
39
39
|
"duplexify": "^4.1.3",
|
|
40
40
|
"gradient-string": "^2.0.2",
|
|
41
|
-
"https-proxy-agent": "^7.0.
|
|
42
|
-
"
|
|
43
|
-
"
|
|
41
|
+
"https-proxy-agent": "^7.0.6",
|
|
42
|
+
"mime": "^3.0.0",
|
|
43
|
+
"mqtt": "^5.10.1",
|
|
44
|
+
"npmlog": "^1.2.0",
|
|
44
45
|
"request": "^2.88.2",
|
|
45
|
-
"sequelize": "^6.37.6",
|
|
46
|
-
"sqlite3": "^5.1.7",
|
|
47
46
|
"totp-generator": "^1.0.0",
|
|
48
|
-
"ws": "^8.18.1"
|
|
49
|
-
"websocket-stream": "^5.5.2"
|
|
47
|
+
"ws": "^8.18.1"
|
|
50
48
|
},
|
|
51
|
-
|
|
52
49
|
"engines": {
|
|
53
50
|
"node": ">=16.0.0"
|
|
54
51
|
}
|
|
55
|
-
}
|
|
52
|
+
}
|
package/src/addExternalModule.js
CHANGED
package/src/friendList.js
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ===========================================================
|
|
3
|
+
* 🧑💻 Author: Sheikh Tamim (ST | Sheikh Tamim)
|
|
4
|
+
* 🔰 Owner & Developer
|
|
5
|
+
* 🌐 GitHub: https://github.com/sheikhtamimlover
|
|
6
|
+
* 📸 Instagram: https://instagram.com/sheikh.tamim_lover
|
|
7
|
+
* -----------------------------------------------------------
|
|
8
|
+
* 🕊️ Respect the creator & give proper credits if reused.
|
|
9
|
+
* ===========================================================
|
|
10
|
+
*/
|
|
1
11
|
"use strict";
|
|
2
12
|
|
|
3
13
|
const utils = require("../utils");
|
|
4
14
|
|
|
5
15
|
module.exports = function (defaultFuncs, api, ctx) {
|
|
16
|
+
/** Developed by Sheikh Tamim | GitHub: sheikhtamimlover | Instagram: @sheikh.tamim_lover */
|
|
6
17
|
return function friendList(callback) {
|
|
7
18
|
let resolveFunc = function () {};
|
|
8
19
|
let rejectFunc = function () {};
|
|
@@ -89,3 +100,4 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
89
100
|
return returnPromise;
|
|
90
101
|
};
|
|
91
102
|
};
|
|
103
|
+
/** Developed by Sheikh Tamim | GitHub: sheikhtamimlover | Please give credits if reused. */
|