bb-fca 2.0.10 → 2.0.12
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/deltas/apis/messaging/sendPageMessage.js +197 -0
- package/dist/deltas/apis/messaging/sendPageMessage.js.map +1 -0
- package/dist/deltas/apis/posting/group.js +407 -0
- package/dist/deltas/apis/posting/group.js.map +1 -1
- package/dist/deltas/apis/threads/getPageThreadList.js +207 -0
- package/dist/deltas/apis/threads/getPageThreadList.js.map +1 -0
- package/dist/deltas/apis/users/getManagedPages.js +84 -0
- package/dist/deltas/apis/users/getManagedPages.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/types/deltas/apis/messaging/sendPageMessage.d.ts +1 -0
- package/dist/types/deltas/apis/posting/group.d.ts +88 -0
- package/dist/types/deltas/apis/threads/getPageThreadList.d.ts +7 -0
- package/dist/types/deltas/apis/users/getManagedPages.d.ts +1 -0
- package/dist/utils/clients.js +2 -1
- package/dist/utils/clients.js.map +1 -1
- package/dist/utils/index.js +4 -4
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/src/deltas/apis/messaging/sendPageMessage.ts +246 -0
- package/src/deltas/apis/posting/group.ts +480 -0
- package/src/deltas/apis/threads/getPageThreadList.ts +239 -0
- package/src/deltas/apis/users/getManagedPages.ts +94 -0
- package/src/types/index.d.ts +26 -0
- package/src/utils/clients.ts +2 -1
- package/src/utils/index.ts +4 -4
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = sendPageMessage;
|
|
4
|
+
const utils = require("../../../utils");
|
|
5
|
+
// @NethWs3Dev
|
|
6
|
+
const allowedProperties = {
|
|
7
|
+
attachment: true,
|
|
8
|
+
url: true,
|
|
9
|
+
sticker: true,
|
|
10
|
+
emoji: true,
|
|
11
|
+
emojiSize: true,
|
|
12
|
+
body: true,
|
|
13
|
+
mentions: true,
|
|
14
|
+
location: true,
|
|
15
|
+
};
|
|
16
|
+
function sendPageMessage(defaultFuncs, api, ctx) {
|
|
17
|
+
async function uploadAttachment(attachments) {
|
|
18
|
+
const uploads = [];
|
|
19
|
+
for (let i = 0; i < attachments.length; i++) {
|
|
20
|
+
if (!utils.isReadableStream(attachments[i])) {
|
|
21
|
+
throw new Error('Attachment should be a readable stream and not ' +
|
|
22
|
+
utils.getType(attachments[i]) +
|
|
23
|
+
'.');
|
|
24
|
+
}
|
|
25
|
+
const oksir = await defaultFuncs
|
|
26
|
+
.postFormData('https://upload.facebook.com/ajax/mercury/upload.php', ctx.jar, {
|
|
27
|
+
upload_1024: attachments[i],
|
|
28
|
+
voice_clip: 'true',
|
|
29
|
+
}, {})
|
|
30
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs));
|
|
31
|
+
if (oksir.error) {
|
|
32
|
+
throw new Error(oksir.error);
|
|
33
|
+
}
|
|
34
|
+
uploads.push(oksir.payload.metadata[0]);
|
|
35
|
+
}
|
|
36
|
+
return uploads;
|
|
37
|
+
}
|
|
38
|
+
async function getUrl(url) {
|
|
39
|
+
const resData = await defaultFuncs
|
|
40
|
+
.post('https://www.facebook.com/message_share_attachment/fromURI/', ctx.jar, {
|
|
41
|
+
image_height: 960,
|
|
42
|
+
image_width: 960,
|
|
43
|
+
uri: url,
|
|
44
|
+
})
|
|
45
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs));
|
|
46
|
+
if (!resData || resData.error || !resData.payload) {
|
|
47
|
+
throw new Error(resData);
|
|
48
|
+
}
|
|
49
|
+
return resData.payload;
|
|
50
|
+
}
|
|
51
|
+
async function sendContent(form, threadID) {
|
|
52
|
+
const resData = await defaultFuncs
|
|
53
|
+
.post('https://www.facebook.com/messaging/send/', ctx.jar, form)
|
|
54
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs));
|
|
55
|
+
if (!resData) {
|
|
56
|
+
throw new Error('Send page message failed.');
|
|
57
|
+
}
|
|
58
|
+
if (resData.error) {
|
|
59
|
+
if (resData.error === 1545012) {
|
|
60
|
+
utils.warn('sendMessage', "Got error 1545012. This might mean that you're not part of the conversation " +
|
|
61
|
+
threadID);
|
|
62
|
+
}
|
|
63
|
+
throw new Error(JSON.stringify(resData));
|
|
64
|
+
}
|
|
65
|
+
// Facebook frequently changes this payload response format. Try to parse actions if available
|
|
66
|
+
if (resData.payload && resData.payload.actions) {
|
|
67
|
+
const messageInfo = resData.payload.actions.reduce((p, v) => {
|
|
68
|
+
return {
|
|
69
|
+
threadID: v.thread_fbid,
|
|
70
|
+
messageID: v.message_id,
|
|
71
|
+
timestamp: v.timestamp,
|
|
72
|
+
};
|
|
73
|
+
}, null);
|
|
74
|
+
return messageInfo;
|
|
75
|
+
}
|
|
76
|
+
return resData;
|
|
77
|
+
}
|
|
78
|
+
return async function sendPageMessageImpl(msg, receiverID, senderID, replyToMessage) {
|
|
79
|
+
const msgType = utils.getType(msg);
|
|
80
|
+
const receiverIDType = utils.getType(receiverID);
|
|
81
|
+
const senderIDType = utils.getType(senderID);
|
|
82
|
+
const messageIDType = utils.getType(replyToMessage);
|
|
83
|
+
if (senderIDType !== 'String' && senderIDType !== 'Number') {
|
|
84
|
+
throw new Error('senderID (Page ID) must be of type string or number.');
|
|
85
|
+
}
|
|
86
|
+
const pageID = String(senderID);
|
|
87
|
+
const threadID = String(receiverID);
|
|
88
|
+
if (msgType !== 'String' && msgType !== 'Object')
|
|
89
|
+
throw new Error('Message should be of type string or object and not ' + msgType + '.');
|
|
90
|
+
// Usually Page sends message to exactly 1 user (the customer)
|
|
91
|
+
if (receiverIDType !== 'Number' && receiverIDType !== 'String')
|
|
92
|
+
throw new Error('receiverID should be of type number, string and not ' +
|
|
93
|
+
receiverIDType +
|
|
94
|
+
'.');
|
|
95
|
+
if (replyToMessage && messageIDType !== 'String')
|
|
96
|
+
throw new Error('MessageID should be of type string and not ' + messageIDType + '.');
|
|
97
|
+
if (msgType === 'String') {
|
|
98
|
+
msg = { body: msg };
|
|
99
|
+
}
|
|
100
|
+
const disallowedProperties = Object.keys(msg).filter((prop) => !allowedProperties[prop]);
|
|
101
|
+
if (disallowedProperties.length > 0) {
|
|
102
|
+
throw new Error('Disallowed props: `' + disallowedProperties.join(', ') + '`');
|
|
103
|
+
}
|
|
104
|
+
const messageAndOTID = utils.generateOfflineThreadingID();
|
|
105
|
+
// Construct payload specifically based on Unified Inbox schema
|
|
106
|
+
const form = {
|
|
107
|
+
av: pageID,
|
|
108
|
+
client: 'mercury',
|
|
109
|
+
action_type: 'ma-type:user-generated-message',
|
|
110
|
+
...(msg.body && { body: msg.body }),
|
|
111
|
+
ephemeral_ttl_mode: '0',
|
|
112
|
+
has_attachment: !!(msg.attachment || msg.url || msg.sticker),
|
|
113
|
+
message_id: messageAndOTID,
|
|
114
|
+
offline_threading_id: messageAndOTID,
|
|
115
|
+
other_user_fbid: threadID,
|
|
116
|
+
source: 'source:page_unified_inbox',
|
|
117
|
+
'specific_to_list[0]': 'fbid:' + threadID,
|
|
118
|
+
'specific_to_list[1]': 'fbid:' + pageID,
|
|
119
|
+
timestamp: Date.now(),
|
|
120
|
+
request_user_id: pageID,
|
|
121
|
+
// Default function post/method wraps _user, _a, fb_dtsg inherently if the environment config is valid.
|
|
122
|
+
...(replyToMessage && {
|
|
123
|
+
replied_to_message_id: replyToMessage,
|
|
124
|
+
}),
|
|
125
|
+
};
|
|
126
|
+
if (msg.location) {
|
|
127
|
+
if (!msg.location.latitude || !msg.location.longitude)
|
|
128
|
+
throw new Error('location property needs both latitude and longitude');
|
|
129
|
+
form['location_attachment[coordinates][latitude]'] =
|
|
130
|
+
msg.location.latitude;
|
|
131
|
+
form['location_attachment[coordinates][longitude]'] =
|
|
132
|
+
msg.location.longitude;
|
|
133
|
+
form['location_attachment[is_current_location]'] = !!msg.location.current;
|
|
134
|
+
}
|
|
135
|
+
if (msg.sticker) {
|
|
136
|
+
form['sticker_id'] = msg.sticker;
|
|
137
|
+
}
|
|
138
|
+
if (msg.attachment) {
|
|
139
|
+
form.image_ids = [];
|
|
140
|
+
form.gif_ids = [];
|
|
141
|
+
form.file_ids = [];
|
|
142
|
+
form.video_ids = [];
|
|
143
|
+
form.audio_ids = [];
|
|
144
|
+
if (utils.getType(msg.attachment) !== 'Array') {
|
|
145
|
+
msg.attachment = [msg.attachment];
|
|
146
|
+
}
|
|
147
|
+
const files = await uploadAttachment(msg.attachment);
|
|
148
|
+
files.forEach((file) => {
|
|
149
|
+
const type = Object.keys(file)[0];
|
|
150
|
+
form['' + type + 's'].push(file[type]);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
if (msg.url) {
|
|
154
|
+
form['shareable_attachment[share_type]'] = '100';
|
|
155
|
+
const params = await getUrl(msg.url);
|
|
156
|
+
form['shareable_attachment[share_params]'] = params;
|
|
157
|
+
}
|
|
158
|
+
if (msg.emoji) {
|
|
159
|
+
if (!msg.emojiSize) {
|
|
160
|
+
msg.emojiSize = 'medium';
|
|
161
|
+
}
|
|
162
|
+
if (msg.emojiSize !== 'small' &&
|
|
163
|
+
msg.emojiSize !== 'medium' &&
|
|
164
|
+
msg.emojiSize !== 'large') {
|
|
165
|
+
throw new Error('emojiSize property is invalid');
|
|
166
|
+
}
|
|
167
|
+
if (!form.body) {
|
|
168
|
+
throw new Error('body is not empty');
|
|
169
|
+
}
|
|
170
|
+
form.body = msg.emoji;
|
|
171
|
+
form['tags[0]'] = 'hot_emoji_size:' + msg.emojiSize;
|
|
172
|
+
}
|
|
173
|
+
if (msg.mentions) {
|
|
174
|
+
for (let i = 0; i < msg.mentions.length; i++) {
|
|
175
|
+
const mention = msg.mentions[i];
|
|
176
|
+
const tag = mention.tag;
|
|
177
|
+
if (typeof tag !== 'string') {
|
|
178
|
+
throw new Error('Mention tags must be strings.');
|
|
179
|
+
}
|
|
180
|
+
const offset = msg.body.indexOf(tag, mention.fromIndex || 0);
|
|
181
|
+
if (offset < 0)
|
|
182
|
+
utils.warn('handleMention', 'Mention for "' + tag + '" not found in message string.');
|
|
183
|
+
if (!mention.id)
|
|
184
|
+
utils.warn('handleMention', 'Mention id should be non-null.');
|
|
185
|
+
const id = mention.id || 0;
|
|
186
|
+
const emptyChar = '\u200E';
|
|
187
|
+
form['body'] = emptyChar + msg.body;
|
|
188
|
+
form['profile_xmd[' + i + '][offset]'] = offset + 1;
|
|
189
|
+
form['profile_xmd[' + i + '][length]'] = tag.length;
|
|
190
|
+
form['profile_xmd[' + i + '][id]'] = id;
|
|
191
|
+
form['profile_xmd[' + i + '][type]'] = 'p';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return await sendContent(form, threadID);
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=sendPageMessage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sendPageMessage.js","sourceRoot":"","sources":["../../../../src/deltas/apis/messaging/sendPageMessage.ts"],"names":[],"mappings":";;AAcA,kCAuOC;AArPD,wCAAyC;AACzC,cAAc;AAEd,MAAM,iBAAiB,GAAG;IACxB,UAAU,EAAE,IAAI;IAChB,GAAG,EAAE,IAAI;IACT,OAAO,EAAE,IAAI;IACb,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,IAAI;IACf,IAAI,EAAE,IAAI;IACV,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;CACf,CAAC;AAEF,SAAwB,eAAe,CACrC,YAAiB,EACjB,GAAQ,EACR,GAAQ;IAER,KAAK,UAAU,gBAAgB,CAAC,WAAkB;QAChD,MAAM,OAAO,GAAU,EAAE,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5C,MAAM,IAAI,KAAK,CACb,iDAAiD;oBAC/C,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;oBAC7B,GAAG,CACN,CAAC;YACJ,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,YAAY;iBAC7B,YAAY,CACX,qDAAqD,EACrD,GAAG,CAAC,GAAG,EACP;gBACE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;gBAC3B,UAAU,EAAE,MAAM;aACnB,EACD,EAAE,CACH;iBACA,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC;YACrD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC/B,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,UAAU,MAAM,CAAC,GAAW;QAC/B,MAAM,OAAO,GAAG,MAAM,YAAY;aAC/B,IAAI,CACH,4DAA4D,EAC5D,GAAG,CAAC,GAAG,EACP;YACE,YAAY,EAAE,GAAG;YACjB,WAAW,EAAE,GAAG;YAChB,GAAG,EAAE,GAAG;SACT,CACF;aACA,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC;QACrD,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,OAAO,CAAC,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,UAAU,WAAW,CACxB,IAAyB,EACzB,QAAa;QAEb,MAAM,OAAO,GAAG,MAAM,YAAY;aAC/B,IAAI,CAAC,0CAA0C,EAAE,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC;aAC/D,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC;QAErD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,IAAI,OAAO,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;gBAC9B,KAAK,CAAC,IAAI,CACR,aAAa,EACb,8EAA8E;oBAC5E,QAAQ,CACX,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3C,CAAC;QAED,8FAA8F;QAC9F,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,CAAM,EAAE,EAAE;gBACpE,OAAO;oBACL,QAAQ,EAAE,CAAC,CAAC,WAAW;oBACvB,SAAS,EAAE,CAAC,CAAC,UAAU;oBACvB,SAAS,EAAE,CAAC,CAAC,SAAS;iBACvB,CAAC;YACJ,CAAC,EAAE,IAAI,CAAC,CAAC;YACT,OAAO,WAAW,CAAC;QACrB,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,KAAK,UAAU,mBAAmB,CACvC,GAAQ,EACR,UAA2B,EAC3B,QAAyB,EACzB,cAAuB;QAEvB,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACnC,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACjD,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAEpD,IAAI,YAAY,KAAK,QAAQ,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChC,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;QAEpC,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,QAAQ;YAC9C,MAAM,IAAI,KAAK,CACb,qDAAqD,GAAG,OAAO,GAAG,GAAG,CACtE,CAAC;QACJ,8DAA8D;QAC9D,IAAI,cAAc,KAAK,QAAQ,IAAI,cAAc,KAAK,QAAQ;YAC5D,MAAM,IAAI,KAAK,CACb,sDAAsD;gBACpD,cAAc;gBACd,GAAG,CACN,CAAC;QACJ,IAAI,cAAc,IAAI,aAAa,KAAK,QAAQ;YAC9C,MAAM,IAAI,KAAK,CACb,6CAA6C,GAAG,aAAa,GAAG,GAAG,CACpE,CAAC;QACJ,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;YACzB,GAAG,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;QACtB,CAAC;QACD,MAAM,oBAAoB,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAClD,CAAC,IAAI,EAAE,EAAE,CAAC,CAAE,iBAAyB,CAAC,IAAI,CAAC,CAC5C,CAAC;QACF,IAAI,oBAAoB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CACb,qBAAqB,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAC9D,CAAC;QACJ,CAAC;QAED,MAAM,cAAc,GAAG,KAAK,CAAC,0BAA0B,EAAE,CAAC;QAE1D,+DAA+D;QAC/D,MAAM,IAAI,GAAwB;YAChC,EAAE,EAAE,MAAM;YACV,MAAM,EAAE,SAAS;YACjB,WAAW,EAAE,gCAAgC;YAC7C,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;YACnC,kBAAkB,EAAE,GAAG;YACvB,cAAc,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC;YAC5D,UAAU,EAAE,cAAc;YAC1B,oBAAoB,EAAE,cAAc;YACpC,eAAe,EAAE,QAAQ;YACzB,MAAM,EAAE,2BAA2B;YACnC,qBAAqB,EAAE,OAAO,GAAG,QAAQ;YACzC,qBAAqB,EAAE,OAAO,GAAG,MAAM;YACvC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,eAAe,EAAE,MAAM;YACvB,uGAAuG;YACvG,GAAG,CAAC,cAAc,IAAI;gBACpB,qBAAqB,EAAE,cAAc;aACtC,CAAC;SACH,CAAC;QAEF,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS;gBACnD,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;YACzE,IAAI,CAAC,4CAA4C,CAAC;gBAChD,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;YACxB,IAAI,CAAC,6CAA6C,CAAC;gBACjD,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;YACzB,IAAI,CAAC,0CAA0C,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;QAC5E,CAAC;QACD,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;YAChB,IAAI,CAAC,YAAY,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC;QACnC,CAAC;QACD,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;YAClB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;YACpB,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,OAAO,EAAE,CAAC;gBAC9C,GAAG,CAAC,UAAU,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACpC,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACrD,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBACrB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBAClC,IAAI,CAAC,EAAE,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACzC,CAAC,CAAC,CAAC;QACL,CAAC;QACD,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;YACZ,IAAI,CAAC,kCAAkC,CAAC,GAAG,KAAK,CAAC;YACjD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACrC,IAAI,CAAC,oCAAoC,CAAC,GAAG,MAAM,CAAC;QACtD,CAAC;QACD,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;gBACnB,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAC;YAC3B,CAAC;YACD,IACE,GAAG,CAAC,SAAS,KAAK,OAAO;gBACzB,GAAG,CAAC,SAAS,KAAK,QAAQ;gBAC1B,GAAG,CAAC,SAAS,KAAK,OAAO,EACzB,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;YACnD,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;YACD,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC;YACtB,IAAI,CAAC,SAAS,CAAC,GAAG,iBAAiB,GAAG,GAAG,CAAC,SAAS,CAAC;QACtD,CAAC;QACD,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;YACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7C,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAChC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;gBACxB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;oBAC5B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;gBACnD,CAAC;gBACD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC;gBAC7D,IAAI,MAAM,GAAG,CAAC;oBACZ,KAAK,CAAC,IAAI,CACR,eAAe,EACf,eAAe,GAAG,GAAG,GAAG,gCAAgC,CACzD,CAAC;gBACJ,IAAI,CAAC,OAAO,CAAC,EAAE;oBACb,KAAK,CAAC,IAAI,CAAC,eAAe,EAAE,gCAAgC,CAAC,CAAC;gBAChE,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;gBAC3B,MAAM,SAAS,GAAG,QAAQ,CAAC;gBAC3B,IAAI,CAAC,MAAM,CAAC,GAAG,SAAS,GAAG,GAAG,CAAC,IAAI,CAAC;gBACpC,IAAI,CAAC,cAAc,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;gBACpD,IAAI,CAAC,cAAc,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC;gBACpD,IAAI,CAAC,cAAc,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;gBACxC,IAAI,CAAC,cAAc,GAAG,CAAC,GAAG,SAAS,CAAC,GAAG,GAAG,CAAC;YAC7C,CAAC;QACH,CAAC;QACD,OAAO,MAAM,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC3C,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.default = default_1;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
4
38
|
const utils = require("../../../utils");
|
|
5
39
|
/**
|
|
6
40
|
* @namespace api.group
|
|
@@ -494,6 +528,379 @@ function default_1(defaultFuncs, api, ctx) {
|
|
|
494
528
|
hasNextPage: Boolean(pageInfo.has_next_page),
|
|
495
529
|
};
|
|
496
530
|
},
|
|
531
|
+
/**
|
|
532
|
+
* Resolves a Facebook share URL to the actual group ID.
|
|
533
|
+
*
|
|
534
|
+
* Accepts various formats:
|
|
535
|
+
* - Full URL: `https://www.facebook.com/share/g/14bKqsywAfu/`
|
|
536
|
+
* - Path only: `/share/g/14bKqsywAfu/`
|
|
537
|
+
* - Short key: `14bKqsywAfu`
|
|
538
|
+
*
|
|
539
|
+
* @param {string} shareUrl The share URL, path, or short key to resolve.
|
|
540
|
+
* @returns {Promise<{ groupID: string; name: string | null; url: string | null }>}
|
|
541
|
+
* The resolved group ID, name (if available), and canonical URL.
|
|
542
|
+
* @throws {Error} If the shareUrl is missing or the group ID cannot be extracted.
|
|
543
|
+
*
|
|
544
|
+
* @example
|
|
545
|
+
* const result = await api.group.resolveShareUrl('https://www.facebook.com/share/g/14bKqsywAfu/');
|
|
546
|
+
* console.log(result.groupID); // "1482314963016056"
|
|
547
|
+
*/
|
|
548
|
+
resolveShareUrl: async function (shareUrl) {
|
|
549
|
+
if (!shareUrl || typeof shareUrl !== 'string') {
|
|
550
|
+
throw new Error('resolveShareUrl: shareUrl must be a non-empty string.');
|
|
551
|
+
}
|
|
552
|
+
// Normalize input to a full URL
|
|
553
|
+
let fullUrl;
|
|
554
|
+
if (shareUrl.startsWith('http://') || shareUrl.startsWith('https://')) {
|
|
555
|
+
fullUrl = shareUrl;
|
|
556
|
+
}
|
|
557
|
+
else if (shareUrl.startsWith('/')) {
|
|
558
|
+
fullUrl = 'https://www.facebook.com' + shareUrl;
|
|
559
|
+
}
|
|
560
|
+
else {
|
|
561
|
+
// Assume it's just the short key
|
|
562
|
+
fullUrl = `https://www.facebook.com/share/g/${shareUrl}/`;
|
|
563
|
+
}
|
|
564
|
+
// Fetch the share page - Facebook will embed the group data in the HTML
|
|
565
|
+
const allJsonData = await utils.json(fullUrl, ctx.jar, null, ctx.globalOptions, ctx);
|
|
566
|
+
if (!allJsonData || allJsonData.length === 0) {
|
|
567
|
+
throw new Error('resolveShareUrl: Could not fetch data from the share URL.');
|
|
568
|
+
}
|
|
569
|
+
// Strategy 1: Look for group object with __typename "Group" in the JSON data
|
|
570
|
+
let groupID = null;
|
|
571
|
+
let groupName = null;
|
|
572
|
+
let groupUrl = null;
|
|
573
|
+
const groupObj = deepFind(allJsonData, (val, _key) => val &&
|
|
574
|
+
typeof val === 'object' &&
|
|
575
|
+
val.__typename === 'Group' &&
|
|
576
|
+
typeof val.id === 'string');
|
|
577
|
+
if (groupObj) {
|
|
578
|
+
groupID = groupObj.id;
|
|
579
|
+
groupName = groupObj.name || null;
|
|
580
|
+
groupUrl = groupObj.url || null;
|
|
581
|
+
}
|
|
582
|
+
// Strategy 2: Look for groupID in various data patterns
|
|
583
|
+
if (!groupID) {
|
|
584
|
+
const groupIdVal = deepFind(allJsonData, (val, key) => (key === 'groupID' || key === 'group_id') &&
|
|
585
|
+
typeof val === 'string' &&
|
|
586
|
+
/^\d+$/.test(val));
|
|
587
|
+
if (groupIdVal) {
|
|
588
|
+
groupID = groupIdVal;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
// Strategy 3: Look for meta property og:url or al:android:url containing group ID
|
|
592
|
+
if (!groupID) {
|
|
593
|
+
// Try to find the raw HTML response from the GET request
|
|
594
|
+
const res = await utils.get(fullUrl, ctx.jar, null, ctx.globalOptions, ctx);
|
|
595
|
+
const html = typeof res.body === 'string' ? res.body : String(res.body);
|
|
596
|
+
// Try og:url meta tag: <meta property="og:url" content="https://www.facebook.com/groups/XXXXXXX/" />
|
|
597
|
+
const ogUrlMatch = html.match(/property="og:url"\s+content="[^"]*\/groups\/(\d+)/);
|
|
598
|
+
if (ogUrlMatch) {
|
|
599
|
+
groupID = ogUrlMatch[1];
|
|
600
|
+
}
|
|
601
|
+
// Try al:android:url: fb://group/XXXXXXX
|
|
602
|
+
if (!groupID) {
|
|
603
|
+
const androidUrlMatch = html.match(/property="al:android:url"\s+content="fb:\/\/group\/(\d+)"/);
|
|
604
|
+
if (androidUrlMatch) {
|
|
605
|
+
groupID = androidUrlMatch[1];
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
// Try entity_id pattern in the HTML
|
|
609
|
+
if (!groupID) {
|
|
610
|
+
const entityIdMatch = html.match(/"entity_id":"(\d+)"/);
|
|
611
|
+
if (entityIdMatch) {
|
|
612
|
+
groupID = entityIdMatch[1];
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
// Try groupID in the URL of the final redirect
|
|
616
|
+
if (!groupID) {
|
|
617
|
+
const groupUrlMatch = html.match(/facebook\.com\/groups\/(\d+)/);
|
|
618
|
+
if (groupUrlMatch) {
|
|
619
|
+
groupID = groupUrlMatch[1];
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
// Extract group name from og:title if available
|
|
623
|
+
if (!groupName) {
|
|
624
|
+
const ogTitleMatch = html.match(/property="og:title"\s+content="([^"]*)"/);
|
|
625
|
+
if (ogTitleMatch) {
|
|
626
|
+
groupName = ogTitleMatch[1];
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
if (!groupID) {
|
|
631
|
+
throw new Error('resolveShareUrl: Could not extract group ID from the share URL. ' +
|
|
632
|
+
'The link may be invalid, expired, or require authentication.');
|
|
633
|
+
}
|
|
634
|
+
if (!groupUrl) {
|
|
635
|
+
groupUrl = `https://www.facebook.com/groups/${groupID}/`;
|
|
636
|
+
}
|
|
637
|
+
return {
|
|
638
|
+
groupID,
|
|
639
|
+
name: groupName,
|
|
640
|
+
url: groupUrl,
|
|
641
|
+
};
|
|
642
|
+
},
|
|
643
|
+
/**
|
|
644
|
+
* Uploads a photo to Facebook for use in group posts.
|
|
645
|
+
*
|
|
646
|
+
* The photo is uploaded to `upload.facebook.com` with the group discussion
|
|
647
|
+
* route context (`CometGroupDiscussionRoute`), making it ready to be
|
|
648
|
+
* attached to a group post via {@link createGroupPost}.
|
|
649
|
+
*
|
|
650
|
+
* @param {string | string[]} photoPaths - A single file path or an array of file paths to upload.
|
|
651
|
+
* @returns {Promise<{ photoID: string; uploadID: string; data: any }[]>}
|
|
652
|
+
* Array of upload results, one per photo, each containing:
|
|
653
|
+
* - `photoID` – The Facebook-assigned photo ID (use in `createGroupPost`).
|
|
654
|
+
* - `uploadID` – The client-generated upload ID.
|
|
655
|
+
* - `data` – The raw server response payload.
|
|
656
|
+
* @throws {Error} If any path is missing, not a string, or doesn't exist on disk.
|
|
657
|
+
*
|
|
658
|
+
* @example
|
|
659
|
+
* const [photo] = await api.group.uploadPhoto('/path/to/image.jpg');
|
|
660
|
+
* const post = await api.group.createGroupPost('123456789', {
|
|
661
|
+
* message: 'Check this out!',
|
|
662
|
+
* photos: [photo.photoID],
|
|
663
|
+
* });
|
|
664
|
+
*/
|
|
665
|
+
uploadPhoto: async function (photoPaths) {
|
|
666
|
+
const paths = Array.isArray(photoPaths) ? photoPaths : [photoPaths];
|
|
667
|
+
if (paths.length === 0) {
|
|
668
|
+
throw new Error('uploadPhoto: at least one photo path is required.');
|
|
669
|
+
}
|
|
670
|
+
const results = [];
|
|
671
|
+
for (const photoPath of paths) {
|
|
672
|
+
if (!photoPath || typeof photoPath !== 'string') {
|
|
673
|
+
throw new Error('uploadPhoto: each photo path must be a non-empty string.');
|
|
674
|
+
}
|
|
675
|
+
if (!fs.existsSync(photoPath)) {
|
|
676
|
+
throw new Error(`uploadPhoto: file not found: ${photoPath}`);
|
|
677
|
+
}
|
|
678
|
+
const photoStream = fs.createReadStream(photoPath);
|
|
679
|
+
const uploadId = `jsc_c_${Math.random().toString(36).substring(2, 11)}`;
|
|
680
|
+
// Build URL with query parameters matching the captured request
|
|
681
|
+
const url = new URL('https://upload.facebook.com/ajax/react_composer/attachments/photo/upload');
|
|
682
|
+
url.searchParams.append('av', ctx.userID);
|
|
683
|
+
url.searchParams.append('__aaid', '0');
|
|
684
|
+
url.searchParams.append('__user', ctx.userID);
|
|
685
|
+
url.searchParams.append('__a', '1');
|
|
686
|
+
url.searchParams.append('__req', '1');
|
|
687
|
+
url.searchParams.append('__hs', '20558.HCSV2:comet_pkg.2.1...0');
|
|
688
|
+
url.searchParams.append('dpr', '1');
|
|
689
|
+
url.searchParams.append('__ccg', 'EXCELLENT');
|
|
690
|
+
url.searchParams.append('__comet_req', '15');
|
|
691
|
+
url.searchParams.append('fb_dtsg', ctx.fb_dtsg);
|
|
692
|
+
url.searchParams.append('jazoest', ctx.jazoest);
|
|
693
|
+
url.searchParams.append('lsd', ctx.lsd || ctx.fb_dtsg);
|
|
694
|
+
url.searchParams.append('__spin_r', '1037381017');
|
|
695
|
+
url.searchParams.append('__spin_b', 'trunk');
|
|
696
|
+
url.searchParams.append('__spin_t', Math.floor(Date.now() / 1000).toString());
|
|
697
|
+
url.searchParams.append('__crn', 'comet.fbweb.CometGroupDiscussionRoute');
|
|
698
|
+
// Multipart form fields
|
|
699
|
+
const form = {
|
|
700
|
+
source: '8',
|
|
701
|
+
profile_id: ctx.userID,
|
|
702
|
+
waterfallxapp: 'comet',
|
|
703
|
+
farr: photoStream,
|
|
704
|
+
upload_id: uploadId,
|
|
705
|
+
};
|
|
706
|
+
const uploadResponse = await utils.postFormData(url.toString(), ctx.jar, form, ctx.globalOptions, ctx);
|
|
707
|
+
const uploadResult = JSON.parse(uploadResponse.body.toString().replace(/^for \(;;\);/, ''));
|
|
708
|
+
if (uploadResult.error || uploadResult.errors) {
|
|
709
|
+
throw new Error(JSON.stringify(uploadResult.error || uploadResult.errors));
|
|
710
|
+
}
|
|
711
|
+
const photoId = uploadResult.payload?.fbid ||
|
|
712
|
+
uploadResult.payload?.photoID ||
|
|
713
|
+
null;
|
|
714
|
+
results.push({
|
|
715
|
+
photoID: photoId,
|
|
716
|
+
uploadID: uploadId,
|
|
717
|
+
data: uploadResult,
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
return results;
|
|
721
|
+
},
|
|
722
|
+
/**
|
|
723
|
+
* Creates a post in a Facebook group, optionally with photo attachments and a title.
|
|
724
|
+
*
|
|
725
|
+
* @param {string} groupID - The ID of the group to post in.
|
|
726
|
+
* @param {object} options - Post options.
|
|
727
|
+
* @param {string} [options.message=''] - The text content of the post.
|
|
728
|
+
* @param {string} [options.title] - Optional post title (for groups that support titled posts).
|
|
729
|
+
* @param {string[]} [options.photos=[]] - Array of photo IDs from {@link uploadPhoto}.
|
|
730
|
+
* @returns {Promise<{ success: boolean; postID: string | null; url: string | null; data: any }>}
|
|
731
|
+
* @throws {Error} If groupID is missing or the API request fails.
|
|
732
|
+
*
|
|
733
|
+
* @example
|
|
734
|
+
* // Text-only post
|
|
735
|
+
* await api.group.createGroupPost('123456789', { message: 'Hello group!' });
|
|
736
|
+
*
|
|
737
|
+
* // Post with photos
|
|
738
|
+
* const photos = await api.group.uploadPhoto(['/path/a.jpg', '/path/b.jpg']);
|
|
739
|
+
* await api.group.createGroupPost('123456789', {
|
|
740
|
+
* message: 'Check these out!',
|
|
741
|
+
* photos: photos.map(p => p.photoID),
|
|
742
|
+
* });
|
|
743
|
+
*
|
|
744
|
+
* // Post with title and photos
|
|
745
|
+
* await api.group.createGroupPost('123456789', {
|
|
746
|
+
* message: 'Post body here',
|
|
747
|
+
* title: 'My Post Title',
|
|
748
|
+
* photos: photos.map(p => p.photoID),
|
|
749
|
+
* });
|
|
750
|
+
*/
|
|
751
|
+
createGroupPost: async function (groupID, options = {}) {
|
|
752
|
+
if (!groupID)
|
|
753
|
+
throw new Error('createGroupPost: groupID is required.');
|
|
754
|
+
const postMessage = options.message || '';
|
|
755
|
+
const postTitle = options.title || null;
|
|
756
|
+
const photos = options.photos || [];
|
|
757
|
+
const composerSessionId = createBsid();
|
|
758
|
+
const variables = {
|
|
759
|
+
input: {
|
|
760
|
+
composer_entry_point: 'inline_composer',
|
|
761
|
+
composer_source_surface: 'group',
|
|
762
|
+
composer_type: 'group',
|
|
763
|
+
logging: {
|
|
764
|
+
composer_session_id: composerSessionId,
|
|
765
|
+
},
|
|
766
|
+
source: 'WWW',
|
|
767
|
+
message: {
|
|
768
|
+
ranges: [],
|
|
769
|
+
text: postMessage,
|
|
770
|
+
},
|
|
771
|
+
with_tags_ids: null,
|
|
772
|
+
inline_activities: [],
|
|
773
|
+
text_format_preset_id: '0',
|
|
774
|
+
group_flair: {
|
|
775
|
+
flair_id: null,
|
|
776
|
+
},
|
|
777
|
+
composed_text: {
|
|
778
|
+
block_data: ['{}'],
|
|
779
|
+
block_depths: [0],
|
|
780
|
+
block_types: [0],
|
|
781
|
+
blocks: [postMessage],
|
|
782
|
+
entities: ['[]'],
|
|
783
|
+
entity_map: '{}',
|
|
784
|
+
inline_styles: ['[]'],
|
|
785
|
+
},
|
|
786
|
+
navigation_data: {
|
|
787
|
+
attribution_id_v2: `CometGroupDiscussionRoot.react,comet.group,tap_bookmark,${Date.now()},352021,${groupID},,`,
|
|
788
|
+
},
|
|
789
|
+
tracking: [null],
|
|
790
|
+
event_share_metadata: {
|
|
791
|
+
surface: 'newsfeed',
|
|
792
|
+
},
|
|
793
|
+
audience: {
|
|
794
|
+
to_id: groupID,
|
|
795
|
+
},
|
|
796
|
+
actor_id: ctx.userID,
|
|
797
|
+
client_mutation_id: Math.floor(Math.random() * 10 + 1).toString(),
|
|
798
|
+
},
|
|
799
|
+
feedLocation: 'GROUP',
|
|
800
|
+
feedbackSource: 0,
|
|
801
|
+
focusCommentID: null,
|
|
802
|
+
gridMediaWidth: null,
|
|
803
|
+
groupID: null,
|
|
804
|
+
scale: 1,
|
|
805
|
+
privacySelectorRenderLocation: 'COMET_STREAM',
|
|
806
|
+
checkPhotosToReelsUpsellEligibility: false,
|
|
807
|
+
referringStoryRenderLocation: null,
|
|
808
|
+
renderLocation: 'group',
|
|
809
|
+
useDefaultActor: false,
|
|
810
|
+
inviteShortLinkKey: null,
|
|
811
|
+
isFeed: false,
|
|
812
|
+
isFundraiser: false,
|
|
813
|
+
isFunFactPost: false,
|
|
814
|
+
isGroup: true,
|
|
815
|
+
isEvent: false,
|
|
816
|
+
isTimeline: false,
|
|
817
|
+
isSocialLearning: false,
|
|
818
|
+
isPageNewsFeed: false,
|
|
819
|
+
isProfileReviews: false,
|
|
820
|
+
isWorkSharedDraft: false,
|
|
821
|
+
canUserManageOffers: false,
|
|
822
|
+
__relay_internal__pv__CometUFIShareActionMigrationrelayprovider: true,
|
|
823
|
+
__relay_internal__pv__GHLShouldChangeSponsoredDataFieldNamerelayprovider: true,
|
|
824
|
+
__relay_internal__pv__GHLShouldChangeAdIdFieldNamerelayprovider: true,
|
|
825
|
+
__relay_internal__pv__CometUFI_dedicated_comment_routable_dialog_gkrelayprovider: true,
|
|
826
|
+
__relay_internal__pv__CometUFICommentAutoTranslationTyperelayprovider: 'ORIGINAL',
|
|
827
|
+
__relay_internal__pv__CometUFICommentAvatarStickerAnimatedImagerelayprovider: false,
|
|
828
|
+
__relay_internal__pv__CometUFICommentActionLinksRewriteEnabledrelayprovider: false,
|
|
829
|
+
__relay_internal__pv__IsWorkUserrelayprovider: false,
|
|
830
|
+
__relay_internal__pv__CometUFIReactionsEnableShortNamerelayprovider: false,
|
|
831
|
+
__relay_internal__pv__CometUFISingleLineUFIrelayprovider: false,
|
|
832
|
+
__relay_internal__pv__CometFeedStory_enable_post_permalink_white_space_clickrelayprovider: false,
|
|
833
|
+
__relay_internal__pv__TestPilotShouldIncludeDemoAdUseCaserelayprovider: false,
|
|
834
|
+
__relay_internal__pv__FBReels_deprecate_short_form_video_context_gkrelayprovider: true,
|
|
835
|
+
__relay_internal__pv__FBReels_enable_view_dubbed_audio_type_gkrelayprovider: true,
|
|
836
|
+
__relay_internal__pv__CometImmersivePhotoCanUserDisable3DMotionrelayprovider: false,
|
|
837
|
+
__relay_internal__pv__WorkCometIsEmployeeGKProviderrelayprovider: false,
|
|
838
|
+
__relay_internal__pv__IsMergQAPollsrelayprovider: false,
|
|
839
|
+
__relay_internal__pv__FBReelsMediaFooter_comet_enable_reels_ads_gkrelayprovider: true,
|
|
840
|
+
__relay_internal__pv__FBReelsIFUTileContent_reelsIFUPlayOnHoverrelayprovider: true,
|
|
841
|
+
__relay_internal__pv__GroupsCometGYSJFeedItemHeightrelayprovider: 150,
|
|
842
|
+
__relay_internal__pv__ShouldEnableBakedInTextStoriesrelayprovider: false,
|
|
843
|
+
__relay_internal__pv__StoriesShouldIncludeFbNotesrelayprovider: false,
|
|
844
|
+
__relay_internal__pv__groups_comet_use_glvrelayprovider: false,
|
|
845
|
+
__relay_internal__pv__GHLShouldChangeSponsoredAuctionDistanceFieldNamerelayprovider: false,
|
|
846
|
+
__relay_internal__pv__GHLShouldUseSponsoredAuctionLabelFieldNameV1relayprovider: false,
|
|
847
|
+
__relay_internal__pv__GHLShouldUseSponsoredAuctionLabelFieldNameV2relayprovider: false,
|
|
848
|
+
};
|
|
849
|
+
// Attach post title if provided
|
|
850
|
+
if (postTitle) {
|
|
851
|
+
variables.input.post_message_title = { text: postTitle };
|
|
852
|
+
}
|
|
853
|
+
// Attach photos if provided
|
|
854
|
+
if (photos.length > 0) {
|
|
855
|
+
variables.input.attachments = photos
|
|
856
|
+
.filter(Boolean)
|
|
857
|
+
.map((photoID) => ({
|
|
858
|
+
photo: { id: String(photoID) },
|
|
859
|
+
}));
|
|
860
|
+
}
|
|
861
|
+
const form = {
|
|
862
|
+
av: ctx.userID,
|
|
863
|
+
__aaid: '0',
|
|
864
|
+
__user: ctx.userID,
|
|
865
|
+
__a: '1',
|
|
866
|
+
__req: '1z',
|
|
867
|
+
__hs: '20558.HCSV2:comet_pkg.2.1...0',
|
|
868
|
+
dpr: '1',
|
|
869
|
+
__ccg: 'EXCELLENT',
|
|
870
|
+
__comet_req: '15',
|
|
871
|
+
locale: 'vi_VN',
|
|
872
|
+
fb_dtsg: ctx.fb_dtsg,
|
|
873
|
+
jazoest: ctx.jazoest,
|
|
874
|
+
lsd: ctx.lsd || ctx.fb_dtsg,
|
|
875
|
+
__spin_r: '1037381017',
|
|
876
|
+
__spin_b: 'trunk',
|
|
877
|
+
__spin_t: Math.floor(Date.now() / 1000).toString(),
|
|
878
|
+
__crn: 'comet.fbweb.CometGroupDiscussionRoute',
|
|
879
|
+
fb_api_caller_class: 'RelayModern',
|
|
880
|
+
fb_api_req_friendly_name: 'ComposerStoryCreateMutation',
|
|
881
|
+
variables: JSON.stringify(variables),
|
|
882
|
+
server_timestamps: 'true',
|
|
883
|
+
doc_id: '34999618373018994',
|
|
884
|
+
};
|
|
885
|
+
const customHeader = {
|
|
886
|
+
'x-fb-friendly-name': 'ComposerStoryCreateMutation',
|
|
887
|
+
'x-fb-lsd': ctx.lsd || '',
|
|
888
|
+
'x-asbd-id': '359341',
|
|
889
|
+
origin: 'https://www.facebook.com',
|
|
890
|
+
referer: `https://www.facebook.com/groups/${groupID}?locale=vi_VN`,
|
|
891
|
+
};
|
|
892
|
+
const res = await utils.post('https://www.facebook.com/api/graphql/', ctx.jar, form, ctx.globalOptions, ctx, customHeader);
|
|
893
|
+
const data = parseResponseBody(res.body);
|
|
894
|
+
if (data?.errors) {
|
|
895
|
+
throw new Error(JSON.stringify(data.errors));
|
|
896
|
+
}
|
|
897
|
+
return {
|
|
898
|
+
success: true,
|
|
899
|
+
postID: data?.data?.story_create?.story?.id || null,
|
|
900
|
+
url: data?.data?.story_create?.story?.url || null,
|
|
901
|
+
data,
|
|
902
|
+
};
|
|
903
|
+
},
|
|
497
904
|
};
|
|
498
905
|
return groupModule;
|
|
499
906
|
}
|