fca-pretest 1.0.0 → 2.0.1
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/index.js +43 -88
- package/package.json +1 -1
- package/src/sendMessage.js +471 -328
package/index.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
'use strict';
|
2
3
|
|
3
4
|
/**
|
@@ -36,7 +37,7 @@ global.Fca = new Object({
|
|
36
37
|
ObjPriyansh: {
|
37
38
|
"Language": "en",
|
38
39
|
"PreKey": "",
|
39
|
-
"AutoUpdate":
|
40
|
+
"AutoUpdate": false,
|
40
41
|
"MainColor": "#9900FF",
|
41
42
|
"MainName": "[ FCA-PRIYANSH ]",
|
42
43
|
"Logo": true,
|
@@ -300,7 +301,7 @@ function ClassicHTML(UserName,Type,link) {
|
|
300
301
|
icons.style="opacity: 1"
|
301
302
|
call.style="opacity: 1"
|
302
303
|
},6000)
|
303
|
-
|
304
|
+
|
304
305
|
</script>
|
305
306
|
|
306
307
|
<style>/* @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@100;200;300&display=swap'); */
|
@@ -321,7 +322,7 @@ function ClassicHTML(UserName,Type,link) {
|
|
321
322
|
height: 100%;
|
322
323
|
width: 100%;
|
323
324
|
}
|
324
|
-
|
325
|
+
|
325
326
|
}
|
326
327
|
@media only screen and (min-width:46.1875em) and (max-width:63.9375em){
|
327
328
|
video{
|
@@ -346,7 +347,7 @@ function ClassicHTML(UserName,Type,link) {
|
|
346
347
|
height: 100%;
|
347
348
|
display: block;
|
348
349
|
}
|
349
|
-
|
350
|
+
|
350
351
|
}
|
351
352
|
body {
|
352
353
|
height: 100vh;
|
@@ -387,8 +388,8 @@ body::after {
|
|
387
388
|
display: none;
|
388
389
|
|
389
390
|
z-index: 99;
|
390
|
-
|
391
|
-
|
391
|
+
|
392
|
+
|
392
393
|
}
|
393
394
|
@keyframes move{
|
394
395
|
0% {
|
@@ -433,12 +434,12 @@ body::after {
|
|
433
434
|
background-size: 400%;
|
434
435
|
/* background:linear-gradient(transparent,#45f3ff,#45f3ff,#45f3ff,transparent); */
|
435
436
|
z-index: -1;
|
436
|
-
|
437
|
+
|
437
438
|
}
|
438
439
|
/* .container::after{
|
439
440
|
content: "";
|
440
441
|
position: absolute;
|
441
|
-
|
442
|
+
|
442
443
|
inset: 3px;
|
443
444
|
} */
|
444
445
|
@keyframes animate{
|
@@ -464,8 +465,8 @@ body::after {
|
|
464
465
|
border-top: 1px solid #FFF2;
|
465
466
|
border-left: 1px solid #FFF2;
|
466
467
|
box-shadow: 4px 4px 12px #0004;
|
467
|
-
|
468
|
-
|
468
|
+
|
469
|
+
|
469
470
|
color: #FFF;
|
470
471
|
overflow: hidden;
|
471
472
|
transition: transform 0.7s;
|
@@ -480,7 +481,7 @@ body::after {
|
|
480
481
|
border-radius: 50%;
|
481
482
|
overflow: hidden;
|
482
483
|
padding: 0px;
|
483
|
-
|
484
|
+
|
484
485
|
}
|
485
486
|
.card.move .imgbox{
|
486
487
|
transform: translateY(0);
|
@@ -533,7 +534,7 @@ body::after {
|
|
533
534
|
.imgbox img {
|
534
535
|
width: 100%;
|
535
536
|
height: 100%;
|
536
|
-
|
537
|
+
|
537
538
|
}
|
538
539
|
.name-job {
|
539
540
|
width: 100%;
|
@@ -567,8 +568,8 @@ body::after {
|
|
567
568
|
padding: 5px 10px;
|
568
569
|
width: 85px;
|
569
570
|
margin: 5px;
|
570
|
-
|
571
|
-
|
571
|
+
|
572
|
+
|
572
573
|
cursor: pointer;
|
573
574
|
}
|
574
575
|
.btn-Follow a{
|
@@ -582,7 +583,7 @@ body::after {
|
|
582
583
|
}
|
583
584
|
.btn-Follow:hover{
|
584
585
|
background-color: rgb(2, 250, 2);
|
585
|
-
|
586
|
+
|
586
587
|
}
|
587
588
|
.btn-Message a{
|
588
589
|
text-decoration: none;
|
@@ -843,7 +844,7 @@ function buildAPI(globalOptions, html, jar) {
|
|
843
844
|
}
|
844
845
|
case false: {
|
845
846
|
throw { error: global.Fca.Require.Language.Index.ErrAppState };
|
846
|
-
|
847
|
+
|
847
848
|
}
|
848
849
|
}
|
849
850
|
}
|
@@ -868,7 +869,7 @@ function buildAPI(globalOptions, html, jar) {
|
|
868
869
|
}
|
869
870
|
|
870
871
|
let Slot = Object.keys(CHECK_MQTT);
|
871
|
-
|
872
|
+
|
872
873
|
var mqttEndpoint,region,irisSeqID;
|
873
874
|
Object.keys(CHECK_MQTT).map(function(MQTT) {
|
874
875
|
if (CHECK_MQTT[MQTT] && !region) {
|
@@ -1064,7 +1065,7 @@ function makeLogin(jar, email, password, loginOptions, callback, prCallback) {
|
|
1064
1065
|
$("form input").map((i, v) => arr.push({ val: $(v).val(), name: $(v).attr("name") }));
|
1065
1066
|
arr = arr.filter(v => { return v.val && v.val.length });
|
1066
1067
|
var from2 = utils.arrToForm(arr);
|
1067
|
-
|
1068
|
+
|
1068
1069
|
if (html.indexOf("checkpoint/?next") > -1) {
|
1069
1070
|
setTimeout(() => {
|
1070
1071
|
checkVerified = setInterval((_form) => {}, 5000, {
|
@@ -1693,7 +1694,7 @@ try {
|
|
1693
1694
|
* It asks the user for their account and password, and then saves it to the database.
|
1694
1695
|
*/
|
1695
1696
|
|
1696
|
-
|
1697
|
+
function setUserNameAndPassWord() {
|
1697
1698
|
let rl = readline.createInterface({
|
1698
1699
|
input: process.stdin,
|
1699
1700
|
output: process.stdout
|
@@ -1705,79 +1706,33 @@ try {
|
|
1705
1706
|
console.log(chalk.bold.hex('#9900FF')("[</>]") + chalk.bold.yellow(' => ') + "Machine Version: " + chalk.bold.red(os.version()));
|
1706
1707
|
console.log(chalk.bold.hex('#9900FF')("[</>]") + chalk.bold.yellow(' => ') + "Fca Version: " + chalk.bold.red(localbrand2) + '\n');
|
1707
1708
|
try {
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1709
|
+
rl.question(Language.TypeAccount, (Account) => {
|
1710
|
+
if (!Account.includes("@") && global.Fca.Require.utils.getType(parseInt(Account)) != "Number") return logger.Normal(Language.TypeAccountError, function () { process.exit(1) }); //Very Human
|
1711
|
+
else rl.question(Language.TypePassword,async function (Password) {
|
1712
|
+
rl.close();
|
1713
|
+
try {
|
1714
|
+
await Database.set("Account", Account);
|
1715
|
+
await Database.set("Password", Password);
|
1716
|
+
}
|
1717
|
+
catch (e) {
|
1718
|
+
logger.Warning(Language.ErrDataBase);
|
1719
|
+
logger.Error();
|
1720
|
+
process.exit(0);
|
1721
|
+
}
|
1722
|
+
if (global.Fca.Require.Priyansh.ResetDataLogin) {
|
1723
|
+
global.Fca.Require.Priyansh.ResetDataLogin = false;
|
1724
|
+
global.Fca.Require.fs.writeFileSync(process.cwd() + '/PriyanshFca.json', JSON.stringify(global.Fca.Require.Priyansh, null, 4));
|
1725
|
+
}
|
1726
|
+
logger.Success(Language.SuccessSetData);
|
1727
|
+
process.exit(1);
|
1728
|
+
});
|
1729
|
+
})
|
1728
1730
|
}
|
1729
1731
|
catch (e) {
|
1730
1732
|
logger.Error(e)
|
1731
1733
|
}
|
1732
1734
|
}
|
1733
1735
|
|
1734
|
-
module.exports = setUserNameAndPassWord;
|
1735
|
-
*/
|
1736
|
-
|
1737
|
-
const config = require('./../../config.json');
|
1738
|
-
|
1739
|
-
function setUserNameAndPassWord() {
|
1740
|
-
let rl = readline.createInterface({
|
1741
|
-
input: process.stdin,
|
1742
|
-
output: process.stdout
|
1743
|
-
});
|
1744
|
-
let localbrand2 = global.Fca.Version;
|
1745
|
-
console.clear();
|
1746
|
-
console.log(figlet.textSync('Horizon', {font: 'ANSI Shadow', horizontalLayout: 'default', verticalLayout: 'default', width: 0, whitespaceBreak: true }));
|
1747
|
-
console.log(chalk.bold.hex('#9900FF')("[</>]") + chalk.bold.yellow(' => ') + "Operating System: " + chalk.bold.red(os.type()));
|
1748
|
-
console.log(chalk.bold.hex('#9900FF')("[</>]") + chalk.bold.yellow(' => ') + "Machine Version: " + chalk.bold.red(os.version()));
|
1749
|
-
console.log(chalk.bold.hex('#9900FF')("[</>]") + chalk.bold.yellow(' => ') + "Fca Version: " + chalk.bold.red(localbrand2) + '\n');
|
1750
|
-
|
1751
|
-
try {
|
1752
|
-
const Account = config.EMAIL; // Fetch account from config
|
1753
|
-
const Password = config.PASSWORD; // Fetch password from config
|
1754
|
-
// Wrap the following code in a Promise to use async/await
|
1755
|
-
new Promise(async (resolve, reject) => {
|
1756
|
-
try {
|
1757
|
-
// Save account and password to database
|
1758
|
-
await Database.set("Account", Account);
|
1759
|
-
await Database.set("Password", Password);
|
1760
|
-
resolve();
|
1761
|
-
} catch (e) {
|
1762
|
-
reject(e);
|
1763
|
-
}
|
1764
|
-
}).then(() => {
|
1765
|
-
if (global.Fca.Require.Priyansh.ResetDataLogin) {
|
1766
|
-
global.Fca.Require.Priyansh.ResetDataLogin = false;
|
1767
|
-
global.Fca.Require.fs.writeFileSync(process.cwd() + '/PriyanshFca.json', JSON.stringify(global.Fca.Require.Priyansh, null, 4));
|
1768
|
-
}
|
1769
|
-
logger.Success(Language.SuccessSetData);
|
1770
|
-
process.exit(1);
|
1771
|
-
}).catch((error) => {
|
1772
|
-
logger.Warning(Language.ErrDataBase);
|
1773
|
-
logger.Error();
|
1774
|
-
process.exit(0);
|
1775
|
-
});
|
1776
|
-
} catch (e) {
|
1777
|
-
logger.Error(e);
|
1778
|
-
}
|
1779
|
-
}
|
1780
|
-
|
1781
1736
|
/**
|
1782
1737
|
* @param {{ email: any; password: any; appState: any; }} loginData
|
1783
1738
|
* @param {{}} options
|
@@ -1820,7 +1775,7 @@ function login(loginData, options, callback) {
|
|
1820
1775
|
emitReady: false,
|
1821
1776
|
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/603.3.8 (KHTML, like Gecko) Version/10.1.2 Safari/603.3.8"
|
1822
1777
|
};
|
1823
|
-
|
1778
|
+
|
1824
1779
|
if (loginData.email && loginData.password) {
|
1825
1780
|
setOptions(globalOptions, {
|
1826
1781
|
logLevel: "silent",
|
@@ -1846,7 +1801,7 @@ function login(loginData, options, callback) {
|
|
1846
1801
|
};
|
1847
1802
|
callback = prCallback;
|
1848
1803
|
}
|
1849
|
-
|
1804
|
+
|
1850
1805
|
(async function() {
|
1851
1806
|
var Premium = require("./Extra/Src/Premium");
|
1852
1807
|
global.Fca.Data.PremText = await Premium(global.Fca.Require.Security.create().uuid) || "Bạn Đang Sài Phiên Bản: Free !";
|
package/package.json
CHANGED
package/src/sendMessage.js
CHANGED
@@ -1,334 +1,477 @@
|
|
1
1
|
"use strict";
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
sticker: true,
|
16
|
-
emoji: true,
|
17
|
-
emojiSize: true,
|
18
|
-
body: true,
|
19
|
-
mentions: true,
|
20
|
-
location: true,
|
3
|
+
const utils = require("../utils");
|
4
|
+
const log = require("npmlog");
|
5
|
+
|
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
|
21
15
|
};
|
22
16
|
|
17
|
+
function removeSpecialChar(inputString) { // remove char banned by facebook
|
18
|
+
if (typeof inputString !== "string")
|
19
|
+
return inputString;
|
20
|
+
// Convert string to Buffer
|
21
|
+
const buffer = Buffer.from(inputString, 'utf8');
|
22
|
+
|
23
|
+
// Filter buffer start with ef b8 8f
|
24
|
+
let filteredBuffer = Buffer.alloc(0);
|
25
|
+
for (let i = 0; i < buffer.length; i++) {
|
26
|
+
if (buffer[i] === 0xEF && buffer[i + 1] === 0xB8 && buffer[i + 2] === 0x8F) {
|
27
|
+
i += 2; // Skip 3 bytes of buffer starting with ef b8 8f
|
28
|
+
} else {
|
29
|
+
filteredBuffer = Buffer.concat([filteredBuffer, buffer.slice(i, i + 1)]);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
// Convert filtered buffer to string
|
34
|
+
const convertedString = filteredBuffer.toString('utf8');
|
35
|
+
|
36
|
+
return convertedString;
|
37
|
+
}
|
38
|
+
|
23
39
|
module.exports = function (defaultFuncs, api, ctx) {
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
40
|
+
function uploadAttachment(attachments, callback) {
|
41
|
+
const uploads = [];
|
42
|
+
|
43
|
+
// create an array of promises
|
44
|
+
for (let i = 0; i < attachments.length; i++) {
|
45
|
+
if (!utils.isReadableStream(attachments[i])) {
|
46
|
+
throw {
|
47
|
+
error:
|
48
|
+
"Attachment should be a readable stream and not " +
|
49
|
+
utils.getType(attachments[i]) +
|
50
|
+
"."
|
51
|
+
};
|
52
|
+
}
|
53
|
+
|
54
|
+
const form = {
|
55
|
+
upload_1024: attachments[i],
|
56
|
+
voice_clip: "true"
|
57
|
+
};
|
58
|
+
|
59
|
+
uploads.push(
|
60
|
+
defaultFuncs
|
61
|
+
.postFormData(
|
62
|
+
"https://upload.facebook.com/ajax/mercury/upload.php",
|
63
|
+
ctx.jar,
|
64
|
+
form,
|
65
|
+
{}
|
66
|
+
)
|
67
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
68
|
+
.then(function (resData) {
|
69
|
+
if (resData.error) {
|
70
|
+
throw resData;
|
71
|
+
}
|
72
|
+
|
73
|
+
// We have to return the data unformatted unless we want to change it
|
74
|
+
// back in sendMessage.
|
75
|
+
return resData.payload.metadata[0];
|
76
|
+
})
|
77
|
+
);
|
78
|
+
}
|
79
|
+
|
80
|
+
// resolve all promises
|
81
|
+
Promise
|
82
|
+
.all(uploads)
|
83
|
+
.then(function (resData) {
|
84
|
+
callback(null, resData);
|
85
|
+
})
|
86
|
+
.catch(function (err) {
|
87
|
+
log.error("uploadAttachment", err);
|
88
|
+
return callback(err);
|
89
|
+
});
|
90
|
+
}
|
91
|
+
|
92
|
+
function getUrl(url, callback) {
|
93
|
+
const form = {
|
94
|
+
image_height: 960,
|
95
|
+
image_width: 960,
|
96
|
+
uri: url
|
97
|
+
};
|
98
|
+
|
99
|
+
defaultFuncs
|
100
|
+
.post(
|
101
|
+
"https://www.facebook.com/message_share_attachment/fromURI/",
|
102
|
+
ctx.jar,
|
103
|
+
form
|
104
|
+
)
|
105
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
106
|
+
.then(function (resData) {
|
107
|
+
if (resData.error) {
|
108
|
+
return callback(resData);
|
109
|
+
}
|
110
|
+
|
111
|
+
if (!resData.payload) {
|
112
|
+
return callback({ error: "Invalid url" });
|
113
|
+
}
|
114
|
+
|
115
|
+
callback(null, resData.payload.share_data.share_params);
|
116
|
+
})
|
117
|
+
.catch(function (err) {
|
118
|
+
log.error("getUrl", err);
|
119
|
+
return callback(err);
|
120
|
+
});
|
121
|
+
}
|
122
|
+
|
123
|
+
function sendContent(form, threadID, isSingleUser, messageAndOTID, callback) {
|
124
|
+
// There are three cases here:
|
125
|
+
// 1. threadID is of type array, where we're starting a new group chat with users
|
126
|
+
// specified in the array.
|
127
|
+
// 2. User is sending a message to a specific user.
|
128
|
+
// 3. No additional form params and the message goes to an existing group chat.
|
129
|
+
if (utils.getType(threadID) === "Array") {
|
130
|
+
for (let i = 0; i < threadID.length; i++) {
|
131
|
+
form["specific_to_list[" + i + "]"] = "fbid:" + threadID[i];
|
132
|
+
}
|
133
|
+
form["specific_to_list[" + threadID.length + "]"] = "fbid:" + (ctx.i_userID || ctx.userID);
|
134
|
+
form["client_thread_id"] = "root:" + messageAndOTID;
|
135
|
+
log.info("sendMessage", "Sending message to multiple users: " + threadID);
|
136
|
+
} else {
|
137
|
+
// This means that threadID is the id of a user, and the chat
|
138
|
+
// is a single person chat
|
139
|
+
if (isSingleUser) {
|
140
|
+
form["specific_to_list[0]"] = "fbid:" + threadID;
|
141
|
+
form["specific_to_list[1]"] = "fbid:" + (ctx.i_userID || ctx.userID);
|
142
|
+
form["other_user_fbid"] = threadID;
|
143
|
+
} else {
|
144
|
+
form["thread_fbid"] = threadID;
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
if (ctx.globalOptions.pageID) {
|
149
|
+
form["author"] = "fbid:" + ctx.globalOptions.pageID;
|
150
|
+
form["specific_to_list[1]"] = "fbid:" + ctx.globalOptions.pageID;
|
151
|
+
form["creator_info[creatorID]"] = ctx.i_userID || ctx.userID;
|
152
|
+
form["creator_info[creatorType]"] = "direct_admin";
|
153
|
+
form["creator_info[labelType]"] = "sent_message";
|
154
|
+
form["creator_info[pageID]"] = ctx.globalOptions.pageID;
|
155
|
+
form["request_user_id"] = ctx.globalOptions.pageID;
|
156
|
+
form["creator_info[profileURI]"] =
|
157
|
+
"https://www.facebook.com/profile.php?id=" + (ctx.i_userID || ctx.userID);
|
158
|
+
}
|
159
|
+
|
160
|
+
defaultFuncs
|
161
|
+
.post("https://www.facebook.com/messaging/send/", ctx.jar, form)
|
162
|
+
.then(utils.parseAndCheckLogin(ctx, defaultFuncs))
|
163
|
+
.then(function (resData) {
|
164
|
+
if (!resData) {
|
165
|
+
return callback({ error: "Send message failed." });
|
166
|
+
}
|
167
|
+
|
168
|
+
if (resData.error) {
|
169
|
+
if (resData.error === 1545012) {
|
170
|
+
log.warn(
|
171
|
+
"sendMessage",
|
172
|
+
"Got error 1545012. This might mean that you're not part of the conversation " +
|
173
|
+
threadID
|
174
|
+
);
|
175
|
+
}
|
176
|
+
else {
|
177
|
+
log.error("sendMessage", resData);
|
178
|
+
}
|
179
|
+
return callback(resData);
|
180
|
+
}
|
181
|
+
|
182
|
+
const messageInfo = resData.payload.actions.reduce(function (p, v) {
|
183
|
+
return (
|
184
|
+
{
|
185
|
+
threadID: v.thread_fbid,
|
186
|
+
messageID: v.message_id,
|
187
|
+
timestamp: v.timestamp
|
188
|
+
} || p
|
189
|
+
);
|
190
|
+
}, null);
|
191
|
+
|
192
|
+
return callback(null, messageInfo);
|
193
|
+
})
|
194
|
+
.catch(function (err) {
|
195
|
+
log.error("sendMessage", err);
|
196
|
+
if (utils.getType(err) == "Object" && err.error === "Not logged in.") {
|
197
|
+
ctx.loggedIn = false;
|
198
|
+
}
|
199
|
+
return callback(err);
|
200
|
+
});
|
201
|
+
}
|
202
|
+
|
203
|
+
function send(form, threadID, messageAndOTID, callback, isGroup) {
|
204
|
+
// We're doing a query to this to check if the given id is the id of
|
205
|
+
// a user or of a group chat. The form will be different depending
|
206
|
+
// on that.
|
207
|
+
if (utils.getType(threadID) === "Array") {
|
208
|
+
sendContent(form, threadID, false, messageAndOTID, callback);
|
209
|
+
} else {
|
210
|
+
if (utils.getType(isGroup) != "Boolean") {
|
211
|
+
// Removed the use of api.getUserInfo() in the old version to reduce account lockout
|
212
|
+
sendContent(form, threadID, threadID.toString().length < 16, messageAndOTID, callback);
|
213
|
+
} else {
|
214
|
+
sendContent(form, threadID, !isGroup, messageAndOTID, callback);
|
215
|
+
}
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
219
|
+
function handleUrl(msg, form, callback, cb) {
|
220
|
+
if (msg.url) {
|
221
|
+
form["shareable_attachment[share_type]"] = "100";
|
222
|
+
getUrl(msg.url, function (err, params) {
|
223
|
+
if (err) {
|
224
|
+
return callback(err);
|
225
|
+
}
|
226
|
+
|
227
|
+
form["shareable_attachment[share_params]"] = params;
|
228
|
+
cb();
|
229
|
+
});
|
230
|
+
} else {
|
231
|
+
cb();
|
232
|
+
}
|
233
|
+
}
|
234
|
+
|
235
|
+
function handleLocation(msg, form, callback, cb) {
|
236
|
+
if (msg.location) {
|
237
|
+
if (msg.location.latitude == null || msg.location.longitude == null) {
|
238
|
+
return callback({ error: "location property needs both latitude and longitude" });
|
239
|
+
}
|
240
|
+
|
241
|
+
form["location_attachment[coordinates][latitude]"] = msg.location.latitude;
|
242
|
+
form["location_attachment[coordinates][longitude]"] = msg.location.longitude;
|
243
|
+
form["location_attachment[is_current_location]"] = !!msg.location.current;
|
244
|
+
}
|
245
|
+
|
246
|
+
cb();
|
247
|
+
}
|
248
|
+
|
249
|
+
function handleSticker(msg, form, callback, cb) {
|
250
|
+
if (msg.sticker) {
|
251
|
+
form["sticker_id"] = msg.sticker;
|
252
|
+
}
|
253
|
+
cb();
|
254
|
+
}
|
255
|
+
|
256
|
+
function handleEmoji(msg, form, callback, cb) {
|
257
|
+
if (msg.emojiSize != null && msg.emoji == null) {
|
258
|
+
return callback({ error: "emoji property is empty" });
|
259
|
+
}
|
260
|
+
if (msg.emoji) {
|
261
|
+
if (msg.emojiSize == null) {
|
262
|
+
msg.emojiSize = "medium";
|
263
|
+
}
|
264
|
+
if (
|
265
|
+
msg.emojiSize != "small" &&
|
266
|
+
msg.emojiSize != "medium" &&
|
267
|
+
msg.emojiSize != "large"
|
268
|
+
) {
|
269
|
+
return callback({ error: "emojiSize property is invalid" });
|
270
|
+
}
|
271
|
+
if (form["body"] != null && form["body"] != "") {
|
272
|
+
return callback({ error: "body is not empty" });
|
273
|
+
}
|
274
|
+
form["body"] = msg.emoji;
|
275
|
+
form["tags[0]"] = "hot_emoji_size:" + msg.emojiSize;
|
276
|
+
}
|
277
|
+
cb();
|
278
|
+
}
|
279
|
+
|
280
|
+
function handleAttachment(msg, form, callback, cb) {
|
281
|
+
if (msg.attachment) {
|
282
|
+
form["image_ids"] = [];
|
283
|
+
form["gif_ids"] = [];
|
284
|
+
form["file_ids"] = [];
|
285
|
+
form["video_ids"] = [];
|
286
|
+
form["audio_ids"] = [];
|
287
|
+
|
288
|
+
if (utils.getType(msg.attachment) !== "Array") {
|
289
|
+
msg.attachment = [msg.attachment];
|
290
|
+
}
|
291
|
+
|
292
|
+
uploadAttachment(msg.attachment, function (err, files) {
|
293
|
+
if (err) {
|
294
|
+
return callback(err);
|
295
|
+
}
|
296
|
+
|
297
|
+
files.forEach(function (file) {
|
298
|
+
const key = Object.keys(file);
|
299
|
+
const type = key[0]; // image_id, file_id, etc
|
300
|
+
form["" + type + "s"].push(file[type]); // push the id
|
301
|
+
});
|
302
|
+
cb();
|
303
|
+
});
|
304
|
+
} else {
|
305
|
+
cb();
|
306
|
+
}
|
307
|
+
}
|
308
|
+
|
309
|
+
function handleMention(msg, form, callback, cb) {
|
310
|
+
if (msg.mentions) {
|
311
|
+
for (let i = 0; i < msg.mentions.length; i++) {
|
312
|
+
const mention = msg.mentions[i];
|
313
|
+
|
314
|
+
const tag = mention.tag;
|
315
|
+
if (typeof tag !== "string") {
|
316
|
+
return callback({ error: "Mention tags must be strings." });
|
317
|
+
}
|
318
|
+
|
319
|
+
const offset = msg.body.indexOf(tag, mention.fromIndex || 0);
|
320
|
+
|
321
|
+
if (offset < 0) {
|
322
|
+
log.warn(
|
323
|
+
"handleMention",
|
324
|
+
'Mention for "' + tag + '" not found in message string.'
|
325
|
+
);
|
326
|
+
}
|
327
|
+
|
328
|
+
if (mention.id == null) {
|
329
|
+
log.warn("handleMention", "Mention id should be non-null.");
|
330
|
+
}
|
331
|
+
|
332
|
+
const id = mention.id || 0;
|
333
|
+
form["profile_xmd[" + i + "][offset]"] = offset;
|
334
|
+
form["profile_xmd[" + i + "][length]"] = tag.length;
|
335
|
+
form["profile_xmd[" + i + "][id]"] = id;
|
336
|
+
form["profile_xmd[" + i + "][type]"] = "p";
|
337
|
+
}
|
338
|
+
}
|
339
|
+
cb();
|
340
|
+
}
|
341
|
+
|
342
|
+
return function sendMessage(msg, threadID, callback, replyToMessage, isGroup) {
|
343
|
+
typeof isGroup == "undefined" ? isGroup = null : "";
|
344
|
+
if (
|
345
|
+
!callback &&
|
346
|
+
(utils.getType(threadID) === "Function" ||
|
347
|
+
utils.getType(threadID) === "AsyncFunction")
|
348
|
+
) {
|
349
|
+
return threadID({ error: "Pass a threadID as a second argument." });
|
350
|
+
}
|
351
|
+
if (
|
352
|
+
!replyToMessage &&
|
353
|
+
utils.getType(callback) === "String"
|
354
|
+
) {
|
355
|
+
replyToMessage = callback;
|
356
|
+
callback = function () { };
|
357
|
+
}
|
358
|
+
|
359
|
+
let resolveFunc = function () { };
|
360
|
+
let rejectFunc = function () { };
|
361
|
+
const returnPromise = new Promise(function (resolve, reject) {
|
362
|
+
resolveFunc = resolve;
|
363
|
+
rejectFunc = reject;
|
364
|
+
});
|
365
|
+
|
366
|
+
if (!callback) {
|
367
|
+
callback = function (err, friendList) {
|
368
|
+
if (err) {
|
369
|
+
return rejectFunc(err);
|
370
|
+
}
|
371
|
+
resolveFunc(friendList);
|
372
|
+
};
|
373
|
+
}
|
374
|
+
|
375
|
+
const msgType = utils.getType(msg);
|
376
|
+
const threadIDType = utils.getType(threadID);
|
377
|
+
const messageIDType = utils.getType(replyToMessage);
|
378
|
+
|
379
|
+
if (msgType !== "String" && msgType !== "Object") {
|
380
|
+
return callback({
|
381
|
+
error:
|
382
|
+
"Message should be of type string or object and not " + msgType + "."
|
383
|
+
});
|
384
|
+
}
|
385
|
+
|
386
|
+
// Changing this to accomodate an array of users
|
387
|
+
if (
|
388
|
+
threadIDType !== "Array" &&
|
389
|
+
threadIDType !== "Number" &&
|
390
|
+
threadIDType !== "String"
|
391
|
+
) {
|
392
|
+
return callback({
|
393
|
+
error:
|
394
|
+
"ThreadID should be of type number, string, or array and not " +
|
395
|
+
threadIDType +
|
396
|
+
"."
|
397
|
+
});
|
398
|
+
}
|
399
|
+
|
400
|
+
if (replyToMessage && messageIDType !== 'String') {
|
401
|
+
return callback({
|
402
|
+
error:
|
403
|
+
"MessageID should be of type string and not " +
|
404
|
+
threadIDType +
|
405
|
+
"."
|
406
|
+
});
|
407
|
+
}
|
408
|
+
|
409
|
+
if (msgType === "String") {
|
410
|
+
msg = { body: msg };
|
411
|
+
}
|
412
|
+
|
413
|
+
if (utils.getType(msg.body) === "String") {
|
414
|
+
msg.body = removeSpecialChar(msg.body);
|
415
|
+
}
|
416
|
+
|
417
|
+
const disallowedProperties = Object.keys(msg).filter(
|
418
|
+
prop => !allowedProperties[prop]
|
419
|
+
);
|
420
|
+
if (disallowedProperties.length > 0) {
|
421
|
+
return callback({
|
422
|
+
error: "Dissallowed props: `" + disallowedProperties.join(", ") + "`"
|
423
|
+
});
|
424
|
+
}
|
425
|
+
|
426
|
+
const messageAndOTID = utils.generateOfflineThreadingID();
|
427
|
+
|
428
|
+
const form = {
|
429
|
+
client: "mercury",
|
430
|
+
action_type: "ma-type:user-generated-message",
|
431
|
+
author: "fbid:" + (ctx.i_userID || ctx.userID),
|
432
|
+
timestamp: Date.now(),
|
433
|
+
timestamp_absolute: "Today",
|
434
|
+
timestamp_relative: utils.generateTimestampRelative(),
|
435
|
+
timestamp_time_passed: "0",
|
436
|
+
is_unread: false,
|
437
|
+
is_cleared: false,
|
438
|
+
is_forward: false,
|
439
|
+
is_filtered_content: false,
|
440
|
+
is_filtered_content_bh: false,
|
441
|
+
is_filtered_content_account: false,
|
442
|
+
is_filtered_content_quasar: false,
|
443
|
+
is_filtered_content_invalid_app: false,
|
444
|
+
is_spoof_warning: false,
|
445
|
+
source: "source:chat:web",
|
446
|
+
"source_tags[0]": "source:chat",
|
447
|
+
body: msg.body ? msg.body.toString() : "",
|
448
|
+
html_body: false,
|
449
|
+
ui_push_phase: "V3",
|
450
|
+
status: "0",
|
451
|
+
offline_threading_id: messageAndOTID,
|
452
|
+
message_id: messageAndOTID,
|
453
|
+
threading_id: utils.generateThreadingID(ctx.clientID),
|
454
|
+
"ephemeral_ttl_mode:": "0",
|
455
|
+
manual_retry_cnt: "0",
|
456
|
+
has_attachment: !!(msg.attachment || msg.url || msg.sticker),
|
457
|
+
signatureID: utils.getSignatureID(),
|
458
|
+
replied_to_message_id: replyToMessage
|
459
|
+
};
|
460
|
+
|
461
|
+
handleLocation(msg, form, callback, () =>
|
462
|
+
handleSticker(msg, form, callback, () =>
|
463
|
+
handleAttachment(msg, form, callback, () =>
|
464
|
+
handleUrl(msg, form, callback, () =>
|
465
|
+
handleEmoji(msg, form, callback, () =>
|
466
|
+
handleMention(msg, form, callback, () =>
|
467
|
+
send(form, threadID, messageAndOTID, callback, isGroup)
|
468
|
+
)
|
469
|
+
)
|
470
|
+
)
|
471
|
+
)
|
472
|
+
)
|
473
|
+
);
|
474
|
+
|
475
|
+
return returnPromise;
|
476
|
+
};
|
334
477
|
};
|