sagor-fca 0.0.18 → 0.0.20
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/package.json +1 -1
- package/src/addExternalModule.js +2 -1
- package/src/sendMessageEffect.js +65 -0
- package/src/sendEffect.js +0 -157
package/package.json
CHANGED
package/src/addExternalModule.js
CHANGED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { generateOfflineThreadingID } = require('../utils');
|
|
4
|
+
|
|
5
|
+
function isCallable(func) {
|
|
6
|
+
return typeof func === 'function';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
module.exports = function (defaultFuncs, api, ctx) {
|
|
10
|
+
return function sendMessageEffect(effectID, messageID, threadID, callback) {
|
|
11
|
+
if (!ctx.mqttClient) {
|
|
12
|
+
throw new Error('MQTT client is not connected');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (!effectID || !messageID || !threadID) {
|
|
16
|
+
throw new Error('Missing required parameters');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
ctx.wsReqNumber = (ctx.wsReqNumber || 0) + 1;
|
|
20
|
+
ctx.wsTaskNumber = (ctx.wsTaskNumber || 0) + 1;
|
|
21
|
+
|
|
22
|
+
const taskPayload = {
|
|
23
|
+
thread_key: threadID,
|
|
24
|
+
message_id: messageID,
|
|
25
|
+
actor_id: ctx.userID,
|
|
26
|
+
timestamp_ms: Date.now(),
|
|
27
|
+
effect_id: effectID,
|
|
28
|
+
sync_group: 1
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const task = {
|
|
32
|
+
failure_count: null,
|
|
33
|
+
label: '46',
|
|
34
|
+
payload: JSON.stringify(taskPayload),
|
|
35
|
+
queue_name: 'effect',
|
|
36
|
+
task_id: ctx.wsTaskNumber
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const content = {
|
|
40
|
+
app_id: '2220391788200892',
|
|
41
|
+
payload: JSON.stringify({
|
|
42
|
+
epoch_id: parseInt(generateOfflineThreadingID()),
|
|
43
|
+
tasks: [task],
|
|
44
|
+
version_id: '7158486590867448'
|
|
45
|
+
}),
|
|
46
|
+
request_id: ctx.wsReqNumber,
|
|
47
|
+
type: 3
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
if (isCallable(callback)) {
|
|
51
|
+
ctx.reqCallbacks = ctx.reqCallbacks || {};
|
|
52
|
+
ctx.reqCallbacks[ctx.wsReqNumber] = callback;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
ctx.mqttClient.publish('/ls_req', JSON.stringify(content), {
|
|
57
|
+
qos: 1,
|
|
58
|
+
retain: false
|
|
59
|
+
});
|
|
60
|
+
} catch (err) {
|
|
61
|
+
if (isCallable(callback)) callback(err);
|
|
62
|
+
else console.error('sendMessageEffect error:', err);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
};
|
package/src/sendEffect.js
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const utils = require("../utils");
|
|
4
|
-
|
|
5
|
-
// ═══════════════════════════════════════════════════
|
|
6
|
-
// sendEffect.js — for sagor-fca
|
|
7
|
-
// Author: SaGor
|
|
8
|
-
//
|
|
9
|
-
// Usage:
|
|
10
|
-
// api.sendEffect(effect, threadID, callback)
|
|
11
|
-
// api.sendEffect("fire", threadID)
|
|
12
|
-
// api.sendEffect("love", event.threadID, (err, info) => {})
|
|
13
|
-
// await api.sendEffect("gift", event.threadID)
|
|
14
|
-
//
|
|
15
|
-
// 4 Confirmed effects (from Messenger "Send Effects" screen):
|
|
16
|
-
// "love" / "hearts" → ❤️ Love (pink hearts)
|
|
17
|
-
// "gift" → 🎁 Gift Wrap (blue ribbon box)
|
|
18
|
-
// "wham" / "bam" → 💥 Wham! (dark impact effect)
|
|
19
|
-
// "fire" → 🔥 Fire (orange fire flies)
|
|
20
|
-
// ═══════════════════════════════════════════════════
|
|
21
|
-
|
|
22
|
-
// Confirmed Facebook Messenger internal send_effect tag names
|
|
23
|
-
const EFFECTS = {
|
|
24
|
-
// ❤️ Love / Hearts — leftmost in Messenger UI
|
|
25
|
-
love: "love_hearts",
|
|
26
|
-
hearts: "love_hearts",
|
|
27
|
-
heart: "love_hearts",
|
|
28
|
-
|
|
29
|
-
// 🎁 Gift Wrap — 2nd in Messenger UI
|
|
30
|
-
gift: "gift_wrap",
|
|
31
|
-
|
|
32
|
-
// 💥 Wham! — 3rd in Messenger UI (dark brown)
|
|
33
|
-
wham: "wham",
|
|
34
|
-
bam: "wham",
|
|
35
|
-
|
|
36
|
-
// 🔥 Fire — rightmost in Messenger UI
|
|
37
|
-
fire: "fire_fly",
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
module.exports = function (defaultFuncs, api, ctx) {
|
|
41
|
-
|
|
42
|
-
return function sendEffect(effect, threadID, callback) {
|
|
43
|
-
|
|
44
|
-
// Promise support
|
|
45
|
-
let resolveFunc, rejectFunc;
|
|
46
|
-
const returnPromise = new Promise((resolve, reject) => {
|
|
47
|
-
resolveFunc = resolve;
|
|
48
|
-
rejectFunc = reject;
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
if (typeof callback !== "function") {
|
|
52
|
-
callback = function (err, data) {
|
|
53
|
-
if (err) return rejectFunc(err);
|
|
54
|
-
resolveFunc(data);
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Validate effect name
|
|
59
|
-
const effectKey = (effect || "").toString().toLowerCase().trim();
|
|
60
|
-
const effectTag = EFFECTS[effectKey];
|
|
61
|
-
|
|
62
|
-
if (!effectTag) {
|
|
63
|
-
const valid = [...new Set(Object.values(EFFECTS).map(v =>
|
|
64
|
-
Object.keys(EFFECTS).find(k => EFFECTS[k] === v)
|
|
65
|
-
))].join(", ");
|
|
66
|
-
return callback({
|
|
67
|
-
error: `Invalid effect "${effect}". Valid: ${valid}`
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Validate threadID
|
|
72
|
-
if (!threadID) {
|
|
73
|
-
return callback({ error: "threadID is required." });
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Build the form — same base as sendMessage.js
|
|
77
|
-
const messageAndOTID = utils.generateOfflineThreadingID();
|
|
78
|
-
|
|
79
|
-
const form = {
|
|
80
|
-
client: "mercury",
|
|
81
|
-
action_type: "ma-type:user-generated-message",
|
|
82
|
-
author: "fbid:" + ctx.userID,
|
|
83
|
-
timestamp: Date.now(),
|
|
84
|
-
timestamp_absolute: "Today",
|
|
85
|
-
timestamp_relative: utils.generateTimestampRelative(),
|
|
86
|
-
timestamp_time_passed: "0",
|
|
87
|
-
is_unread: false,
|
|
88
|
-
is_cleared: false,
|
|
89
|
-
is_forward: false,
|
|
90
|
-
is_filtered_content: false,
|
|
91
|
-
is_filtered_content_bh: false,
|
|
92
|
-
is_filtered_content_account: false,
|
|
93
|
-
is_filtered_content_quasar: false,
|
|
94
|
-
is_filtered_content_invalid_app: false,
|
|
95
|
-
is_spoof_warning: false,
|
|
96
|
-
source: "source:chat:web",
|
|
97
|
-
"source_tags[0]": "source:chat",
|
|
98
|
-
body: "",
|
|
99
|
-
html_body: false,
|
|
100
|
-
ui_push_phase: "V3",
|
|
101
|
-
status: "0",
|
|
102
|
-
offline_threading_id: messageAndOTID,
|
|
103
|
-
message_id: messageAndOTID,
|
|
104
|
-
threading_id: utils.generateThreadingID(ctx.clientID),
|
|
105
|
-
"ephemeral_ttl_mode:": "0",
|
|
106
|
-
manual_retry_cnt: "0",
|
|
107
|
-
has_attachment: false,
|
|
108
|
-
signatureID: utils.getSignatureID(),
|
|
109
|
-
|
|
110
|
-
// KEY: same pattern as hot_emoji_size in sendMessage.js
|
|
111
|
-
// form["tags[0]"] = "hot_emoji_size:large" ← for emoji
|
|
112
|
-
// form["tags[0]"] = "send_effect:fire_fly" ← for effects
|
|
113
|
-
"tags[0]": "send_effect:" + effectTag,
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
// Set thread target — same logic as sendMessage.js
|
|
117
|
-
const threadIDStr = threadID.toString();
|
|
118
|
-
const isDM = threadIDStr.length === 15 || !threadIDStr.match(/^\d{16,}$/);
|
|
119
|
-
|
|
120
|
-
if (isDM) {
|
|
121
|
-
form["specific_to_list[0]"] = "fbid:" + threadID;
|
|
122
|
-
form["specific_to_list[1]"] = "fbid:" + ctx.userID;
|
|
123
|
-
form["other_user_fbid"] = threadID;
|
|
124
|
-
} else {
|
|
125
|
-
form["thread_fbid"] = threadID;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// POST to messaging/send — same endpoint as sendMessage.js
|
|
129
|
-
defaultFuncs
|
|
130
|
-
.post("https://www.facebook.com/messaging/send/", ctx.jar, form)
|
|
131
|
-
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
|
132
|
-
.then(function (resData) {
|
|
133
|
-
if (!resData) {
|
|
134
|
-
throw { error: "sendEffect: empty response." };
|
|
135
|
-
}
|
|
136
|
-
if (resData.error) {
|
|
137
|
-
throw resData;
|
|
138
|
-
}
|
|
139
|
-
const actions = resData.payload && resData.payload.actions;
|
|
140
|
-
const messageInfo = Array.isArray(actions)
|
|
141
|
-
? actions.reduce((p, v) => ({
|
|
142
|
-
threadID: v.thread_fbid,
|
|
143
|
-
messageID: v.message_id,
|
|
144
|
-
timestamp: v.timestamp,
|
|
145
|
-
}) || p, null)
|
|
146
|
-
: null;
|
|
147
|
-
|
|
148
|
-
return callback(null, messageInfo);
|
|
149
|
-
})
|
|
150
|
-
.catch(function (err) {
|
|
151
|
-
console.error("sendEffect error:", err);
|
|
152
|
-
return callback(err);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
return returnPromise;
|
|
156
|
-
};
|
|
157
|
-
};
|