stfca 1.0.18 → 1.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stfca",
3
- "version": "1.0.18",
3
+ "version": "1.0.20",
4
4
  "description": "Unofficial Facebook Chat API for Node.js with Auto-Update System - Enhanced by ST | Sheikh Tamim",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -8,269 +8,96 @@
8
8
  * 🕊️ Respect the creator & give proper credits if reused.
9
9
  * ===========================================================
10
10
  */
11
- "use strict";
11
+ 'use strict';
12
12
 
13
- var utils = require("../utils");
14
- var log = require("npmlog");
13
+ const utils = require('../utils');
14
+ const log = require('npmlog');
15
15
 
16
16
  module.exports = function (defaultFuncs, api, ctx) {
17
- /** Developed by Sheikh Tamim | GitHub: sheikhtamimlover | Instagram: @sheikh.tamim_lover */
18
- return function setThreadTheme(threadID, themeData, callback) {
19
- var resolveFunc = function () { };
20
- var rejectFunc = function () { };
21
- var returnPromise = new Promise(function (resolve, reject) {
22
- resolveFunc = resolve;
23
- rejectFunc = reject;
24
- });
25
-
26
- if (!callback) {
27
- callback = function (err, data) {
28
- if (err) return rejectFunc(err);
29
- resolveFunc(data);
30
- };
31
- }
32
-
33
- if (!threadID) {
34
- return callback({ error: "threadID is required" });
35
- }
36
-
37
- async function updateThreadTheme() {
38
- try {
39
- const timestamp = Date.now();
40
-
41
- // Step 1: Load theme bootloader modules
42
- const moduleParams = new URLSearchParams({
43
- modules: "LSUpdateThreadTheme,LSUpdateThreadCustomEmoji,LSUpdateThreadThemePayloadCacheKey",
44
- __aaid: 0,
45
- __user: ctx.userID,
46
- __a: 1,
47
- __req: utils.getSignatureID(),
48
- __hs: "20352.HYP:comet_pkg.2.1...0",
49
- dpr: 1,
50
- __ccg: "EXCELLENT",
51
- __rev: "1027396270",
52
- __s: utils.getSignatureID(),
53
- __hsi: "7552524636527201016",
54
- __comet_req: 15,
55
- fb_dtsg_ag: ctx.fb_dtsg,
56
- jazoest: ctx.ttstamp,
57
- __spin_r: "1027396270",
58
- __spin_b: "trunk",
59
- __spin_t: timestamp,
60
- __crn: "comet.fbweb.MWInboxHomeRoute"
61
- });
62
-
63
- await defaultFuncs
64
- .get("https://www.facebook.com/ajax/bootloader-endpoint/?" + moduleParams.toString(), ctx.jar)
65
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs));
66
-
67
- // Step 2: Get available themes first
68
- let availableThemes = [];
69
- try {
70
- const themeForm = {
71
- av: ctx.userID,
72
- __aaid: 0,
73
- __user: ctx.userID,
74
- __a: 1,
75
- __req: utils.getSignatureID(),
76
- __hs: "20352.HYP:comet_pkg.2.1...0",
77
- dpr: 1,
78
- __ccg: "EXCELLENT",
79
- __rev: "1027396270",
80
- __s: utils.getSignatureID(),
81
- __hsi: "7552524636527201016",
82
- __comet_req: 15,
83
- fb_dtsg: ctx.fb_dtsg,
84
- jazoest: ctx.ttstamp,
85
- lsd: ctx.fb_dtsg,
86
- __spin_r: "1027396270",
87
- __spin_b: "trunk",
88
- __spin_t: timestamp,
89
- __crn: "comet.fbweb.MWInboxHomeRoute",
90
- qpl_active_flow_ids: "25308101",
91
- fb_api_caller_class: "RelayModern",
92
- fb_api_req_friendly_name: "MWPThreadThemeQuery_AllThemesQuery",
93
- variables: JSON.stringify({
94
- "version": "default"
95
- }),
96
- server_timestamps: true,
97
- doc_id: "24474714052117636"
98
- };
99
-
100
- const themeResult = await defaultFuncs
101
- .post("https://www.facebook.com/api/graphql/", ctx.jar, themeForm)
102
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs));
103
-
104
- if (themeResult && themeResult.data && themeResult.data.messenger_thread_themes) {
105
- availableThemes = themeResult.data.messenger_thread_themes;
106
- }
107
- } catch (e) {
108
- log.warn("setThreadTheme", "Could not fetch available themes, proceeding with theme update");
109
- }
110
-
111
- // Step 3: Determine theme ID based on input
112
- let themeId = null;
113
- let customEmoji = "👍";
114
-
115
- if (typeof themeData === "string") {
116
- // If it's a string, try to find matching theme
117
- if (themeData.match(/^[0-9]+$/)) {
118
- // Numeric theme ID
119
- themeId = themeData;
120
- } else {
121
- // Search by theme name/description
122
- const foundTheme = availableThemes.find(theme =>
123
- theme.accessibility_label &&
124
- theme.accessibility_label.toLowerCase().includes(themeData.toLowerCase())
125
- );
126
- if (foundTheme) {
127
- themeId = foundTheme.id;
128
- } else {
129
- // Fallback color mapping
130
- const colorMap = {
131
- blue: "196241301102133",
132
- purple: "370940413392601",
133
- green: "169463077092846",
134
- pink: "230032715012014",
135
- orange: "175615189761153",
136
- red: "2136751179887052",
137
- yellow: "2058653964378557",
138
- teal: "417639218648241",
139
- black: "539927563794799",
140
- white: "2873642392710980",
141
- default: "196241301102133"
142
- };
143
- themeId = colorMap[themeData.toLowerCase()] || colorMap.default;
144
- }
145
- }
146
- } else if (typeof themeData === "object" && themeData !== null) {
147
- themeId = themeData.themeId || themeData.theme_id || themeData.id;
148
- customEmoji = themeData.emoji || themeData.customEmoji || "👍";
149
- }
150
-
151
- if (!themeId) {
152
- themeId = "196241301102133"; // Default blue theme
153
- }
154
-
155
- // Step 4: Use direct bootloader approach for theme update
156
- try {
157
- // First try with the legacy changeThreadColor approach
158
- const legacyForm = {
159
- dpr: 1,
160
- queries: JSON.stringify({
161
- o0: {
162
- doc_id: "1727493033983591",
163
- query_params: {
164
- data: {
165
- actor_id: ctx.userID,
166
- client_mutation_id: "0",
167
- source: "SETTINGS",
168
- theme_id: themeId,
169
- thread_id: threadID,
170
- },
171
- },
172
- },
173
- }),
174
- };
175
-
176
- const legacyResult = await defaultFuncs
177
- .post("https://www.facebook.com/api/graphqlbatch/", ctx.jar, legacyForm)
178
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs));
179
-
180
- if (legacyResult && !legacyResult[0]?.o0?.errors) {
181
- return callback(null, {
182
- threadID: threadID,
183
- themeId: themeId,
184
- customEmoji: customEmoji,
185
- timestamp: timestamp,
186
- success: true,
187
- method: "legacy",
188
- availableThemes: availableThemes.length > 0 ? availableThemes.map(t => ({
189
- id: t.id,
190
- name: t.accessibility_label,
191
- description: t.description
192
- })) : null
193
- });
194
- }
195
- } catch (legacyErr) {
196
- log.warn("setThreadTheme", "Legacy method failed, trying alternative approach");
197
- }
198
-
199
- // Step 5: Try alternative GraphQL mutation with updated doc_id
200
- const alternativeForm = {
201
- av: ctx.userID,
202
- __aaid: 0,
203
- __user: ctx.userID,
204
- __a: 1,
205
- __req: utils.getSignatureID(),
206
- __hs: "20352.HYP:comet_pkg.2.1...0",
207
- dpr: 1,
208
- __ccg: "EXCELLENT",
209
- __rev: "1027396270",
210
- __s: utils.getSignatureID(),
211
- __hsi: "7552524636527201016",
212
- __comet_req: 15,
213
- fb_dtsg: ctx.fb_dtsg,
214
- jazoest: ctx.ttstamp,
215
- lsd: ctx.fb_dtsg,
216
- __spin_r: "1027396270",
217
- __spin_b: "trunk",
218
- __spin_t: timestamp,
219
- __crn: "comet.fbweb.MWInboxHomeRoute",
220
- fb_api_caller_class: "RelayModern",
221
- fb_api_req_friendly_name: "MessengerThreadThemeUpdateMutation",
222
- variables: JSON.stringify({
223
- "input": {
224
- "actor_id": ctx.userID,
225
- "client_mutation_id": Math.floor(Math.random() * 10000).toString(),
226
- "source": "SETTINGS",
227
- "thread_id": threadID.toString(),
228
- "theme_id": themeId.toString(),
229
- "custom_emoji": customEmoji
230
- }
231
- }),
232
- server_timestamps: true,
233
- doc_id: "9734829906576883" // Updated doc_id based on working API
234
- };
235
-
236
- const result = await defaultFuncs
237
- .post("https://www.facebook.com/api/graphql/", ctx.jar, alternativeForm)
238
- .then(utils.parseAndCheckLogin(ctx, defaultFuncs));
239
-
240
- if (result && result.errors && result.errors.length > 0) {
241
- throw new Error("GraphQL Error: " + JSON.stringify(result.errors));
242
- }
243
-
244
- // Check if the mutation was successful
245
- if (result && result.data && result.data.messenger_thread_theme_update) {
246
- const updateResult = result.data.messenger_thread_theme_update;
247
- if (updateResult.errors && updateResult.errors.length > 0) {
248
- throw new Error("Theme Update Error: " + JSON.stringify(updateResult.errors));
249
- }
250
- }
251
-
252
- return callback(null, {
253
- threadID: threadID,
254
- themeId: themeId,
255
- customEmoji: customEmoji,
256
- timestamp: timestamp,
257
- success: true,
258
- method: "graphql",
259
- availableThemes: availableThemes.length > 0 ? availableThemes.map(t => ({
260
- id: t.id,
261
- name: t.accessibility_label,
262
- description: t.description
263
- })) : null
264
- });
265
-
266
- } catch (err) {
267
- log.error("setThreadTheme", err);
268
- return callback(err);
269
- }
270
- }
271
-
272
- updateThreadTheme();
273
- return returnPromise;
274
- };
17
+ /** Developed by Sheikh Tamim | GitHub: sheikhtamimlover | Instagram: @sheikh.tamim_lover */
18
+ return function setThreadTheme(threadID, themeFBID, callback) {
19
+ var resolveFunc = function () { };
20
+ var rejectFunc = function () { };
21
+ var returnPromise = new Promise(function (resolve, reject) {
22
+ resolveFunc = resolve;
23
+ rejectFunc = reject;
24
+ });
25
+
26
+ if (!callback) {
27
+ callback = function (err, data) {
28
+ if (err) return rejectFunc(err);
29
+ resolveFunc(data);
30
+ };
31
+ }
32
+
33
+ if (!ctx.mqttClient) {
34
+ return callback(new Error('Not connected to MQTT'));
35
+ }
36
+
37
+ ctx.wsReqNumber += 1;
38
+ let baseTaskNumber = ++ctx.wsTaskNumber;
39
+
40
+ const makeTask = (label, queueName, extraPayload = {}) => ({
41
+ failure_count: null,
42
+ label: String(label),
43
+ payload: JSON.stringify({
44
+ thread_key: threadID,
45
+ theme_fbid: themeFBID,
46
+ sync_group: 1,
47
+ ...extraPayload,
48
+ }),
49
+ queue_name: typeof queueName === 'string' ? queueName : JSON.stringify(queueName),
50
+ task_id: baseTaskNumber++,
51
+ });
52
+
53
+ const messages = [
54
+ {
55
+ label: 1013,
56
+ queue: ['ai_generated_theme', String(threadID)],
57
+ },
58
+ {
59
+ label: 1037,
60
+ queue: ['msgr_custom_thread_theme', String(threadID)],
61
+ },
62
+ {
63
+ label: 1028,
64
+ queue: ['thread_theme_writer', String(threadID)],
65
+ },
66
+ {
67
+ label: 43,
68
+ queue: 'thread_theme',
69
+ extra: { source: null, payload: null },
70
+ },
71
+ ].map(({ label, queue, extra }) => {
72
+ ctx.wsReqNumber += 1;
73
+ return {
74
+ app_id: '772021112871879',
75
+ payload: JSON.stringify({
76
+ epoch_id: parseInt(utils.generateOfflineThreadingID()),
77
+ tasks: [makeTask(label, queue, extra)],
78
+ version_id: '24227364673632991',
79
+ }),
80
+ //pwa_version: '1',
81
+ request_id: ctx.wsReqNumber,
82
+ type: 3,
83
+ };
84
+ });
85
+
86
+ try {
87
+ messages.forEach((msg, idx) => {
88
+ ctx.mqttClient.publish(
89
+ '/ls_req',
90
+ JSON.stringify(msg),
91
+ { qos: 1, retain: false },
92
+ idx === messages.length - 1 && callback ? callback : undefined
93
+ );
94
+ });
95
+ } catch (err) {
96
+ if (callback) callback(err);
97
+ else throw err;
98
+ }
99
+
100
+ return returnPromise;
101
+ };
275
102
  };
276
103
  /** Developed by Sheikh Tamim | GitHub: sheikhtamimlover | Please give credits if reused. */
@@ -0,0 +1,133 @@
1
+ /**
2
+ * ===========================================================
3
+ * 💫 META THEME GENERATOR MODULE 💫
4
+ * ===========================================================
5
+ * 🧑‍💻 Author: Sheikh Tamim (ST | Sheikh Tamim)
6
+ * 🔰 Owner & Developer
7
+ * 🌐 GitHub: https://github.com/sheikhtamimlover
8
+ * 📸 Instagram: https://instagram.com/sheikh.tamim_lover
9
+ * 🧠 Description:
10
+ * This module generates beautiful Messenger AI themes
11
+ * using Meta's hidden GraphQL endpoints. It allows you to
12
+ * create unique chat themes based on your custom prompt
13
+ * or optional image inspiration.
14
+ * -----------------------------------------------------------
15
+ * ⚙️ Features:
16
+ * • Generate AI-based Messenger chat themes.
17
+ * • Custom prompt & optional image URL input.
18
+ * • Returns structured theme data with full color mapping.
19
+ * -----------------------------------------------------------
20
+ * 🕊️ Respect the creator & give proper credits if reused.
21
+ * ===========================================================
22
+ */
23
+
24
+ "use strict";
25
+
26
+ var utils = require("../utils");
27
+ var log = require("npmlog");
28
+
29
+ module.exports = function (defaultFuncs, api, ctx) {
30
+ /** Developed by Sheikh Tamim | GitHub: sheikhtamimlover | Instagram: @sheikh.tamim_lover */
31
+ return function suggestFriend(count, cursor, callback) {
32
+ var resolveFunc = function () { };
33
+ var rejectFunc = function () { };
34
+ var returnPromise = new Promise(function (resolve, reject) {
35
+ resolveFunc = resolve;
36
+ rejectFunc = reject;
37
+ });
38
+
39
+ if (!callback) {
40
+ callback = function (err, data) {
41
+ if (err) return rejectFunc(err);
42
+ resolveFunc(data);
43
+ };
44
+ }
45
+
46
+ if (typeof count === 'function') {
47
+ callback = count;
48
+ count = 30;
49
+ cursor = null;
50
+ }
51
+
52
+ if (typeof cursor === 'function') {
53
+ callback = cursor;
54
+ cursor = null;
55
+ }
56
+
57
+ count = count || 30;
58
+
59
+ var form = {
60
+ av: ctx.userID,
61
+ __aaid: 0,
62
+ __user: ctx.userID,
63
+ __a: 1,
64
+ __req: utils.getSignatureID(),
65
+ __hs: "20405.HYP:comet_pkg.2.1...0",
66
+ dpr: 1,
67
+ __ccg: "EXCELLENT",
68
+ __rev: "1029835515",
69
+ __s: utils.getSignatureID(),
70
+ __hsi: Date.now(),
71
+ __comet_req: 15,
72
+ fb_dtsg: ctx.fb_dtsg,
73
+ jazoest: ctx.ttstamp,
74
+ lsd: ctx.fb_dtsg,
75
+ __spin_r: "1029835515",
76
+ __spin_b: "trunk",
77
+ __spin_t: Date.now(),
78
+ __crn: "comet.fbweb.CometPYMKSuggestionsRoute",
79
+ fb_api_caller_class: "RelayModern",
80
+ fb_api_req_friendly_name: "FriendingCometPYMKPanelPaginationQuery",
81
+ server_timestamps: true,
82
+ variables: JSON.stringify({
83
+ count: count,
84
+ cursor: cursor,
85
+ location: "FRIENDS_HOME_MAIN",
86
+ scale: 3
87
+ }),
88
+ doc_id: "9917809191634193"
89
+ };
90
+
91
+ defaultFuncs
92
+ .post("https://www.facebook.com/api/graphql/", ctx.jar, form)
93
+ .then(utils.parseAndCheckLogin(ctx, defaultFuncs))
94
+ .then(function (resData) {
95
+ if (resData.error) {
96
+ throw resData;
97
+ }
98
+
99
+ if (resData.data && resData.data.viewer && resData.data.viewer.people_you_may_know) {
100
+ var pymkData = resData.data.viewer.people_you_may_know;
101
+ var suggestions = pymkData.edges.map(function (edge) {
102
+ var node = edge.node;
103
+ return {
104
+ id: node.id,
105
+ name: node.name,
106
+ url: node.url,
107
+ friendshipStatus: node.friendship_status,
108
+ profilePicture: node.profile_picture ? node.profile_picture.uri : null,
109
+ mutualFriends: node.social_context ? node.social_context.text : "",
110
+ topMutualFriends: node.social_context_top_mutual_friends || []
111
+ };
112
+ });
113
+
114
+ var result = {
115
+ suggestions: suggestions,
116
+ hasNextPage: pymkData.page_info.has_next_page,
117
+ endCursor: pymkData.page_info.end_cursor
118
+ };
119
+
120
+ return callback(null, result);
121
+ } else {
122
+ return callback({ error: "Invalid response format" });
123
+ }
124
+ })
125
+ .catch(function (err) {
126
+ log.error("suggestFriend", err);
127
+ return callback(err);
128
+ });
129
+
130
+ return returnPromise;
131
+ };
132
+ };
133
+ /** Developed by Sheikh Tamim | GitHub: sheikhtamimlover | Please give credits if reused. */