@lazyneoaz/metachat 6.0.5 → 6.0.7
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/dist/index.cjs +106 -56
- package/dist/index.mjs +106 -56
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -89023,7 +89023,7 @@ var sendMessage_default = (defaultFuncs, api, ctx) => {
|
|
|
89023
89023
|
}, null);
|
|
89024
89024
|
return messageInfo;
|
|
89025
89025
|
}
|
|
89026
|
-
|
|
89026
|
+
const sendMessageCore = async function(msg, threadID, callback, replyToMessage, isGroup) {
|
|
89027
89027
|
if (typeof isGroup === "undefined") isGroup = null;
|
|
89028
89028
|
if (!callback && (getType(threadID) === "Function" || getType(threadID) === "AsyncFunction")) {
|
|
89029
89029
|
throw new Error("Pass a threadID as a second argument.");
|
|
@@ -89047,11 +89047,13 @@ var sendMessage_default = (defaultFuncs, api, ctx) => {
|
|
|
89047
89047
|
if (msgType !== "String" && msgType !== "Object") {
|
|
89048
89048
|
const err = new Error("Message should be of type string or object and not " + msgType + ".");
|
|
89049
89049
|
settle2(err);
|
|
89050
|
+
if (legacyCallback) return null;
|
|
89050
89051
|
throw err;
|
|
89051
89052
|
}
|
|
89052
89053
|
if (threadIDType !== "Array" && threadIDType !== "Number" && threadIDType !== "String") {
|
|
89053
89054
|
const err = new Error("ThreadID should be of type number, string, or array and not " + threadIDType + ".");
|
|
89054
89055
|
settle2(err);
|
|
89056
|
+
if (legacyCallback) return null;
|
|
89055
89057
|
throw err;
|
|
89056
89058
|
}
|
|
89057
89059
|
if (messageIDType === "Function" || messageIDType === "Undefined" || messageIDType === "Null") {
|
|
@@ -89059,6 +89061,7 @@ var sendMessage_default = (defaultFuncs, api, ctx) => {
|
|
|
89059
89061
|
} else if (replyToMessage && messageIDType !== "String") {
|
|
89060
89062
|
const err = new Error("MessageID should be of type string and not " + messageIDType + ".");
|
|
89061
89063
|
settle2(err);
|
|
89064
|
+
if (legacyCallback) return null;
|
|
89062
89065
|
throw err;
|
|
89063
89066
|
}
|
|
89064
89067
|
let isSingleUser = null;
|
|
@@ -89316,6 +89319,12 @@ var sendMessage_default = (defaultFuncs, api, ctx) => {
|
|
|
89316
89319
|
}
|
|
89317
89320
|
}
|
|
89318
89321
|
};
|
|
89322
|
+
return function sendMessage(msg, threadID, callback, replyToMessage, isGroup) {
|
|
89323
|
+
const promise = sendMessageCore(msg, threadID, callback, replyToMessage, isGroup);
|
|
89324
|
+
if (typeof callback === "function") promise.catch(() => {
|
|
89325
|
+
});
|
|
89326
|
+
return promise;
|
|
89327
|
+
};
|
|
89319
89328
|
};
|
|
89320
89329
|
|
|
89321
89330
|
// src/deltas/apis/messaging/sendTypingIndicator.ts
|
|
@@ -90856,6 +90865,7 @@ function pinMessage_default(defaultFuncs, api, ctx) {
|
|
|
90856
90865
|
}
|
|
90857
90866
|
|
|
90858
90867
|
// src/deltas/apis/mqtt/sendMessageMqtt.ts
|
|
90868
|
+
var DEFAULT_RETRY_DELAYS_MS = [900, 1600, 2400, 3500, 5e3, 7e3];
|
|
90859
90869
|
function preUploadedId(item) {
|
|
90860
90870
|
if (typeof item === "number" && Number.isFinite(item)) return String(item);
|
|
90861
90871
|
if (typeof item === "string" && /^\d{6,}$/.test(item.trim())) return item.trim();
|
|
@@ -90959,6 +90969,8 @@ var sendMessageMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
90959
90969
|
resolveFunc = resolve;
|
|
90960
90970
|
rejectFunc = reject;
|
|
90961
90971
|
});
|
|
90972
|
+
returnPromise.catch(() => {
|
|
90973
|
+
});
|
|
90962
90974
|
const userCallback = typeof callback === "function" ? callback : null;
|
|
90963
90975
|
let finished2 = false;
|
|
90964
90976
|
const finish = (err, data2) => {
|
|
@@ -90975,51 +90987,14 @@ var sendMessageMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
90975
90987
|
if (!callback) {
|
|
90976
90988
|
callback = finish;
|
|
90977
90989
|
}
|
|
90990
|
+
const done = () => userCallback ? returnPromise.then(() => null, () => null) : returnPromise;
|
|
90978
90991
|
if (!ctx.mqttClient || !ctx.mqttClient.connected) {
|
|
90979
90992
|
const error2 = new Error("MQTT client is not connected. Cannot send message.");
|
|
90980
90993
|
finish(error2);
|
|
90981
|
-
return
|
|
90994
|
+
return done();
|
|
90982
90995
|
}
|
|
90983
90996
|
const timestamp = Date.now();
|
|
90984
|
-
|
|
90985
|
-
const epoch_id = (BigInt(Date.now()) << 22n).toString();
|
|
90986
|
-
const request_id = ctx.wsReqNumber = (ctx.wsReqNumber || 0) + 1;
|
|
90987
|
-
const payload = getSendPayload(threadID, msg, otid);
|
|
90988
|
-
const tasks = [{
|
|
90989
|
-
label: "46",
|
|
90990
|
-
payload,
|
|
90991
|
-
queue_name: threadID.toString(),
|
|
90992
|
-
task_id: 400,
|
|
90993
|
-
failure_count: null
|
|
90994
|
-
}, {
|
|
90995
|
-
label: "21",
|
|
90996
|
-
payload: {
|
|
90997
|
-
thread_id: threadID.toString(),
|
|
90998
|
-
last_read_watermark_ts: timestamp,
|
|
90999
|
-
sync_group: 1
|
|
91000
|
-
},
|
|
91001
|
-
queue_name: threadID.toString(),
|
|
91002
|
-
task_id: 401,
|
|
91003
|
-
failure_count: null
|
|
91004
|
-
}];
|
|
91005
|
-
if (replyToMessage) {
|
|
91006
|
-
tasks[0].payload.reply_metadata = {
|
|
91007
|
-
reply_source_id: replyToMessage,
|
|
91008
|
-
reply_source_type: 1,
|
|
91009
|
-
reply_type: 0
|
|
91010
|
-
};
|
|
91011
|
-
}
|
|
91012
|
-
const form = {
|
|
91013
|
-
app_id: "2220391788200892",
|
|
91014
|
-
payload: {
|
|
91015
|
-
tasks,
|
|
91016
|
-
epoch_id,
|
|
91017
|
-
version_id: "24804310205905615",
|
|
91018
|
-
data_trace_id: `#${Buffer.from(String(Math.random())).toString("base64").replace(/=+$/g, "")}`
|
|
91019
|
-
},
|
|
91020
|
-
request_id,
|
|
91021
|
-
type: 3
|
|
91022
|
-
};
|
|
90997
|
+
let attachmentIds = null;
|
|
91023
90998
|
if (msg.attachment) {
|
|
91024
90999
|
try {
|
|
91025
91000
|
const inputs = Array.isArray(msg.attachment) ? msg.attachment : [msg.attachment];
|
|
@@ -91036,20 +91011,62 @@ var sendMessageMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
91036
91011
|
ids.push(file && typeof file === "object" ? String(Object.values(file)[0]) : String(file));
|
|
91037
91012
|
}
|
|
91038
91013
|
}
|
|
91039
|
-
|
|
91014
|
+
attachmentIds = ids;
|
|
91040
91015
|
} catch (err) {
|
|
91041
91016
|
error("Attachment upload failed:", err);
|
|
91042
91017
|
callback(err);
|
|
91043
|
-
return
|
|
91018
|
+
return done();
|
|
91044
91019
|
}
|
|
91045
91020
|
}
|
|
91046
|
-
form.payload.tasks.forEach((task) => {
|
|
91047
|
-
task.payload = JSON.stringify(task.payload);
|
|
91048
|
-
});
|
|
91049
|
-
form.payload = JSON.stringify(form.payload);
|
|
91050
|
-
const fallbackMessageID = `mid.${otid}`;
|
|
91051
91021
|
const mqttClient = ctx.mqttClient;
|
|
91052
|
-
const
|
|
91022
|
+
const buildForm = () => {
|
|
91023
|
+
const otid = generateOfflineThreadingID();
|
|
91024
|
+
const epoch_id = (BigInt(Date.now()) << 22n).toString();
|
|
91025
|
+
const request_id = ctx.wsReqNumber = (ctx.wsReqNumber || 0) + 1;
|
|
91026
|
+
const payload = getSendPayload(threadID, msg, otid);
|
|
91027
|
+
if (attachmentIds) payload.attachment_fbids = attachmentIds;
|
|
91028
|
+
const tasks = [{
|
|
91029
|
+
label: "46",
|
|
91030
|
+
payload,
|
|
91031
|
+
queue_name: threadID.toString(),
|
|
91032
|
+
task_id: 400,
|
|
91033
|
+
failure_count: null
|
|
91034
|
+
}, {
|
|
91035
|
+
label: "21",
|
|
91036
|
+
payload: {
|
|
91037
|
+
thread_id: threadID.toString(),
|
|
91038
|
+
last_read_watermark_ts: Date.now(),
|
|
91039
|
+
sync_group: 1
|
|
91040
|
+
},
|
|
91041
|
+
queue_name: threadID.toString(),
|
|
91042
|
+
task_id: 401,
|
|
91043
|
+
failure_count: null
|
|
91044
|
+
}];
|
|
91045
|
+
if (replyToMessage) {
|
|
91046
|
+
tasks[0].payload.reply_metadata = {
|
|
91047
|
+
reply_source_id: replyToMessage,
|
|
91048
|
+
reply_source_type: 1,
|
|
91049
|
+
reply_type: 0
|
|
91050
|
+
};
|
|
91051
|
+
}
|
|
91052
|
+
const form = {
|
|
91053
|
+
app_id: "2220391788200892",
|
|
91054
|
+
payload: {
|
|
91055
|
+
tasks,
|
|
91056
|
+
epoch_id,
|
|
91057
|
+
version_id: "24804310205905615",
|
|
91058
|
+
data_trace_id: `#${Buffer.from(String(Math.random())).toString("base64").replace(/=+$/g, "")}`
|
|
91059
|
+
},
|
|
91060
|
+
request_id,
|
|
91061
|
+
type: 3
|
|
91062
|
+
};
|
|
91063
|
+
form.payload.tasks.forEach((task) => {
|
|
91064
|
+
task.payload = JSON.stringify(task.payload);
|
|
91065
|
+
});
|
|
91066
|
+
form.payload = JSON.stringify(form.payload);
|
|
91067
|
+
return { form, request_id, otid };
|
|
91068
|
+
};
|
|
91069
|
+
const publishAndWait = (form, request_id) => new Promise((resolve) => {
|
|
91053
91070
|
let settled = false;
|
|
91054
91071
|
let timer = null;
|
|
91055
91072
|
const cleanup = () => {
|
|
@@ -91078,6 +91095,7 @@ var sendMessageMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
91078
91095
|
let threadIDFromAck = null;
|
|
91079
91096
|
let failure = null;
|
|
91080
91097
|
let serverError = null;
|
|
91098
|
+
let softFailure = null;
|
|
91081
91099
|
const steps = parsed.payload?.step;
|
|
91082
91100
|
const visit = (node) => {
|
|
91083
91101
|
if (!Array.isArray(node)) return;
|
|
@@ -91089,10 +91107,10 @@ var sendMessageMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
91089
91107
|
threadIDFromAck = String(node[2][1]);
|
|
91090
91108
|
}
|
|
91091
91109
|
if (node[1] === "markOptimisticMessageFailed") {
|
|
91092
|
-
|
|
91110
|
+
softFailure = typeof node[3] === "string" ? node[3] : "Message failed on server.";
|
|
91093
91111
|
}
|
|
91094
91112
|
if (node[1] === "updateSubscriptErrorMessage" || node[1] === "fatalError") {
|
|
91095
|
-
|
|
91113
|
+
softFailure = typeof node[3] === "string" ? node[3] : typeof node[4] === "string" ? node[4] : "Couldn't send.";
|
|
91096
91114
|
}
|
|
91097
91115
|
}
|
|
91098
91116
|
for (const child of node) visit(child);
|
|
@@ -91102,7 +91120,8 @@ var sendMessageMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
91102
91120
|
messageID: resolvedMessageID,
|
|
91103
91121
|
threadID: threadIDFromAck,
|
|
91104
91122
|
failure,
|
|
91105
|
-
serverError
|
|
91123
|
+
serverError,
|
|
91124
|
+
softFailure
|
|
91106
91125
|
});
|
|
91107
91126
|
};
|
|
91108
91127
|
if (mqttClient && typeof mqttClient.on === "function") {
|
|
@@ -91113,24 +91132,55 @@ var sendMessageMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
91113
91132
|
});
|
|
91114
91133
|
timer = setTimeout(() => settle2({ timeout: true }), 15e3);
|
|
91115
91134
|
});
|
|
91135
|
+
const retryDelays = (() => {
|
|
91136
|
+
const override = ctx.globalOptions && ctx.globalOptions.mqttSendRetryDelaysMs;
|
|
91137
|
+
return Array.isArray(override) && override.length ? override : DEFAULT_RETRY_DELAYS_MS;
|
|
91138
|
+
})();
|
|
91139
|
+
let result = null;
|
|
91140
|
+
let lastOtid = "";
|
|
91141
|
+
for (let attempt = 0; attempt <= retryDelays.length; attempt++) {
|
|
91142
|
+
const built = buildForm();
|
|
91143
|
+
lastOtid = built.otid;
|
|
91144
|
+
result = await publishAndWait(built.form, built.request_id);
|
|
91145
|
+
if (!result.failure && !result.serverError && !result.softFailure) break;
|
|
91146
|
+
if ((result.failure || result.serverError) && attempt >= 2) break;
|
|
91147
|
+
if (attempt < retryDelays.length) {
|
|
91148
|
+
await sleep(retryDelays[attempt] + Math.floor(Math.random() * 400));
|
|
91149
|
+
}
|
|
91150
|
+
}
|
|
91116
91151
|
if (result.failure || result.serverError) {
|
|
91117
91152
|
const err = result.failure || { error: result.serverError };
|
|
91118
91153
|
if (err.error && err.error === 1545012) {
|
|
91119
91154
|
warn("sendMessageMqtt [MQTT]", `Got error 1545012. Bot is not part of the conversation ${threadID}`);
|
|
91120
91155
|
finish(null, null);
|
|
91121
|
-
return
|
|
91156
|
+
return done();
|
|
91122
91157
|
}
|
|
91123
91158
|
error("sendMessageMqtt", "Send failed:", err.error || err);
|
|
91124
91159
|
finish(err);
|
|
91125
|
-
return
|
|
91160
|
+
return done();
|
|
91161
|
+
}
|
|
91162
|
+
if (result.softFailure) {
|
|
91163
|
+
warn(
|
|
91164
|
+
"sendMessageMqtt [MQTT]",
|
|
91165
|
+
`Facebook rejected the message (${result.softFailure}); thread ${threadID}. Retried ${retryDelays.length} times without success; continuing without failing the bot.`
|
|
91166
|
+
);
|
|
91167
|
+
finish(null, {
|
|
91168
|
+
threadID: result.threadID || threadID.toString(),
|
|
91169
|
+
messageID: result.messageID || null,
|
|
91170
|
+
timestamp,
|
|
91171
|
+
type: replyToMessage ? "message_reply" : "message",
|
|
91172
|
+
error: result.softFailure,
|
|
91173
|
+
success: false
|
|
91174
|
+
});
|
|
91175
|
+
return done();
|
|
91126
91176
|
}
|
|
91127
91177
|
finish(null, {
|
|
91128
91178
|
threadID: result.threadID || threadID.toString(),
|
|
91129
|
-
messageID: result.messageID ||
|
|
91179
|
+
messageID: result.messageID || `mid.${lastOtid}`,
|
|
91130
91180
|
timestamp,
|
|
91131
91181
|
type: replyToMessage ? "message_reply" : "message"
|
|
91132
91182
|
});
|
|
91133
|
-
return
|
|
91183
|
+
return done();
|
|
91134
91184
|
};
|
|
91135
91185
|
};
|
|
91136
91186
|
|
package/dist/index.mjs
CHANGED
|
@@ -88991,7 +88991,7 @@ var sendMessage_default = (defaultFuncs, api, ctx) => {
|
|
|
88991
88991
|
}, null);
|
|
88992
88992
|
return messageInfo;
|
|
88993
88993
|
}
|
|
88994
|
-
|
|
88994
|
+
const sendMessageCore = async function(msg, threadID, callback, replyToMessage, isGroup) {
|
|
88995
88995
|
if (typeof isGroup === "undefined") isGroup = null;
|
|
88996
88996
|
if (!callback && (getType(threadID) === "Function" || getType(threadID) === "AsyncFunction")) {
|
|
88997
88997
|
throw new Error("Pass a threadID as a second argument.");
|
|
@@ -89015,11 +89015,13 @@ var sendMessage_default = (defaultFuncs, api, ctx) => {
|
|
|
89015
89015
|
if (msgType !== "String" && msgType !== "Object") {
|
|
89016
89016
|
const err = new Error("Message should be of type string or object and not " + msgType + ".");
|
|
89017
89017
|
settle2(err);
|
|
89018
|
+
if (legacyCallback) return null;
|
|
89018
89019
|
throw err;
|
|
89019
89020
|
}
|
|
89020
89021
|
if (threadIDType !== "Array" && threadIDType !== "Number" && threadIDType !== "String") {
|
|
89021
89022
|
const err = new Error("ThreadID should be of type number, string, or array and not " + threadIDType + ".");
|
|
89022
89023
|
settle2(err);
|
|
89024
|
+
if (legacyCallback) return null;
|
|
89023
89025
|
throw err;
|
|
89024
89026
|
}
|
|
89025
89027
|
if (messageIDType === "Function" || messageIDType === "Undefined" || messageIDType === "Null") {
|
|
@@ -89027,6 +89029,7 @@ var sendMessage_default = (defaultFuncs, api, ctx) => {
|
|
|
89027
89029
|
} else if (replyToMessage && messageIDType !== "String") {
|
|
89028
89030
|
const err = new Error("MessageID should be of type string and not " + messageIDType + ".");
|
|
89029
89031
|
settle2(err);
|
|
89032
|
+
if (legacyCallback) return null;
|
|
89030
89033
|
throw err;
|
|
89031
89034
|
}
|
|
89032
89035
|
let isSingleUser = null;
|
|
@@ -89284,6 +89287,12 @@ var sendMessage_default = (defaultFuncs, api, ctx) => {
|
|
|
89284
89287
|
}
|
|
89285
89288
|
}
|
|
89286
89289
|
};
|
|
89290
|
+
return function sendMessage(msg, threadID, callback, replyToMessage, isGroup) {
|
|
89291
|
+
const promise = sendMessageCore(msg, threadID, callback, replyToMessage, isGroup);
|
|
89292
|
+
if (typeof callback === "function") promise.catch(() => {
|
|
89293
|
+
});
|
|
89294
|
+
return promise;
|
|
89295
|
+
};
|
|
89287
89296
|
};
|
|
89288
89297
|
|
|
89289
89298
|
// src/deltas/apis/messaging/sendTypingIndicator.ts
|
|
@@ -90824,6 +90833,7 @@ function pinMessage_default(defaultFuncs, api, ctx) {
|
|
|
90824
90833
|
}
|
|
90825
90834
|
|
|
90826
90835
|
// src/deltas/apis/mqtt/sendMessageMqtt.ts
|
|
90836
|
+
var DEFAULT_RETRY_DELAYS_MS = [900, 1600, 2400, 3500, 5e3, 7e3];
|
|
90827
90837
|
function preUploadedId(item) {
|
|
90828
90838
|
if (typeof item === "number" && Number.isFinite(item)) return String(item);
|
|
90829
90839
|
if (typeof item === "string" && /^\d{6,}$/.test(item.trim())) return item.trim();
|
|
@@ -90927,6 +90937,8 @@ var sendMessageMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
90927
90937
|
resolveFunc = resolve;
|
|
90928
90938
|
rejectFunc = reject;
|
|
90929
90939
|
});
|
|
90940
|
+
returnPromise.catch(() => {
|
|
90941
|
+
});
|
|
90930
90942
|
const userCallback = typeof callback === "function" ? callback : null;
|
|
90931
90943
|
let finished2 = false;
|
|
90932
90944
|
const finish = (err, data2) => {
|
|
@@ -90943,51 +90955,14 @@ var sendMessageMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
90943
90955
|
if (!callback) {
|
|
90944
90956
|
callback = finish;
|
|
90945
90957
|
}
|
|
90958
|
+
const done = () => userCallback ? returnPromise.then(() => null, () => null) : returnPromise;
|
|
90946
90959
|
if (!ctx.mqttClient || !ctx.mqttClient.connected) {
|
|
90947
90960
|
const error2 = new Error("MQTT client is not connected. Cannot send message.");
|
|
90948
90961
|
finish(error2);
|
|
90949
|
-
return
|
|
90962
|
+
return done();
|
|
90950
90963
|
}
|
|
90951
90964
|
const timestamp = Date.now();
|
|
90952
|
-
|
|
90953
|
-
const epoch_id = (BigInt(Date.now()) << 22n).toString();
|
|
90954
|
-
const request_id = ctx.wsReqNumber = (ctx.wsReqNumber || 0) + 1;
|
|
90955
|
-
const payload = getSendPayload(threadID, msg, otid);
|
|
90956
|
-
const tasks = [{
|
|
90957
|
-
label: "46",
|
|
90958
|
-
payload,
|
|
90959
|
-
queue_name: threadID.toString(),
|
|
90960
|
-
task_id: 400,
|
|
90961
|
-
failure_count: null
|
|
90962
|
-
}, {
|
|
90963
|
-
label: "21",
|
|
90964
|
-
payload: {
|
|
90965
|
-
thread_id: threadID.toString(),
|
|
90966
|
-
last_read_watermark_ts: timestamp,
|
|
90967
|
-
sync_group: 1
|
|
90968
|
-
},
|
|
90969
|
-
queue_name: threadID.toString(),
|
|
90970
|
-
task_id: 401,
|
|
90971
|
-
failure_count: null
|
|
90972
|
-
}];
|
|
90973
|
-
if (replyToMessage) {
|
|
90974
|
-
tasks[0].payload.reply_metadata = {
|
|
90975
|
-
reply_source_id: replyToMessage,
|
|
90976
|
-
reply_source_type: 1,
|
|
90977
|
-
reply_type: 0
|
|
90978
|
-
};
|
|
90979
|
-
}
|
|
90980
|
-
const form = {
|
|
90981
|
-
app_id: "2220391788200892",
|
|
90982
|
-
payload: {
|
|
90983
|
-
tasks,
|
|
90984
|
-
epoch_id,
|
|
90985
|
-
version_id: "24804310205905615",
|
|
90986
|
-
data_trace_id: `#${Buffer.from(String(Math.random())).toString("base64").replace(/=+$/g, "")}`
|
|
90987
|
-
},
|
|
90988
|
-
request_id,
|
|
90989
|
-
type: 3
|
|
90990
|
-
};
|
|
90965
|
+
let attachmentIds = null;
|
|
90991
90966
|
if (msg.attachment) {
|
|
90992
90967
|
try {
|
|
90993
90968
|
const inputs = Array.isArray(msg.attachment) ? msg.attachment : [msg.attachment];
|
|
@@ -91004,20 +90979,62 @@ var sendMessageMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
91004
90979
|
ids.push(file && typeof file === "object" ? String(Object.values(file)[0]) : String(file));
|
|
91005
90980
|
}
|
|
91006
90981
|
}
|
|
91007
|
-
|
|
90982
|
+
attachmentIds = ids;
|
|
91008
90983
|
} catch (err) {
|
|
91009
90984
|
error("Attachment upload failed:", err);
|
|
91010
90985
|
callback(err);
|
|
91011
|
-
return
|
|
90986
|
+
return done();
|
|
91012
90987
|
}
|
|
91013
90988
|
}
|
|
91014
|
-
form.payload.tasks.forEach((task) => {
|
|
91015
|
-
task.payload = JSON.stringify(task.payload);
|
|
91016
|
-
});
|
|
91017
|
-
form.payload = JSON.stringify(form.payload);
|
|
91018
|
-
const fallbackMessageID = `mid.${otid}`;
|
|
91019
90989
|
const mqttClient = ctx.mqttClient;
|
|
91020
|
-
const
|
|
90990
|
+
const buildForm = () => {
|
|
90991
|
+
const otid = generateOfflineThreadingID();
|
|
90992
|
+
const epoch_id = (BigInt(Date.now()) << 22n).toString();
|
|
90993
|
+
const request_id = ctx.wsReqNumber = (ctx.wsReqNumber || 0) + 1;
|
|
90994
|
+
const payload = getSendPayload(threadID, msg, otid);
|
|
90995
|
+
if (attachmentIds) payload.attachment_fbids = attachmentIds;
|
|
90996
|
+
const tasks = [{
|
|
90997
|
+
label: "46",
|
|
90998
|
+
payload,
|
|
90999
|
+
queue_name: threadID.toString(),
|
|
91000
|
+
task_id: 400,
|
|
91001
|
+
failure_count: null
|
|
91002
|
+
}, {
|
|
91003
|
+
label: "21",
|
|
91004
|
+
payload: {
|
|
91005
|
+
thread_id: threadID.toString(),
|
|
91006
|
+
last_read_watermark_ts: Date.now(),
|
|
91007
|
+
sync_group: 1
|
|
91008
|
+
},
|
|
91009
|
+
queue_name: threadID.toString(),
|
|
91010
|
+
task_id: 401,
|
|
91011
|
+
failure_count: null
|
|
91012
|
+
}];
|
|
91013
|
+
if (replyToMessage) {
|
|
91014
|
+
tasks[0].payload.reply_metadata = {
|
|
91015
|
+
reply_source_id: replyToMessage,
|
|
91016
|
+
reply_source_type: 1,
|
|
91017
|
+
reply_type: 0
|
|
91018
|
+
};
|
|
91019
|
+
}
|
|
91020
|
+
const form = {
|
|
91021
|
+
app_id: "2220391788200892",
|
|
91022
|
+
payload: {
|
|
91023
|
+
tasks,
|
|
91024
|
+
epoch_id,
|
|
91025
|
+
version_id: "24804310205905615",
|
|
91026
|
+
data_trace_id: `#${Buffer.from(String(Math.random())).toString("base64").replace(/=+$/g, "")}`
|
|
91027
|
+
},
|
|
91028
|
+
request_id,
|
|
91029
|
+
type: 3
|
|
91030
|
+
};
|
|
91031
|
+
form.payload.tasks.forEach((task) => {
|
|
91032
|
+
task.payload = JSON.stringify(task.payload);
|
|
91033
|
+
});
|
|
91034
|
+
form.payload = JSON.stringify(form.payload);
|
|
91035
|
+
return { form, request_id, otid };
|
|
91036
|
+
};
|
|
91037
|
+
const publishAndWait = (form, request_id) => new Promise((resolve) => {
|
|
91021
91038
|
let settled = false;
|
|
91022
91039
|
let timer = null;
|
|
91023
91040
|
const cleanup = () => {
|
|
@@ -91046,6 +91063,7 @@ var sendMessageMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
91046
91063
|
let threadIDFromAck = null;
|
|
91047
91064
|
let failure = null;
|
|
91048
91065
|
let serverError = null;
|
|
91066
|
+
let softFailure = null;
|
|
91049
91067
|
const steps = parsed.payload?.step;
|
|
91050
91068
|
const visit = (node) => {
|
|
91051
91069
|
if (!Array.isArray(node)) return;
|
|
@@ -91057,10 +91075,10 @@ var sendMessageMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
91057
91075
|
threadIDFromAck = String(node[2][1]);
|
|
91058
91076
|
}
|
|
91059
91077
|
if (node[1] === "markOptimisticMessageFailed") {
|
|
91060
|
-
|
|
91078
|
+
softFailure = typeof node[3] === "string" ? node[3] : "Message failed on server.";
|
|
91061
91079
|
}
|
|
91062
91080
|
if (node[1] === "updateSubscriptErrorMessage" || node[1] === "fatalError") {
|
|
91063
|
-
|
|
91081
|
+
softFailure = typeof node[3] === "string" ? node[3] : typeof node[4] === "string" ? node[4] : "Couldn't send.";
|
|
91064
91082
|
}
|
|
91065
91083
|
}
|
|
91066
91084
|
for (const child of node) visit(child);
|
|
@@ -91070,7 +91088,8 @@ var sendMessageMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
91070
91088
|
messageID: resolvedMessageID,
|
|
91071
91089
|
threadID: threadIDFromAck,
|
|
91072
91090
|
failure,
|
|
91073
|
-
serverError
|
|
91091
|
+
serverError,
|
|
91092
|
+
softFailure
|
|
91074
91093
|
});
|
|
91075
91094
|
};
|
|
91076
91095
|
if (mqttClient && typeof mqttClient.on === "function") {
|
|
@@ -91081,24 +91100,55 @@ var sendMessageMqtt_default = (defaultFuncs, api, ctx) => {
|
|
|
91081
91100
|
});
|
|
91082
91101
|
timer = setTimeout(() => settle2({ timeout: true }), 15e3);
|
|
91083
91102
|
});
|
|
91103
|
+
const retryDelays = (() => {
|
|
91104
|
+
const override = ctx.globalOptions && ctx.globalOptions.mqttSendRetryDelaysMs;
|
|
91105
|
+
return Array.isArray(override) && override.length ? override : DEFAULT_RETRY_DELAYS_MS;
|
|
91106
|
+
})();
|
|
91107
|
+
let result = null;
|
|
91108
|
+
let lastOtid = "";
|
|
91109
|
+
for (let attempt = 0; attempt <= retryDelays.length; attempt++) {
|
|
91110
|
+
const built = buildForm();
|
|
91111
|
+
lastOtid = built.otid;
|
|
91112
|
+
result = await publishAndWait(built.form, built.request_id);
|
|
91113
|
+
if (!result.failure && !result.serverError && !result.softFailure) break;
|
|
91114
|
+
if ((result.failure || result.serverError) && attempt >= 2) break;
|
|
91115
|
+
if (attempt < retryDelays.length) {
|
|
91116
|
+
await sleep(retryDelays[attempt] + Math.floor(Math.random() * 400));
|
|
91117
|
+
}
|
|
91118
|
+
}
|
|
91084
91119
|
if (result.failure || result.serverError) {
|
|
91085
91120
|
const err = result.failure || { error: result.serverError };
|
|
91086
91121
|
if (err.error && err.error === 1545012) {
|
|
91087
91122
|
warn("sendMessageMqtt [MQTT]", `Got error 1545012. Bot is not part of the conversation ${threadID}`);
|
|
91088
91123
|
finish(null, null);
|
|
91089
|
-
return
|
|
91124
|
+
return done();
|
|
91090
91125
|
}
|
|
91091
91126
|
error("sendMessageMqtt", "Send failed:", err.error || err);
|
|
91092
91127
|
finish(err);
|
|
91093
|
-
return
|
|
91128
|
+
return done();
|
|
91129
|
+
}
|
|
91130
|
+
if (result.softFailure) {
|
|
91131
|
+
warn(
|
|
91132
|
+
"sendMessageMqtt [MQTT]",
|
|
91133
|
+
`Facebook rejected the message (${result.softFailure}); thread ${threadID}. Retried ${retryDelays.length} times without success; continuing without failing the bot.`
|
|
91134
|
+
);
|
|
91135
|
+
finish(null, {
|
|
91136
|
+
threadID: result.threadID || threadID.toString(),
|
|
91137
|
+
messageID: result.messageID || null,
|
|
91138
|
+
timestamp,
|
|
91139
|
+
type: replyToMessage ? "message_reply" : "message",
|
|
91140
|
+
error: result.softFailure,
|
|
91141
|
+
success: false
|
|
91142
|
+
});
|
|
91143
|
+
return done();
|
|
91094
91144
|
}
|
|
91095
91145
|
finish(null, {
|
|
91096
91146
|
threadID: result.threadID || threadID.toString(),
|
|
91097
|
-
messageID: result.messageID ||
|
|
91147
|
+
messageID: result.messageID || `mid.${lastOtid}`,
|
|
91098
91148
|
timestamp,
|
|
91099
91149
|
type: replyToMessage ? "message_reply" : "message"
|
|
91100
91150
|
});
|
|
91101
|
-
return
|
|
91151
|
+
return done();
|
|
91102
91152
|
};
|
|
91103
91153
|
};
|
|
91104
91154
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyneoaz/metachat",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.7",
|
|
4
4
|
"description": "A modern TypeScript Facebook Chat API client for building reliable Messenger bots, with built-in anti-detection protection, automatic cookie refresh, music search, and AI theme support.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"prepublishOnly": "npm run build",
|
|
58
58
|
"lint": "npm run typecheck",
|
|
59
59
|
"format": "prettier --write \"src/**/*.ts\" \"index.ts\"",
|
|
60
|
-
"test": "npm run build && node test/smoke.test.cjs && node test/smoke.test.mjs && node test/music-search.test.cjs && node test/mqtt-lifecycle.test.cjs && node test/session-reliability.test.cjs && node test/anti-detection.test.cjs && node test/account-safety.test.cjs && node test/liveness.test.cjs && node test/recovery.test.cjs && node test/cookie-acquisition.test.cjs && node test/realtime-health.test.cjs && node test/attachment-resilience.test.cjs && node test/reaction-validation.test.cjs && node test/api-surface-fixes.test.cjs && node test/threadinfo-regression.test.cjs && node test/new-modules.test.cjs && node test/mention-parsing.test.cjs && node test/pending-support.test.cjs && node test/music-token-resilience.test.cjs",
|
|
60
|
+
"test": "npm run build && node test/smoke.test.cjs && node test/smoke.test.mjs && node test/music-search.test.cjs && node test/mqtt-lifecycle.test.cjs && node test/session-reliability.test.cjs && node test/anti-detection.test.cjs && node test/account-safety.test.cjs && node test/liveness.test.cjs && node test/recovery.test.cjs && node test/cookie-acquisition.test.cjs && node test/realtime-health.test.cjs && node test/attachment-resilience.test.cjs && node test/reaction-validation.test.cjs && node test/api-surface-fixes.test.cjs && node test/threadinfo-regression.test.cjs && node test/new-modules.test.cjs && node test/mention-parsing.test.cjs && node test/pending-support.test.cjs && node test/music-token-resilience.test.cjs && node test/send-failure.test.cjs",
|
|
61
61
|
"audit": "npm audit",
|
|
62
62
|
"audit:fix": "npm audit fix"
|
|
63
63
|
},
|