dunbot / source /apis /utils.js
Duongkum999's picture
Upload 56 files
91d9d20 verified
raw
history blame
12.4 kB
var request = require("request").defaults({ jar: true });
var parseProxy = proxy => (proxy.match(/^(?:http:\/\/)?(?:(\S+):(\S+)@)?([A-Za-z0-9.-]+):(\d{2,5})$/) || []).slice(1);
var utilsLib = require("../lib/utils");
var log = require("../lib/log");
var stream = require("stream");
function setProxy(proxy) {
var proxyArray = parseProxy(proxy);
if (proxyArray)
request = require("request").defaults({ jar: true, proxy });
else
request = require("request").defaults({ jar: true });
}
function setHeaders(url, ctx, customHeaders) {
var headers = {
"Content-Type": "application/x-www-form-urlencoded",
Referer: "https://www.facebook.com/",
Host: new URL(url).hostname,
Origin: "https://www.facebook.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (Kbody, like Gecko) Chrome/127.0.0.0 Safari/537.36",
Connection: "keep-alive",
"sec-fetch-site": "same-origin"
}
if (customHeaders)
Object.assign(headers, customHeaders);
if (customHeaders && customHeaders.noRef) {
delete headers.Referer;
delete headers.noRef;
}
if (ctx && ctx.region)
headers["X-MSGR-Region"] = ctx.region;
return headers;
}
function get(url, jar, qs, ctx, customHeaders) {
if (utilsLib.getType(qs) === "Object") {
for (var prop in qs) {
if (qs.hasOwnProperty(prop) && utilsLib.getType(qs[prop]) === "Object") {
qs[prop] = JSON.stringify(qs[prop]);
}
}
}
var options = {
headers: setHeaders(url, ctx, customHeaders),
timeout: 60000,
qs,
url,
method: "GET",
jar,
gzip: true
}
var callback;
var returnPromise = new Promise(function (resolve, reject) {
callback = (error, response) => error ? reject(error) : resolve(response);
});
request(options, callback);
return returnPromise;
}
function post(url, jar, form, ctx, customHeaders) {
var options = {
headers: setHeaders(url, ctx, customHeaders),
timeout: 60000,
url,
method: "POST",
form,
jar,
gzip: true
}
var callback;
var returnPromise = new Promise(function (resolve, reject) {
callback = (error, response) => error ? reject(error) : resolve(response);
});
request(options, callback);
return returnPromise;
}
function postData(url, jar, formData, qs, ctx, customHeaders) {
if (utilsLib.getType(qs) === "Object") {
for (var prop in qs) {
if (qs.hasOwnProperty(prop) && utilsLib.getType(qs[prop]) === "Object") {
qs[prop] = JSON.stringify(qs[prop]);
}
}
}
var headers = setHeaders(url, ctx, customHeaders);
headers["Content-Type"] = "multipart/form-data";
var options = {
headers,
timeout: 60000,
url,
method: "POST",
formData,
qs,
jar,
gzip: true
}
var callback;
var returnPromise = new Promise(function (resolve, reject) {
callback = (error, response) => error ? reject(error) : resolve(response);
});
request(options, callback);
return returnPromise;
}
function isReadableStream(maybeStream) {
return (maybeStream instanceof stream.Stream && typeof maybeStream._read === "function" && utilsLib.getType(maybeStream._readableState) === "Object");
}
function getGUID() {
var sectionLength = Date.now();
var id = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
var r = Math.floor((sectionLength + Math.random() * 16) % 16);
sectionLength = Math.floor(sectionLength / 16);
var _guid = (c === "x" ? r : (r & 7) | 8).toString(16);
return _guid;
});
return id;
}
function getSignatureID() {
return Math.floor(Math.random() * 2147483648).toString(16);
}
function makeDefaults(body, userID, ctx) {
var reqCounter = 1;
var fb_dtsg = /\["DTSGInitData",\[],{"token":"(\S+)","async_get_token"/g.exec(body)[1];
var revision = /"server_revision":(\d+)/g.exec(body)[1];
function mergeWithDefaults(Obj) {
fb_dtsg = ctx.fb_dtsg ? ctx.fb_dtsg : fb_dtsg
var ttstamp = "2";
for (var i = 0; i < fb_dtsg.length; i++) {
ttstamp += fb_dtsg.charCodeAt(i);
}
var newObj = {
av: userID,
__user: userID,
__req: (reqCounter++).toString(36),
__rev: revision,
__a: 1,
fb_dtsg,
jazoest: ctx.ttstamp ? ctx.ttstamp : ttstamp
}
if (!Obj)
return newObj;
for (var prop in Obj)
if (Obj.hasOwnProperty(prop))
if (!newObj[prop])
newObj[prop] = Obj[prop];
return newObj;
}
function postWithDefaults(url, jar, form, ctxx = ctx, customHeaders) {
return post(url, jar, mergeWithDefaults(form), ctxx, customHeaders);
}
function getWithDefaults(url, jar, qs, ctxx = ctx, customHeaders) {
return get(url, jar, mergeWithDefaults(qs), ctxx, customHeaders);
}
function postDataWithDefault(url, jar, form, qs, ctxx = ctx, customHeaders) {
return postData(url, jar, mergeWithDefaults(form), mergeWithDefaults(qs), ctxx, customHeaders);
}
return {
get: getWithDefaults,
post: postWithDefaults,
postData: postDataWithDefault
}
}
function makeParsable(body) {
var withoutForLoop = body.replace(/for\s*\(\s*;\s*;\s*\)\s*;\s*/, "");
var maybeMultipleObjects = withoutForLoop.split(/\}\r\n *\{/);
if (maybeMultipleObjects.length === 1)
return maybeMultipleObjects;
return "[" + maybeMultipleObjects.join("},{") + "]";
}
function parseAndCheckLogin(ctx, http, retryCount) {
var delay = ms => new Promise(resolve => setTimeout(resolve, ms));
var _try = tryData => new Promise(function (resolve, reject) {
try {
resolve(tryData());
} catch (error) {
reject(error);
}
});
if (retryCount === undefined) retryCount = 0;
return function (data) {
function any() {
if (data.statusCode >= 500 && data.statusCode < 600) {
if (retryCount >= 5) {
var err = new Error("Request retry failed. Check the `res` and `statusCode` property on this error.");
err.statusCode = data.statusCode;
err.res = data.body;
err.error = "Request retry failed. Check the `res` and `statusCode` property on this error.";
throw err;
}
retryCount++;
var retryTime = Math.floor(Math.random() * 5000);
var url = data.request.uri.protocol + "//" + data.request.uri.hostname + data.request.uri.pathname;
if (data.request.headers["Content-Type"].split(";")[0] === "multipart/form-data") {
return delay(retryTime)
.then(function () {
return http
.postData(url, ctx.jar, data.request.formData);
})
.then(parseAndCheckLogin(ctx, http, retryCount));
}
else {
return delay(retryTime)
.then(function () {
return http
.post(url, ctx.jar, data.request.formData);
})
.then(parseAndCheckLogin(ctx, http, retryCount));
}
}
if (data.statusCode !== 200)
throw new Error("parseAndCheckLogin got status code: " + data.statusCode + ". Bailing out of trying to parse response.");
var res = null;
try {
res = JSON.parse(makeParsable(data.body));
} catch (e) {
var err = new Error("JSON.parse error. Check the `detail` property on this error.");
err.error = "JSON.parse error. Check the `detail` property on this error.";
err.detail = e;
err.res = data.body;
throw err;
}
if (res.redirect && data.request.method === "GET") {
return http
.get(res.redirect, ctx.jar)
.then(parseAndCheckLogin(ctx, http));
}
if (res.jsmods && res.jsmods.require && Array.isArray(res.jsmods.require[0]) && res.jsmods.require[0][0] === "Cookie") {
res.jsmods.require[0][3][0] = res.jsmods.require[0][3][0].replace("_js_", "");
var cookie = formatCookie(res.jsmods.require[0][3], "facebook");
var cookie2 = formatCookie(res.jsmods.require[0][3], "messenger");
ctx.jar.setCookie(request.cookie(cookie), "https://www.facebook.com");
ctx.jar.setCookie(request.cookie(cookie2), "https://www.messenger.com");
}
if (res.jsmods && Array.isArray(res.jsmods.require)) {
var arr = res.jsmods.require;
for (var i in arr) {
if (arr[i][0] === "DTSG" && arr[i][1] === "setToken") {
ctx.fb_dtsg = arr[i][3][0];
ctx.ttstamp = "2";
for (var j = 0; j < ctx.fb_dtsg.length; j++) {
ctx.ttstamp += ctx.fb_dtsg.charCodeAt(j);
}
}
}
}
if (res.error === 1357001) {
var err = new Error('Facebook blocked login. Please visit https://facebook.com and check your account.');
err.type = "Logout.";
throw err;
}
return res;
}
return _try(any);
}
}
function formatID(id) {
if (id != undefined && id != null) {
return id.replace(/(fb)?id[:.]/, "");
}
else {
return id;
}
}
function getDTSGInitData(ctx) {
return get("https://www.facebook.com", ctx.jar)
.then(function (res) {
var body = res.body;
ctx.fb_dtsg = /\["DTSGInitData",\[],{"token":"(.+?)"/g.exec(body)[1];
});
}
function binaryToDecimal(data) {
var ret = "";
while (data !== "0") {
var end = 0;
var fullName = "";
var i = 0;
for (; i < data.length; i++) {
end = 2 * end + parseInt(data[i], 10);
if (end >= 10) {
fullName += "1";
end -= 10;
} else
fullName += "0";
}
ret = end.toString() + ret;
data = fullName.slice(fullName.indexOf("1"));
}
return ret;
}
function generateOfflineThreadingID() {
var ret = Date.now();
var value = Math.floor(Math.random() * 4294967295);
var str = ("0000000000000000000000" + value.toString(2)).slice(-22);
var message = ret.toString(2) + str;
return binaryToDecimal(message);
}
function generateTimestampRelative() {
var d = new Date();
return d.getHours() + ":" + padZeros(d.getMinutes());
}
function padZeros(val, len) {
val = String(val);
len = len || 2;
while (val.length < len) val = "0" + val;
return val;
}
function generateThreadingID(clientID) {
var k = Date.now();
var l = Math.floor(Math.random() * 4294967295);
var m = clientID;
return "<" + k + ":" + l + "-" + m + "@mail.projektitan.com>";
}
var utils = {
getJar: request.jar,
cookie: request.cookie,
setProxy,
parseProxy,
get,
post,
postData,
isReadableStream,
getGUID,
getSignatureID,
makeDefaults,
parseAndCheckLogin,
formatID,
getDTSGInitData,
generateOfflineThreadingID,
generateTimestampRelative,
generateThreadingID
}
Object.assign(utils, utilsLib);
module.exports = utils;