@eryxenx/insta-chat 2.0.1 → 2.0.3
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/CHANGELOG.md +95 -8
- package/index.js +105 -1
- package/module/login.js +51 -1
- package/package.json +9 -2
- package/src/api/action/getAppState.js +19 -1
- package/src/api/action/getCookies.js +7 -1
- package/src/api/action/getCurrentUserID.js +7 -1
- package/src/api/action/setOptions.js +8 -1
- package/src/api/messaging/editMessage.js +19 -1
- package/src/api/messaging/markAsRead.js +7 -1
- package/src/api/messaging/resolvePhotoUrl.js +8 -1
- package/src/api/messaging/sendMessage.js +45 -1
- package/src/api/messaging/sendMessageSync.js +8 -1
- package/src/api/messaging/sendTypingIndicator.js +7 -1
- package/src/api/messaging/setMessageReaction.js +19 -1
- package/src/api/messaging/shareContact.js +19 -1
- package/src/api/messaging/unsendMessage.js +16 -1
- package/src/api/realtime/getInbox.js +7 -1
- package/src/api/realtime/listen.js +7 -1
- package/src/api/realtime/stopListening.js +7 -1
- package/src/api/threads/getThreadHistory.js +16 -1
- package/src/api/threads/getThreadInfo.js +59 -1
- package/src/api/threads/getThreadList.js +22 -1
- package/src/api/users/getUID.js +12 -1
- package/src/api/users/getUserInfo.js +37 -1
- package/src/api.js +253 -1
- package/src/app/InstaClient.js +352 -1
- package/src/app/InstaContext.js +46 -1
- package/src/app/createFcaClient.js +59 -1
- package/src/app/loadApiMethods.js +30 -1
- package/src/constants.js +53 -1
- package/src/cookies.js +41 -1
- package/src/deviceIdentity.js +31 -1
- package/src/events/normalizeEvent.js +142 -1
- package/src/http.js +381 -1
- package/src/messageContent.js +73 -1
- package/src/methods/inbox.js +464 -1
- package/src/methods/media.js +218 -1
- package/src/methods/message.js +115 -1
- package/src/methods/reactions.js +52 -1
- package/src/methods/thread.js +96 -1
- package/src/methods/typing.js +35 -1
- package/src/methods/user.js +33 -1
- package/src/session.js +94 -1
- package/src/threadDetail.js +36 -1
- package/src/utils/antiSuspension.js +269 -0
- package/src/utils/dataDir.js +11 -0
- package/src/utils/errors.js +106 -0
- package/src/utils/format.js +38 -1
- package/src/utils/messageStyle.js +57 -1
- package/src/utils/sessionGuard.js +93 -0
package/src/methods/typing.js
CHANGED
|
@@ -4,4 +4,38 @@
|
|
|
4
4
|
* Licensed under the Apache License, Version 2.0. See LICENSE and NOTICE.
|
|
5
5
|
* Original author credit must be retained in all copies and derivatives.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
const { EP } = require("../constants");
|
|
9
|
+
|
|
10
|
+
const FALLBACK_PATHS = [
|
|
11
|
+
(t) => `https://www.instagram.com/api/v1/direct_v2/threads/${t}/indicate_activity/`,
|
|
12
|
+
(t) => `https://www.instagram.com/api/v1/direct_v2/typing/`
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
class TypingMethods {
|
|
16
|
+
constructor(http) {
|
|
17
|
+
this.http = http;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async _try(threadID, isActive) {
|
|
21
|
+
const form = { thread_id: threadID, activity_status: isActive ? "1" : "0" };
|
|
22
|
+
|
|
23
|
+
for (const build of [() => EP.TYPING(threadID), ...FALLBACK_PATHS.map((f) => () => f(threadID))]) {
|
|
24
|
+
try {
|
|
25
|
+
await this.http.postForm(build(), form);
|
|
26
|
+
return true;
|
|
27
|
+
} catch (_) {}
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async start(threadID) {
|
|
33
|
+
return this._try(threadID, true);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async stop(threadID) {
|
|
37
|
+
return this._try(threadID, false);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = TypingMethods;
|
package/src/methods/user.js
CHANGED
|
@@ -4,4 +4,36 @@
|
|
|
4
4
|
* Licensed under the Apache License, Version 2.0. See LICENSE and NOTICE.
|
|
5
5
|
* Original author credit must be retained in all copies and derivatives.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
const { EP } = require("../constants");
|
|
9
|
+
|
|
10
|
+
class UserMethods {
|
|
11
|
+
constructor(http) {
|
|
12
|
+
this.http = http;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async getInfo(userID) {
|
|
16
|
+
const res = await this.http.get(EP.USER_INFO(userID));
|
|
17
|
+
return res?.user || null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async getInfoByUsername(username) {
|
|
21
|
+
try {
|
|
22
|
+
const res = await this.http.get(EP.USER_BY_USERNAME(username));
|
|
23
|
+
if (res?.user) return res.user;
|
|
24
|
+
} catch (_) {}
|
|
25
|
+
|
|
26
|
+
const res = await this.http.get(EP.USER_SEARCH(username, 30));
|
|
27
|
+
const match = (res?.users || []).find(
|
|
28
|
+
(u) => u.username?.toLowerCase() === username.toLowerCase()
|
|
29
|
+
);
|
|
30
|
+
return match || null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async search(query, limit = 20) {
|
|
34
|
+
const res = await this.http.get(EP.USER_SEARCH(query, limit));
|
|
35
|
+
return res?.users || [];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = UserMethods;
|
package/src/session.js
CHANGED
|
@@ -4,4 +4,97 @@
|
|
|
4
4
|
* Licensed under the Apache License, Version 2.0. See LICENSE and NOTICE.
|
|
5
5
|
* Original author credit must be retained in all copies and derivatives.
|
|
6
6
|
*/
|
|
7
|
-
const _0x356125=_0x4efb,_0x13ccf0=_0x4efb;(function(_0x14f8b6,_0x18ee01){const _0x5aeb41=_0x4efb,_0x16b384=_0x4efb,_0xc436ca=_0x14f8b6();while(!![]){try{const _0x1fb0ab=parseInt(_0x5aeb41(0x206,'(Wd('))/0x1+parseInt(_0x16b384(0x1e1,'MM%G'))/0x2+-parseInt(_0x5aeb41(0x1fd,'ae3E'))/0x3*(-parseInt(_0x16b384(0x1f9,'&$V#'))/0x4)+parseInt(_0x5aeb41(0x218,'e#vt'))/0x5+parseInt(_0x16b384(0x212,'99#x'))/0x6*(parseInt(_0x5aeb41(0x1e6,'e#vt'))/0x7)+-parseInt(_0x5aeb41(0x1c3,'eJ3f'))/0x8*(-parseInt(_0x5aeb41(0x186,'lI)]'))/0x9)+-parseInt(_0x16b384(0x1cc,'g#aS'))/0xa;if(_0x1fb0ab===_0x18ee01)break;else _0xc436ca['push'](_0xc436ca['shift']());}catch(_0x47d51c){_0xc436ca['push'](_0xc436ca['shift']());}}}(_0x2adb,0x753c8));function _0x2adb(){const _0x19dc45=['WRTrvCkAxqi','W5tcRCoAW70lbW','WQxcMmkdWPbqbq','WRVcOJiRW7j3','W6NdRqddP8kPWR8','sSk7cMRcIdy','fXRdTSkwytG','uWBdOCkik2G','vIxcO8oZAmkl','nCofa8ogW7NcTG','n8khh8omyCo1','qKRcImoUFmk/W7y','z8ktWRlcVGK','D8ohj8o4ua','y8ogWPddONpcJa','W7dcL8k8utdcUG','cv3cVCoDE27cOGWwWQG9W4P/','W50AW4ZcVmk/AG','W70dCW5v','WOSvyg3dMXC','p2pcJSkTW6W','DCojga','CKpdHcFcQG','yCkfbSoAE8k+','WQXiW7ZcRXS','vXFcQG','WRT5ba','WQzUctRdG8kG','BSoaWPFdRx0','E1hdOuZcMmkA','i8k0yq','ogniqum','W7NcIa1AuW','lCovW5VcK1dcGtTnl8kzjmogjq','qmo0gcxcMxC','pmoZc8kIW4NcPq','iSoFb8oz','WPRcTCkQWPb3WPi','l8oxeWuNWPO','WQhcTmk2','yCkgi8odW5C','j8osa8k0W4NcTa','wgtdQ8kyW7xcUG','W6FdSmk3b33dVq','EstcKmkQWPjs','r8o1d2NcJ3i','o8o5dCkQW4NdTW','pCkrW5ZcVspdLWZcTdXVnYpcJCk+','W77dVWtdPSk2WRq','WRuOBHyIma','WO/cMmkbmuVdHa','W4VcLmo3WOLf','jI7dKmoTW4rm','ygdcR8oIWOq','nSkFnmozW7pcPq','W7LcWPJcOmkLoW','iCkAwCkmj8oOuZn/W5NdRCo7','tLVdVWdcICkC','W7SZugVcNCoYgCkpWQ4IW4vTFq','W7yzWOTsDri','nNBcKSkcW4NcRW','WQpdLCo9fNJdVW','lSktDCkriW','W7hcRCorWQvBua','W5ZcSHLgASkE','ogXVD2G','xvZdOq7cLSkq','usBdMIW7hadcT8kIqHDzc8oL','W6qOW7FcJSkE','DSonWOVdHXddGa','W7ZdHCkJrZhcVG','tmo3csJcIxm','kCk3FSkoceq','WPpcILzXrSkZ','Amkhk8ouEmkV','W51aDxdcGrS','BSoLW5C9W7xdVW','nMZcVmkiW4JdTa','mSo/bmkI','zqa7W5ZcKeG','W6BcKIm5gSo/','iY9KW4/cLfm','W6hcMJyGWRTR','W7FcGmkHcYdcSa','hv1MuM7dNa','WR7cVmkXaMS','ASkSWOtdGWZdGG','W77dLriRW6vS','W5m7WPZdJLJcR8oxW7LVW73cVwK6','W77dVXNcOmkKWRC','WOvJW5hcPZW','pCoqESoLW77dGa','zSk4FSkvbbS','lSoBW5RcNWVdM1TSjmkW','WPHdW5BcO8oHiW','WQpcS8o8cwhdSW','A8kiWPddLqVdMq','kSoDgSodW7e','uINdMY09gaddGCkOsWLtkq','bSoyaCozW7hcPW','A8kJdSoNW6m','mSkVFSkFsbO','yvFcOSocWRm','imoEb8oeW7xcPW','FfJdTKZcN8kq','FmkQWPFcVd/dGW','WRJcUmkIg2VdRW','W63cS8kDWP/dHNC','W4CBnIZcNLC','dmk+CSksWRjIbG','BWFcTSoWzue','WRVdKmoFF8k9WQddQ8oeD8oE','cKNdJCoAWR8TW6C','wGZcOSohWQCr','ogFcSSo2F8ok','ieXiwSk9DW','W6yjsCooaKLKgCkIW4rZmG','fHTUt3NdIW','WR3cMCop','W4jGWOtcHXJdQW','kZmSW58','W6bIbI3dM8kK','WR3dIxuHhmoZWOtdG8ooW6pcSmoT','FmocWPBdV3NcIW','kCowESoKWRZdHG','WQRdH2PYWQCRW5zsW4ddUg/cQa','WPrEW6xcJWO','mgddTSkcW5pdOG','trZdOmkwdZ0','W7KMxqDQ','pCoCaZi7WOC','t8o1W5WW','g2LPWPZdQKK','W7tcMt5OW7vW','pCoqcZueWP4','WOjaDNldIW0','l2rLWP3dPW','WQpdNmoQhHhcVfzgW4jy','lwHUWOW','wCoygmoxC8km','WQbKhh7dHSkR','oI44W5JcUea','W6ldUWddUCkOWQO','kCouW5VcLLFcGtLjmSkDn8o5mG','W4VcHSoYWPpdGa','luDDtCo3sa','W6lcQSoqWQLqra','WO0GWOtcTaxdQq','W6dcKsv6xSkU','WPXqCvldJX4','W50lW5NcQmkGnq','lCktr8kqea','omoJWQNcUdBdLW','xCkJrCkoWQHh','tCkagmocW6G','WRHdW40oALa','kgv0r2ldTG','mSk/WOq','WQjqcCknCre','jdpcISkQWPjB','WQpdRmo/WOnRCq','W5WaW4VcUmkTnW','WRZdN8oFFSkgWQ7dKCoWBmo2','y8ocW4xdJ3JcLG','DcRdMSk0dW4','W4/cQSkZe8kUWOe','nYBcI8kXWPGv','oYRcMSo2WPyl','W4T3sxBdIsZcUW','WPFdIv5hcSkF','dZZdVSkiW7FcVG'];_0x2adb=function(){return _0x19dc45;};return _0x2adb();}function _0x4efb(_0x4f5e75,_0x359961){_0x4f5e75=_0x4f5e75-0x182;const _0x2adba7=_0x2adb();let _0x4efb52=_0x2adba7[_0x4f5e75];if(_0x4efb['Tllqfi']===undefined){var _0x3bd86b=function(_0x1ac9bc){const _0x46c20d='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x5d13c3='',_0x1da1d5='';for(let _0x2038d7=0x0,_0xeede97,_0x32e2b5,_0x32e4b7=0x0;_0x32e2b5=_0x1ac9bc['charAt'](_0x32e4b7++);~_0x32e2b5&&(_0xeede97=_0x2038d7%0x4?_0xeede97*0x40+_0x32e2b5:_0x32e2b5,_0x2038d7++%0x4)?_0x5d13c3+=String['fromCharCode'](0xff&_0xeede97>>(-0x2*_0x2038d7&0x6)):0x0){_0x32e2b5=_0x46c20d['indexOf'](_0x32e2b5);}for(let _0x200e27=0x0,_0x502a50=_0x5d13c3['length'];_0x200e27<_0x502a50;_0x200e27++){_0x1da1d5+='%'+('00'+_0x5d13c3['charCodeAt'](_0x200e27)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x1da1d5);};const _0xbda34f=function(_0x279446,_0x24b38c){let _0x708538=[],_0xb7eacd=0x0,_0xfe48d,_0x17cd09='';_0x279446=_0x3bd86b(_0x279446);let _0x59c189;for(_0x59c189=0x0;_0x59c189<0x100;_0x59c189++){_0x708538[_0x59c189]=_0x59c189;}for(_0x59c189=0x0;_0x59c189<0x100;_0x59c189++){_0xb7eacd=(_0xb7eacd+_0x708538[_0x59c189]+_0x24b38c['charCodeAt'](_0x59c189%_0x24b38c['length']))%0x100,_0xfe48d=_0x708538[_0x59c189],_0x708538[_0x59c189]=_0x708538[_0xb7eacd],_0x708538[_0xb7eacd]=_0xfe48d;}_0x59c189=0x0,_0xb7eacd=0x0;for(let _0x177a87=0x0;_0x177a87<_0x279446['length'];_0x177a87++){_0x59c189=(_0x59c189+0x1)%0x100,_0xb7eacd=(_0xb7eacd+_0x708538[_0x59c189])%0x100,_0xfe48d=_0x708538[_0x59c189],_0x708538[_0x59c189]=_0x708538[_0xb7eacd],_0x708538[_0xb7eacd]=_0xfe48d,_0x17cd09+=String['fromCharCode'](_0x279446['charCodeAt'](_0x177a87)^_0x708538[(_0x708538[_0x59c189]+_0x708538[_0xb7eacd])%0x100]);}return _0x17cd09;};_0x4efb['UqviLo']=_0xbda34f,_0x4efb['UVUQfS']={},_0x4efb['Tllqfi']=!![];}const _0x1d6b28=_0x2adba7[0x0],_0x34ce3a=_0x4f5e75+_0x1d6b28,_0x3f609a=_0x4efb['UVUQfS'][_0x34ce3a];return!_0x3f609a?(_0x4efb['TcgEjK']===undefined&&(_0x4efb['TcgEjK']=!![]),_0x4efb52=_0x4efb['UqviLo'](_0x4efb52,_0x359961),_0x4efb['UVUQfS'][_0x34ce3a]=_0x4efb52):_0x4efb52=_0x3f609a,_0x4efb52;}const fs=require('fs'),DEFAULT_UA='Mozill'+_0x356125(0x1c4,'1BED')+_0x356125(0x18c,'(Wd(')+_0x13ccf0(0x1f4,'0Jo@')+_0x356125(0x1c6,'99#x')+_0x356125(0x18a,'Qen8')+'\x20x64)\x20'+_0x13ccf0(0x214,'tvbl')+_0x13ccf0(0x1c5,']nr&')+'537.36'+_0x13ccf0(0x229,'Qen8')+_0x13ccf0(0x1c0,'01cM')+_0x356125(0x1d2,'()Jy')+_0x356125(0x21c,'MM%G')+_0x356125(0x1d9,'FYnX')+_0x356125(0x1f5,'lI)]')+_0x13ccf0(0x221,'mj]k')+_0x356125(0x1bd,'X9^p')+_0x356125(0x226,'z!E5'),CHROMIUM_CANDIDATES=[process['env']['CHROMI'+_0x13ccf0(0x1c9,'FYnX')+'H'],process[_0x13ccf0(0x1a7,'RwGq')]['PUPPET'+_0x13ccf0(0x1bb,'ka93')+_0x356125(0x183,'yzK6')+_0x13ccf0(0x182,'5mfJ')+'H'],_0x13ccf0(0x224,'1BED')+_0x13ccf0(0x1da,'4UYi')+_0x13ccf0(0x1ea,'ZXxo'),_0x356125(0x18f,'5mfJ')+_0x13ccf0(0x189,'ae3E')+_0x13ccf0(0x1d1,'RwGq')+_0x13ccf0(0x198,'99#x')+'r',_0x13ccf0(0x188,'qc&6')+_0x356125(0x1e8,'ka93')+_0x13ccf0(0x20e,'(Wd(')+'rome',_0x13ccf0(0x1d4,'lI)]')+'in/goo'+'gle-ch'+_0x356125(0x1db,'(Wd(')+_0x13ccf0(0x1de,'ka93'),_0x356125(0x1d8,'4UYi')+_0x13ccf0(0x184,'X9^p')+_0x13ccf0(0x1bf,'ZXxo')+_0x13ccf0(0x22c,'j*MA')+_0x356125(0x185,'X9^p')+_0x13ccf0(0x1d3,'tvbl')+_0x13ccf0(0x1fc,'ArRY')+_0x356125(0x187,'()Jy')+_0x13ccf0(0x1b7,'QOmu')+_0x13ccf0(0x1ec,'ZXxo')][_0x356125(0x1fe,'s]1W')](Boolean);function findChromium(){const _0x132fb0=_0x356125;return CHROMIUM_CANDIDATES[_0x132fb0(0x1d7,'QOmu')](_0x549a34=>{const _0x4656ed=_0x132fb0;try{return fs['exists'+_0x4656ed(0x213,'!WUs')](_0x549a34);}catch(_0x59bee8){return![];}});}async function harvestSessionParams(_0x2c83f7,_0xf549b9={}){const _0x590ff4=_0x13ccf0,_0x155642=_0x13ccf0,_0x5ac9de={'lwWFQ':_0x590ff4(0x1ba,'Dw&N')+_0x590ff4(0x1b9,'C[@P'),'iFeaz':function(_0x44f605,_0x564248){return _0x44f605===_0x564248;},'ccHEN':_0x155642(0x1c2,'hyQE')+_0x155642(0x1b2,'QOmu')+_0x590ff4(0x1ae,'M6An')+_0x155642(0x211,'!WUs'),'tDlGR':_0x155642(0x219,'0Jo@'),'faiOk':function(_0x4984cc,_0x44f3e1){return _0x4984cc===_0x44f3e1;},'vWAxg':'x-fb-f'+_0x590ff4(0x1d5,'z!E5')+'y-name','coCxg':function(_0x3a432f,_0x3ab5aa){return _0x3a432f(_0x3ab5aa);},'NAXXv':_0x590ff4(0x210,'lI)]')+_0x590ff4(0x1dc,'99#x')+'re\x20is\x20'+_0x155642(0x215,'eJ3f')+_0x590ff4(0x1e4,'sall')+_0x590ff4(0x1fa,'&$V#')+_0x590ff4(0x200,'MM%G')+'peteer'+_0x155642(0x1b5,'X9^p'),'kIPku':function(_0x40ca21){return _0x40ca21();},'hIbjF':'No\x20Chr'+'omium/'+_0x155642(0x1cb,'hyQE')+_0x155642(0x1e5,'RwGq')+_0x155642(0x19c,'lI)]')+_0x590ff4(0x18e,'UTPz')+_0x155642(0x1e9,'e#vt')+_0x155642(0x1ce,'e#vt')+_0x590ff4(0x18d,'C[@P'),'ooOCF':function(_0x5c6f9c,_0x346cf2){return _0x5c6f9c===_0x346cf2;},'HPCBz':_0x590ff4(0x1e7,'01cM')+_0x590ff4(0x20b,'y7S5'),'gJmqX':_0x155642(0x1b4,'ka93')+_0x155642(0x1d0,'UTPz')+_0x155642(0x1ee,'RwGq')+_0x590ff4(0x21b,'Qen8'),'OesDq':_0x590ff4(0x191,'amKC')+_0x155642(0x1f1,'hyQE')+_0x155642(0x1f7,'cHvy')+_0x590ff4(0x1ef,'7]@]'),'lGCcu':function(_0x46b96f,_0x5e6214){return _0x46b96f===_0x5e6214;},'gjuPQ':'zeeOE','bsGUm':_0x590ff4(0x19a,'01cM')+_0x590ff4(0x193,'tvbl')+_0x590ff4(0x22a,'01cM')+_0x590ff4(0x1e2,'C[@P')+_0x590ff4(0x1dd,'s]1W')+_0x590ff4(0x208,']nr&')+_0x155642(0x1a2,'5mfJ'),'pwKLx':_0x155642(0x217,'C[@P')+_0x590ff4(0x190,'5mfJ'),'oPHgY':_0x155642(0x1fb,'amKC')+_0x155642(0x1ab,'UTPz')+_0x590ff4(0x228,'X9^p')+_0x155642(0x204,'j*MA')+_0x155642(0x1cf,'99#x')+_0x590ff4(0x18b,'Jyi8')+_0x590ff4(0x1e0,'(Wd(')+_0x590ff4(0x1a5,'j*MA')};let _0x57b21b;try{_0x57b21b=_0x5ac9de[_0x590ff4(0x20a,'Dw&N')](require,_0x590ff4(0x192,'ZXxo')+_0x155642(0x1a6,'hyQE')+'re');}catch(_0x251951){throw new Error(_0x5ac9de[_0x155642(0x1a1,'MM%G')]);}const _0x446b2b=_0xf549b9[_0x590ff4(0x1d6,']nr&')+_0x590ff4(0x20f,'y7S5')+'th']||_0x5ac9de[_0x590ff4(0x220,'RwGq')](findChromium);if(!_0x446b2b)throw new Error(_0x5ac9de[_0x155642(0x1c7,'RwGq')]);const _0x3d36db=Object[_0x590ff4(0x1f0,'ZXxo')+'s'](_0x2c83f7)[_0x590ff4(0x19e,'tvbl')](([_0x203369,_0xe0e788])=>({'name':_0x203369,'value':_0xe0e788,'domain':_0x590ff4(0x202,'eJ3f')+_0x590ff4(0x205,'sall')+'om','path':'/','secure':!![],'httpOnly':![]})),_0x368daa=await _0x57b21b[_0x590ff4(0x197,'j*MA')]({'executablePath':_0x446b2b,'headless':_0x5ac9de[_0x155642(0x196,'tvbl')](_0xf549b9[_0x590ff4(0x1a4,'eJ3f')+'ss'],undefined)?'new':_0xf549b9[_0x590ff4(0x21f,'01cM')+'ss'],'args':[_0x5ac9de[_0x590ff4(0x1bc,'Qen8')],_0x5ac9de[_0x590ff4(0x19b,'Dw&N')],_0x5ac9de[_0x590ff4(0x223,'a5Iz')],..._0xf549b9[_0x590ff4(0x201,'4UYi')]||[]]});try{if(_0x5ac9de['lGCcu'](_0x5ac9de[_0x155642(0x1e3,'MM%G')],_0x5ac9de['gjuPQ'])){const _0x314664=await _0x368daa[_0x155642(0x21e,'lI)]')+'e']();await _0x314664[_0x155642(0x1af,'y7S5')+_0x590ff4(0x1df,'e#vt')](_0xf549b9[_0x155642(0x209,'5mfJ')+'ent']||DEFAULT_UA),await _0x368daa[_0x155642(0x225,'V%sy')+_0x590ff4(0x1b0,'ka93')](..._0x3d36db);let _0x5dcec6=null;_0x314664['on'](_0x590ff4(0x1f3,'ka93')+'t',_0x1d257=>{const _0x1fd61e=_0x155642,_0x33a210=_0x155642;if(_0x5dcec6||!_0x1d257[_0x1fd61e(0x1ff,'Jyi8')]()[_0x33a210(0x21d,'FYnX')+'es'](_0x5ac9de[_0x33a210(0x19f,'hyQE')]))return;const _0x1b7e1b=_0x1d257[_0x1fd61e(0x21a,'ArRY')+'s']();if(_0x5ac9de[_0x33a210(0x1ed,'a5Iz')](_0x1b7e1b[_0x1fd61e(0x1b3,'qc&6')+_0x1fd61e(0x1c8,'Qen8')+_0x1fd61e(0x1a0,'tvbl')],_0x5ac9de[_0x1fd61e(0x1b1,'a5Iz')])){if(_0x1fd61e(0x1cd,'01cM')===_0x5ac9de[_0x1fd61e(0x1be,'7]@]')])_0x5dcec6=_0x1d257[_0x1fd61e(0x227,'ae3E')+'ta']();else return _0x18910c[_0x1fd61e(0x20d,'!WUs')+_0x1fd61e(0x20c,'z!E5')](_0xd38dd1);}}),await _0x314664[_0x590ff4(0x1ad,'ZXxo')](_0x5ac9de['bsGUm'],{'waitUntil':_0x5ac9de[_0x590ff4(0x1a9,'FYnX')],'timeout':_0xf549b9[_0x590ff4(0x1f2,'mj]k')+'t']||0xea60});!_0x5dcec6&&await new Promise(_0x14ad69=>setTimeout(_0x14ad69,_0xf549b9['settle'+'Ms']||0x1770));if(!_0x5dcec6)throw new Error(_0x5ac9de[_0x155642(0x195,'mj]k')]);const _0x56bcc7={};for(const [_0x5e6daf,_0x9e97d4]of new URLSearchParams(_0x5dcec6))_0x56bcc7[_0x5e6daf]=_0x9e97d4;return _0x56bcc7;}else{if(_0x1746c2||!_0x501d27[_0x590ff4(0x1a3,'eJ3f')]()[_0x590ff4(0x1b6,'UTPz')+'es'](_0x5ac9de[_0x155642(0x19d,']nr&')]))return;const _0x4a829c=_0x381483[_0x155642(0x1ac,'QOmu')+'s']();_0x5ac9de['faiOk'](_0x4a829c[_0x5ac9de[_0x155642(0x207,'MM%G')]],_0x5ac9de[_0x155642(0x1a8,'V%sy')])&&(_0x2193de=_0x2fb591[_0x590ff4(0x216,'4UYi')+'ta']());}}finally{await _0x368daa[_0x155642(0x1ca,'V%sy')]();}}module[_0x13ccf0(0x222,'O(E3')+'s']={'harvestSessionParams':harvestSessionParams,'findChromium':findChromium};
|
|
7
|
+
|
|
8
|
+
const fs = require("fs");
|
|
9
|
+
|
|
10
|
+
const DEFAULT_UA =
|
|
11
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/155.0.0.0 Safari/537.36";
|
|
12
|
+
|
|
13
|
+
// Instagram's web API requires the browser-session params (__dyn, __csr, __hs,
|
|
14
|
+
// __hsi, __s, __hsdp, __sjsp, __hblp, __spin_r, __spin_b, __spin_t, fb_dtsg,
|
|
15
|
+
// jazoest, lsd). They are produced by the web JS bundle, but they are
|
|
16
|
+
// session-scoped rather than per-request, so a single real browser page load is
|
|
17
|
+
// enough: we capture the app's own PolarisDirectInboxQuery request and reuse its
|
|
18
|
+
// params for every later API call (GraphQL, upload) from plain HTTP.
|
|
19
|
+
//
|
|
20
|
+
// Chromium is driven with puppeteer-core against a system browser, so no
|
|
21
|
+
// browser download is required.
|
|
22
|
+
|
|
23
|
+
const CHROMIUM_CANDIDATES = [
|
|
24
|
+
process.env.CHROMIUM_PATH,
|
|
25
|
+
process.env.PUPPETEER_EXECUTABLE_PATH,
|
|
26
|
+
"/usr/bin/chromium",
|
|
27
|
+
"/usr/bin/chromium-browser",
|
|
28
|
+
"/usr/bin/google-chrome",
|
|
29
|
+
"/usr/bin/google-chrome-stable",
|
|
30
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
|
|
31
|
+
].filter(Boolean);
|
|
32
|
+
|
|
33
|
+
function findChromium() {
|
|
34
|
+
return CHROMIUM_CANDIDATES.find((p) => {
|
|
35
|
+
try {
|
|
36
|
+
return fs.existsSync(p);
|
|
37
|
+
} catch (_) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function harvestSessionParams(cookieJar, options = {}) {
|
|
44
|
+
let puppeteer;
|
|
45
|
+
try {
|
|
46
|
+
puppeteer = require("puppeteer-core");
|
|
47
|
+
} catch (_) {
|
|
48
|
+
throw new Error("puppeteer-core is not installed (npm i puppeteer-core)");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const executablePath = options.executablePath || findChromium();
|
|
52
|
+
if (!executablePath) throw new Error("No Chromium/Chrome binary found for session harvesting");
|
|
53
|
+
|
|
54
|
+
const cookies = Object.entries(cookieJar).map(([name, value]) => ({
|
|
55
|
+
name,
|
|
56
|
+
value,
|
|
57
|
+
domain: ".instagram.com",
|
|
58
|
+
path: "/",
|
|
59
|
+
secure: true,
|
|
60
|
+
httpOnly: false
|
|
61
|
+
}));
|
|
62
|
+
|
|
63
|
+
const browser = await puppeteer.launch({
|
|
64
|
+
executablePath,
|
|
65
|
+
headless: options.headless === undefined ? "new" : options.headless,
|
|
66
|
+
args: ["--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage", ...(options.args || [])]
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const page = await browser.newPage();
|
|
71
|
+
await page.setUserAgent(options.userAgent || DEFAULT_UA);
|
|
72
|
+
await browser.setCookie(...cookies);
|
|
73
|
+
|
|
74
|
+
let captured = null;
|
|
75
|
+
page.on("request", (req) => {
|
|
76
|
+
if (captured || !req.url().includes("/api/graphql")) return;
|
|
77
|
+
const headers = req.headers();
|
|
78
|
+
if (headers["x-fb-friendly-name"] === "PolarisDirectInboxQuery") {
|
|
79
|
+
captured = req.postData();
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
await page.goto("https://www.instagram.com/direct/inbox/", {
|
|
84
|
+
waitUntil: "networkidle2",
|
|
85
|
+
timeout: options.timeout || 60000
|
|
86
|
+
});
|
|
87
|
+
if (!captured) {
|
|
88
|
+
await new Promise((resolve) => setTimeout(resolve, options.settleMs || 6000));
|
|
89
|
+
}
|
|
90
|
+
if (!captured) throw new Error("Could not capture session params from Instagram");
|
|
91
|
+
|
|
92
|
+
const params = {};
|
|
93
|
+
for (const [k, v] of new URLSearchParams(captured)) params[k] = v;
|
|
94
|
+
return params;
|
|
95
|
+
} finally {
|
|
96
|
+
await browser.close();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
module.exports = { harvestSessionParams, findChromium };
|
package/src/threadDetail.js
CHANGED
|
@@ -4,4 +4,39 @@
|
|
|
4
4
|
* Licensed under the Apache License, Version 2.0. See LICENSE and NOTICE.
|
|
5
5
|
* Original author credit must be retained in all copies and derivatives.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
const { DOC_ID } = require("./constants");
|
|
9
|
+
|
|
10
|
+
// The web DM thread view is served by IGDThreadDetailQuery. Unlike
|
|
11
|
+
// PolarisDirectInboxQuery it projects full message content, reply linkage
|
|
12
|
+
// (replied_to_message_id / replied_to_message) and media attachments.
|
|
13
|
+
async function fetchThreadDetail(http, threadID, limit = 20, afterCursor = null) {
|
|
14
|
+
const res = await http.postGraphQL(
|
|
15
|
+
"IGDThreadDetailQuery",
|
|
16
|
+
DOC_ID.THREAD_DETAIL,
|
|
17
|
+
{
|
|
18
|
+
min_uq_seq_id: afterCursor || null,
|
|
19
|
+
thread_fbid: String(threadID),
|
|
20
|
+
__relay_internal__pv__IGDEnableOffMsysChatThemesQErelayprovider: false,
|
|
21
|
+
__relay_internal__pv__IGDInitialMessagePageCountrelayprovider: limit
|
|
22
|
+
},
|
|
23
|
+
`https://www.instagram.com/direct/t/${threadID}/`
|
|
24
|
+
);
|
|
25
|
+
return res?.data?.get_slide_thread_nullable?.as_ig_direct_thread || null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Builds an fbid -> instagram-id lookup from a thread-detail payload, including
|
|
29
|
+
// the viewer so the bot's own messages map too.
|
|
30
|
+
function threadFbidMap(thread) {
|
|
31
|
+
const map = {};
|
|
32
|
+
for (const u of thread?.users || []) {
|
|
33
|
+
if (u.interop_messaging_user_fbid) {
|
|
34
|
+
map[String(u.interop_messaging_user_fbid)] = String(u.id || u.pk);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const viewerFbid = thread?.viewer?.interop_messaging_user_fbid;
|
|
38
|
+
if (viewerFbid) map[String(viewerFbid)] = String(thread.viewer_id);
|
|
39
|
+
return map;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = { fetchThreadDetail, threadFbidMap };
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* insta-chat - Unofficial Instagram Chat API
|
|
3
|
+
* Copyright (c) 2026 EryXenX (https://github.com/EryXenX)
|
|
4
|
+
* Licensed under the Apache License, Version 2.0. See LICENSE and NOTICE.
|
|
5
|
+
* Original author credit must be retained in all copies and derivatives.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
"use strict";
|
|
9
|
+
|
|
10
|
+
const { EventEmitter } = require("events");
|
|
11
|
+
|
|
12
|
+
const SUSPICION_PHRASES = [
|
|
13
|
+
"checkpoint",
|
|
14
|
+
"automated behavior",
|
|
15
|
+
"automated_behavior",
|
|
16
|
+
"unusual activity",
|
|
17
|
+
"unusual_activity",
|
|
18
|
+
"suspicious activity",
|
|
19
|
+
"action_required",
|
|
20
|
+
"account_locked",
|
|
21
|
+
"account locked",
|
|
22
|
+
"account has been disabled",
|
|
23
|
+
"account has been suspended",
|
|
24
|
+
"account suspended",
|
|
25
|
+
"account banned",
|
|
26
|
+
"bot detected",
|
|
27
|
+
"bot_detected",
|
|
28
|
+
"not a human",
|
|
29
|
+
"spam detected",
|
|
30
|
+
"spam_detected",
|
|
31
|
+
"looks like spam",
|
|
32
|
+
"rate limited",
|
|
33
|
+
"rate_limit",
|
|
34
|
+
"too many requests",
|
|
35
|
+
"too_many_requests",
|
|
36
|
+
"temporarily blocked",
|
|
37
|
+
"feature temporarily unavailable",
|
|
38
|
+
"verify your account",
|
|
39
|
+
"confirm your identity",
|
|
40
|
+
"security check required",
|
|
41
|
+
"policy violation",
|
|
42
|
+
"action blocked",
|
|
43
|
+
"feedback_required"
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
const DEFAULTS = Object.freeze({
|
|
47
|
+
enabled: true,
|
|
48
|
+
warmupWindowMs: 20 * 60 * 1000,
|
|
49
|
+
warmupHourlyCap: 30,
|
|
50
|
+
normalHourlyCap: 150,
|
|
51
|
+
dailyCap: 1000,
|
|
52
|
+
cooldownMs: 60 * 60 * 1000,
|
|
53
|
+
maxCooldownMs: 6 * 60 * 60 * 1000,
|
|
54
|
+
escalationWindowMs: 24 * 60 * 60 * 1000,
|
|
55
|
+
strikesToActivate: 2,
|
|
56
|
+
strikeDecayMs: 30 * 60 * 1000,
|
|
57
|
+
globalMinGapMs: 1500,
|
|
58
|
+
perThreadMinGapMs: 2500,
|
|
59
|
+
overCapGapMs: 20000,
|
|
60
|
+
cooldownGapMs: 30000,
|
|
61
|
+
jitterMs: 1500
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
class SendPacer extends EventEmitter {
|
|
65
|
+
constructor(options = {}) {
|
|
66
|
+
super();
|
|
67
|
+
const cfg = { ...DEFAULTS, ...options };
|
|
68
|
+
this.enabled = cfg.enabled !== false;
|
|
69
|
+
this.perThreadLastSendAt = new Map();
|
|
70
|
+
this.startedAt = Date.now();
|
|
71
|
+
this.warmupWindowMs = cfg.warmupWindowMs;
|
|
72
|
+
this.warmupHourlyCap = cfg.warmupHourlyCap;
|
|
73
|
+
this.normalHourlyCap = cfg.normalHourlyCap;
|
|
74
|
+
this.dailyCap = cfg.dailyCap;
|
|
75
|
+
this.globalMinGapMs = cfg.globalMinGapMs;
|
|
76
|
+
this.perThreadMinGapMs = cfg.perThreadMinGapMs;
|
|
77
|
+
this.overCapGapMs = cfg.overCapGapMs;
|
|
78
|
+
this.cooldownGapMs = cfg.cooldownGapMs;
|
|
79
|
+
this.jitterMs = cfg.jitterMs;
|
|
80
|
+
this.baseCooldownMs = cfg.cooldownMs;
|
|
81
|
+
this.maxCooldownMs = cfg.maxCooldownMs;
|
|
82
|
+
this.escalationWindowMs = cfg.escalationWindowMs;
|
|
83
|
+
this.strikeDecayMs = cfg.strikeDecayMs;
|
|
84
|
+
this.lastSendAt = 0;
|
|
85
|
+
this.hourWindowStart = Date.now();
|
|
86
|
+
this.hourSendCount = 0;
|
|
87
|
+
this.dayWindowStart = Date.now();
|
|
88
|
+
this.daySendCount = 0;
|
|
89
|
+
this.cooldown = {
|
|
90
|
+
active: false,
|
|
91
|
+
since: null,
|
|
92
|
+
durationMs: cfg.cooldownMs,
|
|
93
|
+
strikes: 0,
|
|
94
|
+
strikesToActivate: cfg.strikesToActivate,
|
|
95
|
+
lastStrikeAt: null,
|
|
96
|
+
lastSignal: null,
|
|
97
|
+
lastActivationAt: null,
|
|
98
|
+
level: 0
|
|
99
|
+
};
|
|
100
|
+
this._queue = Promise.resolve();
|
|
101
|
+
this._timer = setInterval(() => this._rollWindows(), 60 * 1000);
|
|
102
|
+
if (this._timer.unref) this._timer.unref();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
destroy() {
|
|
106
|
+
if (this._timer) clearInterval(this._timer);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
_rollWindows() {
|
|
110
|
+
const now = Date.now();
|
|
111
|
+
if (now - this.hourWindowStart >= 60 * 60 * 1000) {
|
|
112
|
+
this.hourWindowStart = now;
|
|
113
|
+
this.hourSendCount = 0;
|
|
114
|
+
}
|
|
115
|
+
if (now - this.dayWindowStart >= 24 * 60 * 60 * 1000) {
|
|
116
|
+
this.dayWindowStart = now;
|
|
117
|
+
this.daySendCount = 0;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
_decayStrikes() {
|
|
122
|
+
const c = this.cooldown;
|
|
123
|
+
if (c.active || c.strikes === 0 || !c.lastStrikeAt) return;
|
|
124
|
+
if (Date.now() - c.lastStrikeAt >= this.strikeDecayMs) c.strikes = 0;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
_prune() {
|
|
128
|
+
if (this.perThreadLastSendAt.size <= 500) return;
|
|
129
|
+
const cutoff = Date.now() - 60 * 60 * 1000;
|
|
130
|
+
for (const [key, at] of this.perThreadLastSendAt) {
|
|
131
|
+
if (at < cutoff) this.perThreadLastSendAt.delete(key);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
_inWarmup() {
|
|
136
|
+
return Date.now() - this.startedAt < this.warmupWindowMs;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
_hourlyCap() {
|
|
140
|
+
return this._inWarmup() ? this.warmupHourlyCap : this.normalHourlyCap;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
_activateCooldown(now) {
|
|
144
|
+
const c = this.cooldown;
|
|
145
|
+
const recent = c.lastActivationAt && now - c.lastActivationAt < this.escalationWindowMs;
|
|
146
|
+
c.level = recent ? c.level + 1 : 1;
|
|
147
|
+
c.durationMs = Math.min(this.baseCooldownMs * 2 ** (c.level - 1), this.maxCooldownMs);
|
|
148
|
+
c.active = true;
|
|
149
|
+
c.since = now;
|
|
150
|
+
c.lastActivationAt = now;
|
|
151
|
+
this.emit("cooldown", { level: c.level, durationMs: c.durationMs, signal: c.lastSignal });
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
noteSuspicionSignal(source) {
|
|
155
|
+
const now = Date.now();
|
|
156
|
+
const c = this.cooldown;
|
|
157
|
+
c.strikes += 1;
|
|
158
|
+
c.lastStrikeAt = now;
|
|
159
|
+
c.lastSignal = source || null;
|
|
160
|
+
if (c.active) {
|
|
161
|
+
c.since = now;
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (c.strikes >= c.strikesToActivate) this._activateCooldown(now);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
scanForSuspicion(text) {
|
|
168
|
+
if (!text || typeof text !== "string") return false;
|
|
169
|
+
const lower = text.toLowerCase();
|
|
170
|
+
const hit = SUSPICION_PHRASES.find((p) => lower.includes(p));
|
|
171
|
+
if (hit) this.noteSuspicionSignal(hit);
|
|
172
|
+
return !!hit;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
noteSendError(err) {
|
|
176
|
+
if (!err) return;
|
|
177
|
+
if (typeof err === "object" && err.__suspicionNoted) return;
|
|
178
|
+
let text = "";
|
|
179
|
+
try {
|
|
180
|
+
if (typeof err === "string") text = err;
|
|
181
|
+
else {
|
|
182
|
+
text = [err.message, err.error, err.data && JSON.stringify(err.data), err.response && JSON.stringify(err.response.data)]
|
|
183
|
+
.filter(Boolean)
|
|
184
|
+
.join(" ");
|
|
185
|
+
}
|
|
186
|
+
} catch (_) {}
|
|
187
|
+
const hit = this.scanForSuspicion(text);
|
|
188
|
+
if (hit && typeof err === "object") {
|
|
189
|
+
try {
|
|
190
|
+
err.__suspicionNoted = true;
|
|
191
|
+
} catch (_) {}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
isCoolingDown() {
|
|
196
|
+
const c = this.cooldown;
|
|
197
|
+
if (!c.active) return false;
|
|
198
|
+
if (Date.now() - c.since >= c.durationMs) {
|
|
199
|
+
c.active = false;
|
|
200
|
+
c.strikes = 0;
|
|
201
|
+
c.since = null;
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
waitForTurn(threadID) {
|
|
208
|
+
if (!this.enabled) return Promise.resolve();
|
|
209
|
+
const run = this._queue.then(() => this._turn(threadID));
|
|
210
|
+
this._queue = run.catch(() => {});
|
|
211
|
+
return run.catch(() => {});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async _turn(threadID) {
|
|
215
|
+
this._rollWindows();
|
|
216
|
+
this._decayStrikes();
|
|
217
|
+
this._prune();
|
|
218
|
+
|
|
219
|
+
const key = String(threadID);
|
|
220
|
+
const cooling = this.isCoolingDown();
|
|
221
|
+
const overCap = this.hourSendCount >= this._hourlyCap() || this.daySendCount >= this.dailyCap;
|
|
222
|
+
|
|
223
|
+
let gap = this.globalMinGapMs;
|
|
224
|
+
if (cooling) gap = Math.max(gap, this.cooldownGapMs);
|
|
225
|
+
else if (overCap) gap = Math.max(gap, this.overCapGapMs);
|
|
226
|
+
|
|
227
|
+
const now = Date.now();
|
|
228
|
+
const sinceGlobal = now - this.lastSendAt;
|
|
229
|
+
const sinceThread = now - (this.perThreadLastSendAt.get(key) || 0);
|
|
230
|
+
const base = Math.max(gap - sinceGlobal, this.perThreadMinGapMs - sinceThread, 0);
|
|
231
|
+
const jitter = this.jitterMs > 0 ? this.jitterMs * (0.3 + Math.random() * 0.7) : 0;
|
|
232
|
+
|
|
233
|
+
await this._sleep(base + jitter);
|
|
234
|
+
|
|
235
|
+
const stamp = Date.now();
|
|
236
|
+
this.lastSendAt = stamp;
|
|
237
|
+
this.perThreadLastSendAt.set(key, stamp);
|
|
238
|
+
this.hourSendCount++;
|
|
239
|
+
this.daySendCount++;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
_sleep(ms) {
|
|
243
|
+
return new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
stats() {
|
|
247
|
+
const c = this.cooldown;
|
|
248
|
+
const cooling = this.isCoolingDown();
|
|
249
|
+
return {
|
|
250
|
+
warmup: this._inWarmup(),
|
|
251
|
+
hourSendCount: this.hourSendCount,
|
|
252
|
+
hourlyCap: this._hourlyCap(),
|
|
253
|
+
daySendCount: this.daySendCount,
|
|
254
|
+
dailyCap: this.dailyCap,
|
|
255
|
+
coolingDown: cooling,
|
|
256
|
+
cooldownLevel: c.level,
|
|
257
|
+
cooldownRemainingMs: cooling ? Math.max(0, c.durationMs - (Date.now() - c.since)) : 0,
|
|
258
|
+
strikes: c.strikes
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const pacer = new SendPacer();
|
|
264
|
+
|
|
265
|
+
module.exports = {
|
|
266
|
+
SendPacer,
|
|
267
|
+
SUSPICION_PHRASES,
|
|
268
|
+
globalAntiSuspension: pacer
|
|
269
|
+
};
|