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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bb-fca",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.12",
|
|
4
4
|
"description": "BB-FCA is a powerful and user-friendly Facebook Chat API wrapper for Node.js, designed to simplify the process of creating chatbots and automating interactions on Facebook Messenger. With BB-FCA, developers can easily send messages, manage conversations, and interact with the Facebook Messenger platform using a simple and intuitive API.",
|
|
5
5
|
"main": "dist/core/client.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import utils = require('../../../utils');
|
|
2
|
+
// @NethWs3Dev
|
|
3
|
+
|
|
4
|
+
const allowedProperties = {
|
|
5
|
+
attachment: true,
|
|
6
|
+
url: true,
|
|
7
|
+
sticker: true,
|
|
8
|
+
emoji: true,
|
|
9
|
+
emojiSize: true,
|
|
10
|
+
body: true,
|
|
11
|
+
mentions: true,
|
|
12
|
+
location: true,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default function sendPageMessage(
|
|
16
|
+
defaultFuncs: any,
|
|
17
|
+
api: any,
|
|
18
|
+
ctx: any,
|
|
19
|
+
): Function {
|
|
20
|
+
async function uploadAttachment(attachments: any[]): Promise<any[]> {
|
|
21
|
+
const uploads: any[] = [];
|
|
22
|
+
for (let i = 0; i < attachments.length; i++) {
|
|
23
|
+
if (!utils.isReadableStream(attachments[i])) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
'Attachment should be a readable stream and not ' +
|
|
26
|
+
utils.getType(attachments[i]) +
|
|
27
|
+
'.',
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
const oksir = await defaultFuncs
|
|
31
|
+
.postFormData(
|
|
32
|
+
'https://upload.facebook.com/ajax/mercury/upload.php',
|
|
33
|
+
ctx.jar,
|
|
34
|
+
{
|
|
35
|
+
upload_1024: attachments[i],
|
|
36
|
+
voice_clip: 'true',
|
|
37
|
+
},
|
|
38
|
+
{},
|
|
39
|
+
)
|
|
40
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs));
|
|
41
|
+
if (oksir.error) {
|
|
42
|
+
throw new Error(oksir.error);
|
|
43
|
+
}
|
|
44
|
+
uploads.push(oksir.payload.metadata[0]);
|
|
45
|
+
}
|
|
46
|
+
return uploads;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async function getUrl(url: string): Promise<any> {
|
|
50
|
+
const resData = await defaultFuncs
|
|
51
|
+
.post(
|
|
52
|
+
'https://www.facebook.com/message_share_attachment/fromURI/',
|
|
53
|
+
ctx.jar,
|
|
54
|
+
{
|
|
55
|
+
image_height: 960,
|
|
56
|
+
image_width: 960,
|
|
57
|
+
uri: url,
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs));
|
|
61
|
+
if (!resData || resData.error || !resData.payload) {
|
|
62
|
+
throw new Error(resData);
|
|
63
|
+
}
|
|
64
|
+
return resData.payload;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function sendContent(
|
|
68
|
+
form: Record<string, any>,
|
|
69
|
+
threadID: any,
|
|
70
|
+
): Promise<any> {
|
|
71
|
+
const resData = await defaultFuncs
|
|
72
|
+
.post('https://www.facebook.com/messaging/send/', ctx.jar, form)
|
|
73
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs));
|
|
74
|
+
|
|
75
|
+
if (!resData) {
|
|
76
|
+
throw new Error('Send page message failed.');
|
|
77
|
+
}
|
|
78
|
+
if (resData.error) {
|
|
79
|
+
if (resData.error === 1545012) {
|
|
80
|
+
utils.warn(
|
|
81
|
+
'sendMessage',
|
|
82
|
+
"Got error 1545012. This might mean that you're not part of the conversation " +
|
|
83
|
+
threadID,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
throw new Error(JSON.stringify(resData));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Facebook frequently changes this payload response format. Try to parse actions if available
|
|
90
|
+
if (resData.payload && resData.payload.actions) {
|
|
91
|
+
const messageInfo = resData.payload.actions.reduce((p: any, v: any) => {
|
|
92
|
+
return {
|
|
93
|
+
threadID: v.thread_fbid,
|
|
94
|
+
messageID: v.message_id,
|
|
95
|
+
timestamp: v.timestamp,
|
|
96
|
+
};
|
|
97
|
+
}, null);
|
|
98
|
+
return messageInfo;
|
|
99
|
+
}
|
|
100
|
+
return resData;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return async function sendPageMessageImpl(
|
|
104
|
+
msg: any,
|
|
105
|
+
receiverID: string | number,
|
|
106
|
+
senderID: string | number,
|
|
107
|
+
replyToMessage?: string,
|
|
108
|
+
): Promise<any> {
|
|
109
|
+
const msgType = utils.getType(msg);
|
|
110
|
+
const receiverIDType = utils.getType(receiverID);
|
|
111
|
+
const senderIDType = utils.getType(senderID);
|
|
112
|
+
const messageIDType = utils.getType(replyToMessage);
|
|
113
|
+
|
|
114
|
+
if (senderIDType !== 'String' && senderIDType !== 'Number') {
|
|
115
|
+
throw new Error('senderID (Page ID) must be of type string or number.');
|
|
116
|
+
}
|
|
117
|
+
const pageID = String(senderID);
|
|
118
|
+
const threadID = String(receiverID);
|
|
119
|
+
|
|
120
|
+
if (msgType !== 'String' && msgType !== 'Object')
|
|
121
|
+
throw new Error(
|
|
122
|
+
'Message should be of type string or object and not ' + msgType + '.',
|
|
123
|
+
);
|
|
124
|
+
// Usually Page sends message to exactly 1 user (the customer)
|
|
125
|
+
if (receiverIDType !== 'Number' && receiverIDType !== 'String')
|
|
126
|
+
throw new Error(
|
|
127
|
+
'receiverID should be of type number, string and not ' +
|
|
128
|
+
receiverIDType +
|
|
129
|
+
'.',
|
|
130
|
+
);
|
|
131
|
+
if (replyToMessage && messageIDType !== 'String')
|
|
132
|
+
throw new Error(
|
|
133
|
+
'MessageID should be of type string and not ' + messageIDType + '.',
|
|
134
|
+
);
|
|
135
|
+
if (msgType === 'String') {
|
|
136
|
+
msg = { body: msg };
|
|
137
|
+
}
|
|
138
|
+
const disallowedProperties = Object.keys(msg).filter(
|
|
139
|
+
(prop) => !(allowedProperties as any)[prop],
|
|
140
|
+
);
|
|
141
|
+
if (disallowedProperties.length > 0) {
|
|
142
|
+
throw new Error(
|
|
143
|
+
'Disallowed props: `' + disallowedProperties.join(', ') + '`',
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const messageAndOTID = utils.generateOfflineThreadingID();
|
|
148
|
+
|
|
149
|
+
// Construct payload specifically based on Unified Inbox schema
|
|
150
|
+
const form: Record<string, any> = {
|
|
151
|
+
av: pageID,
|
|
152
|
+
client: 'mercury',
|
|
153
|
+
action_type: 'ma-type:user-generated-message',
|
|
154
|
+
...(msg.body && { body: msg.body }),
|
|
155
|
+
ephemeral_ttl_mode: '0',
|
|
156
|
+
has_attachment: !!(msg.attachment || msg.url || msg.sticker),
|
|
157
|
+
message_id: messageAndOTID,
|
|
158
|
+
offline_threading_id: messageAndOTID,
|
|
159
|
+
other_user_fbid: threadID,
|
|
160
|
+
source: 'source:page_unified_inbox',
|
|
161
|
+
'specific_to_list[0]': 'fbid:' + threadID,
|
|
162
|
+
'specific_to_list[1]': 'fbid:' + pageID,
|
|
163
|
+
timestamp: Date.now(),
|
|
164
|
+
request_user_id: pageID,
|
|
165
|
+
// Default function post/method wraps _user, _a, fb_dtsg inherently if the environment config is valid.
|
|
166
|
+
...(replyToMessage && {
|
|
167
|
+
replied_to_message_id: replyToMessage,
|
|
168
|
+
}),
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
if (msg.location) {
|
|
172
|
+
if (!msg.location.latitude || !msg.location.longitude)
|
|
173
|
+
throw new Error('location property needs both latitude and longitude');
|
|
174
|
+
form['location_attachment[coordinates][latitude]'] =
|
|
175
|
+
msg.location.latitude;
|
|
176
|
+
form['location_attachment[coordinates][longitude]'] =
|
|
177
|
+
msg.location.longitude;
|
|
178
|
+
form['location_attachment[is_current_location]'] = !!msg.location.current;
|
|
179
|
+
}
|
|
180
|
+
if (msg.sticker) {
|
|
181
|
+
form['sticker_id'] = msg.sticker;
|
|
182
|
+
}
|
|
183
|
+
if (msg.attachment) {
|
|
184
|
+
form.image_ids = [];
|
|
185
|
+
form.gif_ids = [];
|
|
186
|
+
form.file_ids = [];
|
|
187
|
+
form.video_ids = [];
|
|
188
|
+
form.audio_ids = [];
|
|
189
|
+
if (utils.getType(msg.attachment) !== 'Array') {
|
|
190
|
+
msg.attachment = [msg.attachment];
|
|
191
|
+
}
|
|
192
|
+
const files = await uploadAttachment(msg.attachment);
|
|
193
|
+
files.forEach((file) => {
|
|
194
|
+
const type = Object.keys(file)[0];
|
|
195
|
+
form['' + type + 's'].push(file[type]);
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
if (msg.url) {
|
|
199
|
+
form['shareable_attachment[share_type]'] = '100';
|
|
200
|
+
const params = await getUrl(msg.url);
|
|
201
|
+
form['shareable_attachment[share_params]'] = params;
|
|
202
|
+
}
|
|
203
|
+
if (msg.emoji) {
|
|
204
|
+
if (!msg.emojiSize) {
|
|
205
|
+
msg.emojiSize = 'medium';
|
|
206
|
+
}
|
|
207
|
+
if (
|
|
208
|
+
msg.emojiSize !== 'small' &&
|
|
209
|
+
msg.emojiSize !== 'medium' &&
|
|
210
|
+
msg.emojiSize !== 'large'
|
|
211
|
+
) {
|
|
212
|
+
throw new Error('emojiSize property is invalid');
|
|
213
|
+
}
|
|
214
|
+
if (!form.body) {
|
|
215
|
+
throw new Error('body is not empty');
|
|
216
|
+
}
|
|
217
|
+
form.body = msg.emoji;
|
|
218
|
+
form['tags[0]'] = 'hot_emoji_size:' + msg.emojiSize;
|
|
219
|
+
}
|
|
220
|
+
if (msg.mentions) {
|
|
221
|
+
for (let i = 0; i < msg.mentions.length; i++) {
|
|
222
|
+
const mention = msg.mentions[i];
|
|
223
|
+
const tag = mention.tag;
|
|
224
|
+
if (typeof tag !== 'string') {
|
|
225
|
+
throw new Error('Mention tags must be strings.');
|
|
226
|
+
}
|
|
227
|
+
const offset = msg.body.indexOf(tag, mention.fromIndex || 0);
|
|
228
|
+
if (offset < 0)
|
|
229
|
+
utils.warn(
|
|
230
|
+
'handleMention',
|
|
231
|
+
'Mention for "' + tag + '" not found in message string.',
|
|
232
|
+
);
|
|
233
|
+
if (!mention.id)
|
|
234
|
+
utils.warn('handleMention', 'Mention id should be non-null.');
|
|
235
|
+
const id = mention.id || 0;
|
|
236
|
+
const emptyChar = '\u200E';
|
|
237
|
+
form['body'] = emptyChar + msg.body;
|
|
238
|
+
form['profile_xmd[' + i + '][offset]'] = offset + 1;
|
|
239
|
+
form['profile_xmd[' + i + '][length]'] = tag.length;
|
|
240
|
+
form['profile_xmd[' + i + '][id]'] = id;
|
|
241
|
+
form['profile_xmd[' + i + '][type]'] = 'p';
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return await sendContent(form, threadID);
|
|
245
|
+
};
|
|
246
|
+
}
|