@lazyneoaz/metachat 1.0.8 → 1.0.10
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/index.js +55 -1
- package/package.json +1 -1
- package/src/apis/changeAdminStatus.js +2 -6
- package/src/apis/createPoll.js +1 -1
- package/src/apis/gcmember.js +17 -10
- package/src/apis/gcrule.js +14 -9
- package/src/apis/getAccess.js +3 -1
- package/src/apis/getBotInitialData.js +1 -1
- package/src/apis/getMessage.js +83 -29
- package/src/apis/getThemeInfo.js +6 -2
- package/src/apis/getThreadHistory.js +1 -1
- package/src/apis/getThreadInfo.js +16 -6
- package/src/apis/getThreadList.js +11 -5
- package/src/apis/listenMqtt.js +19 -40
- package/src/apis/markAsRead.js +12 -15
- package/src/apis/markAsSeen.js +7 -9
- package/src/apis/mqttDeltaValue.js +2 -2
- package/src/apis/nickname.js +7 -4
- package/src/apis/pinMessage.js +7 -5
- package/src/apis/removeUserFromGroup.js +1 -0
- package/src/apis/sendEffect.js +4 -4
- package/src/apis/setMessageReaction.js +12 -11
- package/src/apis/setThreadTheme.js +11 -11
- package/src/apis/unsendMessage.js +1 -1
- package/src/app/MessengerBot.js +239 -0
- package/src/app/broadcast.js +48 -0
- package/src/app/config.js +97 -0
- package/src/app/createFcaClient.js +179 -0
- package/src/app/state.js +117 -0
- package/src/app/threadSync.js +106 -0
- package/src/app/updateCheck.js +92 -0
- package/src/engine/client.js +76 -28
- package/src/utils/antiSuspension.js +9 -9
- package/src/utils/auth-helpers.js +17 -1
- package/src/utils/axios.js +30 -16
- package/src/utils/clients.js +112 -112
- package/src/utils/rateLimiter.js +1 -1
package/index.js
CHANGED
|
@@ -1,2 +1,56 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
const { login, loginAsync, loginLegacy, DEFAULT_OPTIONS } = require('./src/engine/client');
|
|
4
|
+
|
|
5
|
+
const { MessengerBot, MessengerContext, createMessengerBot } = require('./src/app/MessengerBot');
|
|
6
|
+
const { createFcaClient, attachClientFacade, createMessagesDomain, createThreadsDomain, createUsersDomain, createAccountDomain, createRealtimeDomain, createHttpDomain, createSchedulerDomain } = require('./src/app/createFcaClient');
|
|
7
|
+
const { defaultConfig, loadConfig, resolveConfig, writeConfigTemplate } = require('./src/app/config');
|
|
8
|
+
const { broadcast } = require('./src/app/broadcast');
|
|
9
|
+
const { attachThreadInfoRealtimeSync } = require('./src/app/threadSync');
|
|
10
|
+
const { checkForPackageUpdate, runConfiguredUpdateCheck } = require('./src/app/updateCheck');
|
|
11
|
+
const { createDefaultContext, createFcaState, createApiFacade, createRequestHelper } = require('./src/app/state');
|
|
12
|
+
|
|
13
|
+
const { normalizeCookieHeaderString, setJarFromPairs } = require('./src/utils/formatters/value/formatCookie');
|
|
14
|
+
const { createAuthCore } = require('./src/utils/auth-helpers');
|
|
15
|
+
|
|
16
|
+
module.exports = login;
|
|
17
|
+
|
|
18
|
+
module.exports.login = login;
|
|
19
|
+
module.exports.loginAsync = loginAsync;
|
|
20
|
+
module.exports.loginLegacy = loginLegacy;
|
|
21
|
+
module.exports.DEFAULT_OPTIONS = DEFAULT_OPTIONS;
|
|
22
|
+
|
|
23
|
+
module.exports.MessengerBot = MessengerBot;
|
|
24
|
+
module.exports.MessengerContext = MessengerContext;
|
|
25
|
+
module.exports.createMessengerBot = createMessengerBot;
|
|
26
|
+
|
|
27
|
+
module.exports.createFcaClient = createFcaClient;
|
|
28
|
+
module.exports.attachClientFacade = attachClientFacade;
|
|
29
|
+
|
|
30
|
+
module.exports.createMessagesDomain = createMessagesDomain;
|
|
31
|
+
module.exports.createThreadsDomain = createThreadsDomain;
|
|
32
|
+
module.exports.createUsersDomain = createUsersDomain;
|
|
33
|
+
module.exports.createAccountDomain = createAccountDomain;
|
|
34
|
+
module.exports.createRealtimeDomain = createRealtimeDomain;
|
|
35
|
+
module.exports.createHttpDomain = createHttpDomain;
|
|
36
|
+
module.exports.createSchedulerDomain = createSchedulerDomain;
|
|
37
|
+
|
|
38
|
+
module.exports.defaultConfig = defaultConfig;
|
|
39
|
+
module.exports.loadConfig = loadConfig;
|
|
40
|
+
module.exports.resolveConfig = resolveConfig;
|
|
41
|
+
module.exports.writeConfigTemplate = writeConfigTemplate;
|
|
42
|
+
|
|
43
|
+
module.exports.broadcast = broadcast;
|
|
44
|
+
module.exports.attachThreadInfoRealtimeSync = attachThreadInfoRealtimeSync;
|
|
45
|
+
|
|
46
|
+
module.exports.checkForPackageUpdate = checkForPackageUpdate;
|
|
47
|
+
module.exports.runConfiguredUpdateCheck = runConfiguredUpdateCheck;
|
|
48
|
+
|
|
49
|
+
module.exports.createDefaultContext = createDefaultContext;
|
|
50
|
+
module.exports.createFcaState = createFcaState;
|
|
51
|
+
module.exports.createApiFacade = createApiFacade;
|
|
52
|
+
module.exports.createRequestHelper = createRequestHelper;
|
|
53
|
+
|
|
54
|
+
module.exports.normalizeCookieHeaderString = normalizeCookieHeaderString;
|
|
55
|
+
module.exports.setJarFromPairs = setJarFromPairs;
|
|
56
|
+
module.exports.createAuthCore = createAuthCore;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyneoaz/metachat",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"types": "src/types/index.d.ts",
|
|
6
6
|
"description": "Advanced Facebook Chat API client for building Messenger bots — real-time messaging, thread management, MQTT, and session stability.",
|
|
@@ -2,10 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const utils = require('../utils');
|
|
4
4
|
|
|
5
|
-
function generateOfflineThreadingID() {
|
|
6
|
-
return Date.now().toString() + Math.floor(Math.random() * 1000000).toString();
|
|
7
|
-
}
|
|
8
|
-
|
|
9
5
|
function getType(obj) {
|
|
10
6
|
return Object.prototype.toString.call(obj).slice(8, -1);
|
|
11
7
|
}
|
|
@@ -39,7 +35,7 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
39
35
|
if (ctx.mqttClient) {
|
|
40
36
|
const tasks = [];
|
|
41
37
|
const isAdmin = adminStatus ? 1 : 0;
|
|
42
|
-
const epochID = generateOfflineThreadingID();
|
|
38
|
+
const epochID = utils.generateOfflineThreadingID();
|
|
43
39
|
|
|
44
40
|
if (getType(adminID) === "Array") {
|
|
45
41
|
adminID.forEach((id, index) => {
|
|
@@ -93,7 +89,7 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
93
89
|
} else {
|
|
94
90
|
utils.warn("MQTT client not available, using HTTP fallback for changeAdminStatus");
|
|
95
91
|
const tasks = [];
|
|
96
|
-
const epochID = generateOfflineThreadingID();
|
|
92
|
+
const epochID = utils.generateOfflineThreadingID();
|
|
97
93
|
|
|
98
94
|
if (getType(adminID) === "Array") {
|
|
99
95
|
adminID.forEach((id, index) => {
|
package/src/apis/createPoll.js
CHANGED
|
@@ -61,7 +61,7 @@ module.exports = (defaultFuncs, api, ctx) => {
|
|
|
61
61
|
type: 3
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
ctx.mqttClient.publish("/ls_req", form);
|
|
64
|
+
ctx.mqttClient.publish("/ls_req", form, { qos: 1, retain: false });
|
|
65
65
|
callback(null, { success: true });
|
|
66
66
|
} catch (err) {
|
|
67
67
|
utils.error("createPoll", err);
|
package/src/apis/gcmember.js
CHANGED
|
@@ -43,24 +43,30 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
if (!validActions.includes(action)) {
|
|
46
|
-
|
|
46
|
+
_callback(null, { type: "error_gc", error: `Invalid action. Must be one of: ${validActions.join(", ")}` });
|
|
47
|
+
return returnPromise;
|
|
47
48
|
}
|
|
48
49
|
if (!userIDs || userIDs.length === 0) {
|
|
49
|
-
|
|
50
|
+
_callback(null, { type: "error_gc", error: "userIDs is required." });
|
|
51
|
+
return returnPromise;
|
|
50
52
|
}
|
|
51
53
|
if (!threadID) {
|
|
52
|
-
|
|
54
|
+
_callback(null, { type: "error_gc", error: "threadID is required." });
|
|
55
|
+
return returnPromise;
|
|
53
56
|
}
|
|
54
57
|
if (!ctx.mqttClient) {
|
|
55
|
-
|
|
58
|
+
_callback(null, { type: "error_gc", error: "Not connected to MQTT" });
|
|
59
|
+
return returnPromise;
|
|
56
60
|
}
|
|
57
61
|
|
|
58
62
|
const threadInfo = await api.getThreadInfo(threadID);
|
|
59
63
|
if (!threadInfo) {
|
|
60
|
-
|
|
64
|
+
_callback(null, { type: "error_gc", error: "Could not retrieve thread information." });
|
|
65
|
+
return returnPromise;
|
|
61
66
|
}
|
|
62
67
|
if (threadInfo.isGroup === false) {
|
|
63
|
-
|
|
68
|
+
_callback(null, { type: "error_gc", error: "This feature is only for group chats, not private messages." });
|
|
69
|
+
return returnPromise;
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
const currentMembers = threadInfo.participantIDs;
|
|
@@ -74,7 +80,8 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
74
80
|
if (action === 'add') {
|
|
75
81
|
const usersToAdd = usersToModify.filter(id => !currentMembers.includes(id));
|
|
76
82
|
if (usersToAdd.length === 0) {
|
|
77
|
-
|
|
83
|
+
_callback(null, { type: "error_gc", error: "All specified users are already in the group." });
|
|
84
|
+
return returnPromise;
|
|
78
85
|
}
|
|
79
86
|
finalUsers = usersToAdd;
|
|
80
87
|
queryPayload = { thread_key: parseInt(threadID), contact_ids: finalUsers.map(id => parseInt(id)), sync_group: 1 };
|
|
@@ -83,7 +90,8 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
83
90
|
} else { // action is 'remove'
|
|
84
91
|
const userToRemove = usersToModify[0];
|
|
85
92
|
if (!currentMembers.includes(userToRemove)) {
|
|
86
|
-
|
|
93
|
+
_callback(null, { type: "error_gc", error: `User with ID ${userToRemove} is not in this group chat.` });
|
|
94
|
+
return returnPromise;
|
|
87
95
|
}
|
|
88
96
|
finalUsers = [userToRemove];
|
|
89
97
|
queryPayload = { thread_id: threadID, contact_id: userToRemove, sync_group: 1 };
|
|
@@ -113,8 +121,7 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
113
121
|
return _callback(null, gcmemberInfo);
|
|
114
122
|
});
|
|
115
123
|
} catch (err) {
|
|
116
|
-
|
|
117
|
-
return _callback(null, { type: "error_gc", error: err.message || "An unknown error occurred." });
|
|
124
|
+
_callback(null, { type: "error_gc", error: err.message || "An unknown error occurred." });
|
|
118
125
|
}
|
|
119
126
|
|
|
120
127
|
return returnPromise;
|
package/src/apis/gcrule.js
CHANGED
|
@@ -41,18 +41,21 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
41
41
|
action = action ? action.toLowerCase() : "";
|
|
42
42
|
|
|
43
43
|
if (!validActions.includes(action)) {
|
|
44
|
-
|
|
44
|
+
_callback(null, { type: "error_gc_rule", error: `Invalid action. Must be one of: ${validActions.join(", ")}` });
|
|
45
|
+
return returnPromise;
|
|
45
46
|
}
|
|
46
|
-
if (!userID)
|
|
47
|
-
if (!threadID)
|
|
48
|
-
if (!ctx.mqttClient)
|
|
47
|
+
if (!userID) { _callback(null, { type: "error_gc_rule", error: "userID is required." }); return returnPromise; }
|
|
48
|
+
if (!threadID) { _callback(null, { type: "error_gc_rule", error: "threadID is required." }); return returnPromise; }
|
|
49
|
+
if (!ctx.mqttClient) { _callback(null, { type: "error_gc_rule", error: "Not connected to MQTT" }); return returnPromise; }
|
|
49
50
|
|
|
50
51
|
const threadInfo = await api.getThreadInfo(threadID);
|
|
51
52
|
if (!threadInfo) {
|
|
52
|
-
|
|
53
|
+
_callback(null, { type: "error_gc_rule", error: "Could not retrieve thread information." });
|
|
54
|
+
return returnPromise;
|
|
53
55
|
}
|
|
54
56
|
if (threadInfo.isGroup === false) {
|
|
55
|
-
|
|
57
|
+
_callback(null, { type: "error_gc_rule", error: "This feature is only for group chats." });
|
|
58
|
+
return returnPromise;
|
|
56
59
|
}
|
|
57
60
|
|
|
58
61
|
const adminIDs = threadInfo.adminIDs || [];
|
|
@@ -60,11 +63,13 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
60
63
|
|
|
61
64
|
if (action === 'admin') {
|
|
62
65
|
if (isCurrentlyAdmin) {
|
|
63
|
-
|
|
66
|
+
_callback(null, { type: "error_gc_rule", error: `User is already an admin.` });
|
|
67
|
+
return returnPromise;
|
|
64
68
|
}
|
|
65
69
|
} else { // action is 'unadmin'
|
|
66
70
|
if (!isCurrentlyAdmin) {
|
|
67
|
-
|
|
71
|
+
_callback(null, { type: "error_gc_rule", error: `User is not an admin.` });
|
|
72
|
+
return returnPromise;
|
|
68
73
|
}
|
|
69
74
|
}
|
|
70
75
|
|
|
@@ -111,7 +116,7 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
111
116
|
});
|
|
112
117
|
|
|
113
118
|
} catch (err) {
|
|
114
|
-
|
|
119
|
+
_callback(null, { type: "error_gc_rule", error: err.message || "An unknown error occurred." });
|
|
115
120
|
}
|
|
116
121
|
|
|
117
122
|
return returnPromise;
|
package/src/apis/getAccess.js
CHANGED
|
@@ -52,7 +52,9 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
52
52
|
Origin: url
|
|
53
53
|
})
|
|
54
54
|
.then(function (res) {
|
|
55
|
-
var
|
|
55
|
+
var parsed;
|
|
56
|
+
try { parsed = JSON.parse(res.body.split(';').pop() || '{}'); } catch(e) { parsed = {}; }
|
|
57
|
+
var { payload } = parsed;
|
|
56
58
|
if (payload && !payload.codeConfirmed)
|
|
57
59
|
throw {
|
|
58
60
|
error: 'submitCode',
|
|
@@ -23,7 +23,7 @@ module.exports = (defaultFuncs, api, ctx) => {
|
|
|
23
23
|
customUserAgent: utils.windowsUserAgent
|
|
24
24
|
}, (err, data) => {
|
|
25
25
|
|
|
26
|
-
if (err)
|
|
26
|
+
if (err) return callback(err);
|
|
27
27
|
const profileMatch = data.match(/"CurrentUserInitialData",\[\],\{(.*?)\},(.*?)\]/);
|
|
28
28
|
if (profileMatch && profileMatch[1]){
|
|
29
29
|
const accountJson = JSON.parse(`{${profileMatch[1]}}`);
|
package/src/apis/getMessage.js
CHANGED
|
@@ -4,26 +4,72 @@ const utils = require('../utils');
|
|
|
4
4
|
const { _formatAttachment } = require('../utils/formatters/data/formatAttachment');
|
|
5
5
|
|
|
6
6
|
const THEME_COLORS = [
|
|
7
|
-
|
|
8
|
-
{ theme_color: "
|
|
9
|
-
{ theme_color: "
|
|
10
|
-
{ theme_color: "
|
|
11
|
-
{ theme_color: "
|
|
12
|
-
{ theme_color: "
|
|
13
|
-
{ theme_color: "
|
|
14
|
-
{ theme_color: "
|
|
15
|
-
{ theme_color: "
|
|
16
|
-
{ theme_color: "
|
|
17
|
-
{ theme_color: "
|
|
18
|
-
{ theme_color: "FF7646FF", theme_id: "
|
|
19
|
-
{ theme_color: "
|
|
20
|
-
{ theme_color: "
|
|
21
|
-
|
|
22
|
-
{ theme_color: "
|
|
23
|
-
{ theme_color: "
|
|
24
|
-
{ theme_color: "
|
|
25
|
-
{ theme_color: "
|
|
26
|
-
{ theme_color: "
|
|
7
|
+
// ── Core solid colours ────────────────────────────────────────────────────
|
|
8
|
+
{ theme_color: "FF0084FF", theme_id: "196241301102133", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Default Blue" },
|
|
9
|
+
{ theme_color: "FF0099FF", theme_id: "3273938616164733", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Classic" },
|
|
10
|
+
{ theme_color: "FF44BEC7", theme_id: "1928399724138152", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Teal Blue" },
|
|
11
|
+
{ theme_color: "FFFFC300", theme_id: "174636906462322", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Yellow" },
|
|
12
|
+
{ theme_color: "FFFA3C4C", theme_id: "2129984390566328", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Red" },
|
|
13
|
+
{ theme_color: "FF7646FF", theme_id: "234137870477637", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Bright Purple" },
|
|
14
|
+
{ theme_color: "FF13CF13", theme_id: "2136751179887052", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Green" },
|
|
15
|
+
{ theme_color: "FFFF7E29", theme_id: "175615189761153", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Orange" },
|
|
16
|
+
{ theme_color: "FFFF5CA1", theme_id: "169463077092846", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Hot Pink" },
|
|
17
|
+
{ theme_color: "FF25D366", theme_id: "2442142322678320", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Deep Sky Blue" },
|
|
18
|
+
{ theme_color: "FF7646FF", theme_id: "2058653964378557", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Lavender Purple" },
|
|
19
|
+
{ theme_color: "FFFF4500", theme_id: "980963458735625", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Light Coral" },
|
|
20
|
+
{ theme_color: "FF00C9C9", theme_id: "417639218648241", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Aqua" },
|
|
21
|
+
// ── Named / gradient themes ───────────────────────────────────────────────
|
|
22
|
+
{ theme_color: "FF000000", theme_id: "788274591712841", theme_emoji: "🖤", gradient: '["FFF0F0F0"]', should_show_icon: "", theme_name_with_subtitle: "Monochrome" },
|
|
23
|
+
{ theme_color: "FF2825B5", theme_id: "271607034185782", theme_emoji: null, gradient: '["FF5E007E","FF331290","FF2825B5"]', should_show_icon: "1", theme_name_with_subtitle: "Shadow" },
|
|
24
|
+
{ theme_color: "FFD9A900", theme_id: "2533652183614000", theme_emoji: null, gradient: '["FF550029","FFAA3232","FFD9A900"]', should_show_icon: "1", theme_name_with_subtitle: "Maple" },
|
|
25
|
+
{ theme_color: "FFFB45DE", theme_id: "2873642949430623", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Tulip" },
|
|
26
|
+
{ theme_color: "FF5E007E", theme_id: "193497045377796", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Grape" },
|
|
27
|
+
{ theme_color: "FF7AA286", theme_id: "1455149831518874", theme_emoji: "🌑", gradient: '["FF25C0E1","FFCE832A"]', should_show_icon: "", theme_name_with_subtitle: "Dune" },
|
|
28
|
+
{ theme_color: "FFFAAF00", theme_id: "672058580051520", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Honey" },
|
|
29
|
+
{ theme_color: "FFF25C54", theme_id: "3022526817824329", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Peach" },
|
|
30
|
+
{ theme_color: "FFF01D6A", theme_id: "724096885023603", theme_emoji: null, gradient: '["FF005FFF","FF9200FF","FFFF2E19"]', should_show_icon: "1", theme_name_with_subtitle: "Berry" },
|
|
31
|
+
{ theme_color: "FFFF7CA8", theme_id: "624266884847972", theme_emoji: null, gradient: '["FFFF8FB2","FFA797FF","FF00E5FF"]', should_show_icon: "1", theme_name_with_subtitle: "Candy" },
|
|
32
|
+
{ theme_color: "FF930099", theme_id: "930060997172551", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Mango" },
|
|
33
|
+
{ theme_color: "FF4267B2", theme_id: "164535220883264", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Berry" },
|
|
34
|
+
{ theme_color: "FF00C400", theme_id: "370940413392601", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Citrus" },
|
|
35
|
+
{ theme_color: "FF50C878", theme_id: "557344741607350", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Citrus 2" },
|
|
36
|
+
{ theme_color: "FFFF0000", theme_id: "205488546921017", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Candy" },
|
|
37
|
+
{ theme_color: "FF8B4513", theme_id: "1833559466821043", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Earth" },
|
|
38
|
+
{ theme_color: "FF0084FF", theme_id: "365557122117011", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Support" },
|
|
39
|
+
{ theme_color: "FFFF6B6B", theme_id: "339021464972092", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Music" },
|
|
40
|
+
{ theme_color: "FFFF69B4", theme_id: "1652456634878319", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Pride" },
|
|
41
|
+
{ theme_color: "FF8B0000", theme_id: "538280997628317", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Doctor Strange" },
|
|
42
|
+
{ theme_color: "FF6C63FF", theme_id: "1060619084701625", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Lo-Fi" },
|
|
43
|
+
{ theme_color: "FF87CEEB", theme_id: "3190514984517598", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Sky" },
|
|
44
|
+
{ theme_color: "FFFF4500", theme_id: "357833546030778", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Lunar New Year" },
|
|
45
|
+
{ theme_color: "FFFF6347", theme_id: "627144732056021", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Celebration" },
|
|
46
|
+
{ theme_color: "FF4682B4", theme_id: "390127158985345", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Chill" },
|
|
47
|
+
{ theme_color: "FFFF0000", theme_id: "1059859811490132", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Stranger Things" },
|
|
48
|
+
{ theme_color: "FFD4A574", theme_id: "275041734441112", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Care" },
|
|
49
|
+
{ theme_color: "FF9B59B6", theme_id: "3082966625307060", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Astrology" },
|
|
50
|
+
{ theme_color: "FFFF8C00", theme_id: "184305226956268", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "J Balvin" },
|
|
51
|
+
{ theme_color: "FFFF69B4", theme_id: "621630955405500", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Birthday" },
|
|
52
|
+
{ theme_color: "FF228B22", theme_id: "539927563794799", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Cottagecore" },
|
|
53
|
+
{ theme_color: "FF006994", theme_id: "736591620215564", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Ocean" },
|
|
54
|
+
{ theme_color: "FFFF1493", theme_id: "741311439775765", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Love" },
|
|
55
|
+
{ theme_color: "FFFF7F7F", theme_id: "230032715012014", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Tie Dye" },
|
|
56
|
+
{ theme_color: "FF808080", theme_id: "262191918210707", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Tropical" },
|
|
57
|
+
{ theme_color: "FF228B22", theme_id: "909695489504566", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Sushi" },
|
|
58
|
+
{ theme_color: "FFFF69B4", theme_id: "280333826736184", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Lollipop" },
|
|
59
|
+
{ theme_color: "FFFF007F", theme_id: "1257453361255152", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Rose" },
|
|
60
|
+
{ theme_color: "FFE6E6FA", theme_id: "571193503540759", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Lavender" },
|
|
61
|
+
{ theme_color: "FFFFC0CB", theme_id: "3151463484918004", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Kiwi" },
|
|
62
|
+
{ theme_color: "FF6F2DA8", theme_id: "810978360551741", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Parenthood" },
|
|
63
|
+
{ theme_color: "FF4169E1", theme_id: "1438011086532622", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Star Wars" },
|
|
64
|
+
{ theme_color: "FF6B8E23", theme_id: "101275642962533", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Guardians of the Galaxy" },
|
|
65
|
+
{ theme_color: "FFFF69B4", theme_id: "158263147151440", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Bloom" },
|
|
66
|
+
{ theme_color: "FF9B59B6", theme_id: "195296273246380", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Bubble Tea" },
|
|
67
|
+
{ theme_color: "FFFF8C00", theme_id: "6026716157422736", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Basketball" },
|
|
68
|
+
{ theme_color: "FF4B0082", theme_id: "737761000603635", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Non-Binary" },
|
|
69
|
+
{ theme_color: "FF55CDFC", theme_id: "504518465021637", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Transgender" },
|
|
70
|
+
{ theme_color: "FFFC0080", theme_id: "769129927636836", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Taylor Swift" },
|
|
71
|
+
{ theme_color: "FFFF7700", theme_id: "822549609168155", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Autumn" },
|
|
72
|
+
{ theme_color: "FFFF007F", theme_id: "693996545771691", theme_emoji: null, gradient: null, should_show_icon: "1", theme_name_with_subtitle: "Elephants and Flowers" },
|
|
27
73
|
];
|
|
28
74
|
|
|
29
75
|
function formatMessage(threadID, data) {
|
|
@@ -63,20 +109,28 @@ function formatMessage(threadID, data) {
|
|
|
63
109
|
const adminType = data.extensible_message_admin_text_type;
|
|
64
110
|
|
|
65
111
|
if (adminType === "CHANGE_THREAD_THEME") {
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
|
|
112
|
+
const ext = data.extensible_message_admin_text || {};
|
|
113
|
+
const themeColor = ext.theme_color || null;
|
|
114
|
+
// Prefer the theme_id field returned directly by GraphQL.
|
|
115
|
+
// Fall back to a reverse lookup in THEME_COLORS for older API
|
|
116
|
+
// responses that omit theme_id.
|
|
117
|
+
const directThemeId = ext.theme_id || ext.theme_fbid || null;
|
|
118
|
+
const colorMatch = directThemeId
|
|
119
|
+
? THEME_COLORS.find(c => c.theme_id === directThemeId)
|
|
120
|
+
: (themeColor ? THEME_COLORS.find(c => c.theme_color === themeColor) : null);
|
|
121
|
+
|
|
69
122
|
return {
|
|
70
123
|
...baseMessage,
|
|
71
124
|
type: "event",
|
|
72
125
|
logMessageType: "log:thread-color",
|
|
73
|
-
logMessageData:
|
|
126
|
+
logMessageData: {
|
|
74
127
|
theme_color: themeColor,
|
|
75
|
-
theme_id: null,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
128
|
+
theme_id: directThemeId || (colorMatch ? colorMatch.theme_id : null),
|
|
129
|
+
theme_fbid: directThemeId || (colorMatch ? colorMatch.theme_id : null),
|
|
130
|
+
theme_emoji: ext.theme_emoji || (colorMatch ? colorMatch.theme_emoji : null),
|
|
131
|
+
gradient: ext.gradient || (colorMatch ? colorMatch.gradient : null),
|
|
132
|
+
should_show_icon: ext.should_show_icon != null ? ext.should_show_icon : (colorMatch ? colorMatch.should_show_icon : null),
|
|
133
|
+
theme_name_with_subtitle: ext.theme_name_with_subtitle || (colorMatch ? colorMatch.theme_name_with_subtitle : null)
|
|
80
134
|
},
|
|
81
135
|
logMessageBody: data.snippet
|
|
82
136
|
};
|
package/src/apis/getThemeInfo.js
CHANGED
|
@@ -84,15 +84,19 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
84
84
|
|
|
85
85
|
const info = Array.isArray(threadInfo) ? threadInfo[0] : threadInfo;
|
|
86
86
|
|
|
87
|
+
// theme_id comes from threadTheme.id (extracted at getThreadInfo level)
|
|
88
|
+
const themeId = info.theme_id || (info.threadTheme && info.threadTheme.id) || info.themeID || null;
|
|
87
89
|
const themeInfo = {
|
|
88
90
|
threadID: identifier,
|
|
89
91
|
threadName: info.threadName || info.name || '',
|
|
90
92
|
color: info.color || null,
|
|
91
93
|
emoji: info.emoji || '👍',
|
|
92
|
-
theme_id:
|
|
94
|
+
theme_id: themeId,
|
|
95
|
+
theme_fbid: themeId,
|
|
93
96
|
theme_color: info.theme_color || info.color || null,
|
|
94
97
|
gradient_colors: info.gradient_colors || null,
|
|
95
|
-
|
|
98
|
+
threadTheme: info.threadTheme || null,
|
|
99
|
+
is_default: !info.color && !themeId
|
|
96
100
|
};
|
|
97
101
|
|
|
98
102
|
if (callback) {
|
|
@@ -112,12 +112,22 @@ function formatThreadGraphQLResponse(data) {
|
|
|
112
112
|
emoji: messageThread.customization_info
|
|
113
113
|
? messageThread.customization_info.emoji
|
|
114
114
|
: null,
|
|
115
|
-
color:
|
|
116
|
-
messageThread.customization_info &&
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
115
|
+
color: (function() {
|
|
116
|
+
const raw = messageThread.customization_info &&
|
|
117
|
+
messageThread.customization_info.outgoing_bubble_color;
|
|
118
|
+
if (!raw) return null;
|
|
119
|
+
const s = String(raw);
|
|
120
|
+
// Format is FFRRGGBB (8 hex chars, ARGB). Strip the FF alpha prefix.
|
|
121
|
+
// Validate before slicing to avoid returning garbage for unexpected formats.
|
|
122
|
+
if (/^[0-9a-fA-F]{8}$/.test(s)) return s.slice(2);
|
|
123
|
+
// Handle #RRGGBB or #AARRGGBB
|
|
124
|
+
if (/^#[0-9a-fA-F]{6}$/.test(s)) return s.slice(1);
|
|
125
|
+
if (/^#[0-9a-fA-F]{8}$/.test(s)) return s.slice(3);
|
|
126
|
+
// Fallback: return as-is
|
|
127
|
+
return s;
|
|
128
|
+
})(),
|
|
120
129
|
threadTheme: messageThread.thread_theme,
|
|
130
|
+
theme_id: messageThread.thread_theme ? (messageThread.thread_theme.id || null) : null,
|
|
121
131
|
nicknames:
|
|
122
132
|
messageThread.customization_info &&
|
|
123
133
|
messageThread.customization_info.participant_customizations
|
|
@@ -253,7 +263,7 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
253
263
|
|
|
254
264
|
const threadInfo = formatThreadGraphQLResponse(responseData.data);
|
|
255
265
|
if (threadInfo) {
|
|
256
|
-
threadInfos[threadInfo.threadID ||
|
|
266
|
+
threadInfos[threadInfo.threadID || threadIDs[i]] = threadInfo;
|
|
257
267
|
}
|
|
258
268
|
}
|
|
259
269
|
|
|
@@ -102,12 +102,18 @@ function formatThreadGraphQLResponse(messageThread) {
|
|
|
102
102
|
emoji: messageThread.customization_info
|
|
103
103
|
? messageThread.customization_info.emoji
|
|
104
104
|
: null,
|
|
105
|
-
color:
|
|
106
|
-
messageThread.customization_info &&
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
105
|
+
color: (function() {
|
|
106
|
+
const raw = messageThread.customization_info &&
|
|
107
|
+
messageThread.customization_info.outgoing_bubble_color;
|
|
108
|
+
if (!raw) return null;
|
|
109
|
+
const s = String(raw);
|
|
110
|
+
if (/^[0-9a-fA-F]{8}$/.test(s)) return s.slice(2);
|
|
111
|
+
if (/^#[0-9a-fA-F]{6}$/.test(s)) return s.slice(1);
|
|
112
|
+
if (/^#[0-9a-fA-F]{8}$/.test(s)) return s.slice(3);
|
|
113
|
+
return s;
|
|
114
|
+
})(),
|
|
110
115
|
threadTheme: messageThread.thread_theme,
|
|
116
|
+
theme_id: messageThread.thread_theme ? (messageThread.thread_theme.id || null) : null,
|
|
111
117
|
nicknames:
|
|
112
118
|
messageThread.customization_info &&
|
|
113
119
|
messageThread.customization_info.participant_customizations
|
package/src/apis/listenMqtt.js
CHANGED
|
@@ -449,15 +449,17 @@ async function listenMqtt(defaultFuncs, api, ctx, globalCallback, scheduleReconn
|
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
451
|
} else if (topic === "/thread_typing" || topic === "/orca_typing_notifications") {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
452
|
+
if (ctx.globalOptions.listenTyping) {
|
|
453
|
+
const typ = {
|
|
454
|
+
type: "typ",
|
|
455
|
+
isTyping: !!jsonMessage.state,
|
|
456
|
+
from: jsonMessage.sender_fbid.toString(),
|
|
457
|
+
threadID: utils.formatID((jsonMessage.thread || jsonMessage.sender_fbid).toString())
|
|
458
|
+
};
|
|
459
|
+
globalCallback(null, typ);
|
|
460
|
+
}
|
|
459
461
|
} else if (topic === "/orca_presence") {
|
|
460
|
-
if (
|
|
462
|
+
if (ctx.globalOptions.updatePresence && jsonMessage.list) {
|
|
461
463
|
for (const data of jsonMessage.list) {
|
|
462
464
|
globalCallback(null, {
|
|
463
465
|
type: "presence",
|
|
@@ -808,39 +810,16 @@ module.exports = (defaultFuncs, api, ctx, opts) => {
|
|
|
808
810
|
} catch (err) {
|
|
809
811
|
const detail = (err && err.detail && err.detail.message) ? ` | detail=${err.detail.message}` : "";
|
|
810
812
|
const msg = ((err && err.error) || (err && err.message) || String(err || "")) + detail;
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
if (isNotLoggedIn || isLoginBlocked) {
|
|
816
|
-
const reason = isLoginBlocked ? "login_blocked" : "not_logged_in";
|
|
817
|
-
utils.error("MQTT", `Auth error in getSeqID: ${reason} — attempting auto re-login`);
|
|
818
|
-
|
|
819
|
-
// Mirror the close-handler re-login pattern: try handleSessionExpiry first.
|
|
820
|
-
// If it succeeds we schedule a reconnect; only fall back to emitAuthError
|
|
821
|
-
// (which kills listening) when re-login is unavailable or already in progress.
|
|
822
|
-
if (!ctx._mqttReauthing && globalAutoReLoginManager && globalAutoReLoginManager.isEnabled && globalAutoReLoginManager.isEnabled()) {
|
|
823
|
-
ctx._mqttReauthing = true;
|
|
824
|
-
globalAutoReLoginManager.handleSessionExpiry(api, 'https://www.facebook.com', msg)
|
|
825
|
-
.then((ok) => {
|
|
826
|
-
ctx._mqttReauthing = false;
|
|
827
|
-
if (ok && ctx.globalOptions.autoReconnect) {
|
|
828
|
-
ctx._reconnectAttempts = 0;
|
|
829
|
-
scheduleReconnect((ctx._mqttOpt && ctx._mqttOpt.reconnectDelayMs) || 2000);
|
|
830
|
-
} else if (!ok) {
|
|
831
|
-
emitAuthError(reason, msg);
|
|
832
|
-
}
|
|
833
|
-
})
|
|
834
|
-
.catch(() => {
|
|
835
|
-
ctx._mqttReauthing = false;
|
|
836
|
-
emitAuthError(reason, msg);
|
|
837
|
-
});
|
|
838
|
-
return;
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
return emitAuthError(reason, msg);
|
|
813
|
+
|
|
814
|
+
if (/Not logged in/i.test(msg)) {
|
|
815
|
+
utils.error("MQTT", "Auth error in getSeqID: Not logged in");
|
|
816
|
+
return emitAuthError("not_logged_in", msg);
|
|
842
817
|
}
|
|
843
|
-
|
|
818
|
+
if (/blocked the login|checkpoint|security check|session.*expir|invalid.*session|authentication.*fail|auth.*fail|login.*block|account.*lock|verification.*requir/i.test(msg)) {
|
|
819
|
+
utils.error("MQTT", "Auth error in getSeqID: Session/Login blocked");
|
|
820
|
+
return emitAuthError("login_blocked", msg);
|
|
821
|
+
}
|
|
822
|
+
|
|
844
823
|
utils.error("MQTT", "getSeqID error:", msg);
|
|
845
824
|
if (ctx.globalOptions.autoReconnect) {
|
|
846
825
|
const baseDelay = (ctx._mqttOpt && ctx._mqttOpt.reconnectDelayMs) || 2000;
|
package/src/apis/markAsRead.js
CHANGED
|
@@ -50,23 +50,20 @@ module.exports = function (defaultFuncs, api, ctx) {
|
|
|
50
50
|
|
|
51
51
|
callback(null);
|
|
52
52
|
} else {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
53
|
+
const form = {
|
|
54
|
+
["ids[" + threadID + "]"]: read,
|
|
55
|
+
watermarkTimestamp: Date.now(),
|
|
56
|
+
shouldSendReadReceipt: true,
|
|
57
|
+
};
|
|
58
58
|
|
|
59
|
-
const
|
|
60
|
-
ctx.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
{ qos: 1, retain: false },
|
|
64
|
-
r,
|
|
65
|
-
)
|
|
66
|
-
);
|
|
59
|
+
const resData = await defaultFuncs
|
|
60
|
+
.post("https://www.facebook.com/ajax/mercury/change_read_status.php", ctx.jar, form)
|
|
61
|
+
.then(utils.saveCookies(ctx.jar))
|
|
62
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs));
|
|
67
63
|
|
|
68
|
-
if (
|
|
69
|
-
|
|
64
|
+
if (resData && resData.error) {
|
|
65
|
+
const err = new Error(String(resData.error.message || resData.error));
|
|
66
|
+
callback(err);
|
|
70
67
|
return returnPromise;
|
|
71
68
|
}
|
|
72
69
|
|