2020-10-16 08:06:03 +00:00
|
|
|
"use strict";
|
2020-10-02 12:01:51 +00:00
|
|
|
|
2020-10-09 14:42:13 +00:00
|
|
|
// Public modules from npm
|
2020-10-31 15:00:26 +00:00
|
|
|
const axios = require("axios").default;
|
|
|
|
const _ = require("lodash");
|
2020-10-16 08:06:03 +00:00
|
|
|
const ky = require("ky-universal").create({
|
2020-10-29 21:14:40 +00:00
|
|
|
throwHttpErrors: false,
|
2020-10-09 14:42:13 +00:00
|
|
|
});
|
2020-11-01 08:54:59 +00:00
|
|
|
const cheerio = require("cheerio");
|
|
|
|
const qs = require("querystring");
|
2020-10-09 14:42:13 +00:00
|
|
|
|
2020-10-01 19:13:23 +00:00
|
|
|
// Modules from file
|
2020-10-31 15:00:26 +00:00
|
|
|
const shared = require("./shared.js");
|
2020-11-01 08:54:59 +00:00
|
|
|
const f95url = require("./constants/url.js");
|
|
|
|
|
|
|
|
// Global variables
|
|
|
|
const userAgent =
|
|
|
|
"Mozilla/5.0 (X11; Linux x86_64)" +
|
|
|
|
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.39 Safari/537.36";
|
2020-10-31 15:00:26 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @protected
|
|
|
|
* Gets the HTML code of a page.
|
|
|
|
* @param {String} url URL to fetch
|
|
|
|
* @returns {Promise<String>} HTML code or `null` if an error arise
|
|
|
|
*/
|
|
|
|
module.exports.fetchHTML = async function (url) {
|
|
|
|
try {
|
|
|
|
const response = await axios.get(url, {
|
|
|
|
headers: {
|
|
|
|
"User-Agent": userAgent
|
2020-11-01 08:54:59 +00:00
|
|
|
},
|
|
|
|
});
|
|
|
|
return response.data;
|
|
|
|
} catch (e) {
|
|
|
|
shared.logger.error(`Error ${e.message} occurred while trying to fetch ${url}`);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @protected
|
|
|
|
* Gets the HTML code of a login-protected page.
|
|
|
|
* @param {String} url URL to fetch
|
|
|
|
* @param {Credentials} credentials Platform access credentials
|
|
|
|
* @returns {Promise<String>} HTML code or `null` if an error arise
|
|
|
|
*/
|
|
|
|
module.exports.fetchHTMLWithAuth = async function (url, credentials) {
|
|
|
|
shared.logger.trace(`Fetching ${url} with user ${credentials.username}`);
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
"login": credentials.username,
|
|
|
|
"url": "",
|
|
|
|
"password": credentials.password,
|
|
|
|
"password_confirm": "",
|
|
|
|
"additional_security": "",
|
|
|
|
"remember": "1",
|
|
|
|
"_xfRedirect": "https://f95zone.to/",
|
|
|
|
"website_code": "",
|
|
|
|
"_xfToken": credentials.token,
|
|
|
|
};
|
|
|
|
|
|
|
|
const config = {
|
|
|
|
headers: {
|
|
|
|
"User-Agent": userAgent,
|
|
|
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
|
|
|
console.log(qs.stringify(data));
|
|
|
|
const response = await axios({
|
|
|
|
method: "post",
|
|
|
|
url: url,
|
|
|
|
data: qs.stringify(data),
|
|
|
|
headers: {
|
|
|
|
"user-agent": userAgent,
|
|
|
|
"content-type": "application/x-www-form-urlencoded;charset=utf-8"
|
|
|
|
},
|
|
|
|
withCredentials: true
|
2020-10-31 15:00:26 +00:00
|
|
|
});
|
2020-11-01 08:54:59 +00:00
|
|
|
//const response = await axios.post(url, qs.stringify(data), config);
|
2020-10-31 15:00:26 +00:00
|
|
|
return response.data;
|
|
|
|
} catch (e) {
|
|
|
|
shared.logger.error(`Error ${e.message} occurred while trying to fetch ${url}`);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-11-01 08:54:59 +00:00
|
|
|
/**
|
|
|
|
* Obtain the token used to authenticate the user to the platform.
|
|
|
|
* @returns {Promise<String>} Token or `null` if an error arise
|
|
|
|
*/
|
|
|
|
module.exports.getF95Token = async function() {
|
|
|
|
try {
|
|
|
|
// Fetch the response of the platform
|
|
|
|
const response = await axios.get(f95url.F95_LOGIN_URL, {
|
|
|
|
headers: {
|
|
|
|
"User-Agent": userAgent
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
// The response is a HTML page, we need to find the <input> with name "_xfToken"
|
|
|
|
const $ = cheerio.load(response.data);
|
|
|
|
const token = $("body").find("input[name='_xfToken']").attr("value");
|
|
|
|
return token;
|
|
|
|
} catch (e) {
|
|
|
|
shared.logger.error(`Error ${e.message} occurred while trying to fetch F95 token`);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-10-31 15:00:26 +00:00
|
|
|
/**
|
|
|
|
* @protected
|
|
|
|
* Enforces the scheme of the URL is https and returns the new URL.
|
|
|
|
* @param {String} url
|
|
|
|
* @returns {String}
|
|
|
|
*/
|
|
|
|
module.exports.enforceHttpsUrl = function (url) {
|
|
|
|
const value = _.isString(url) ? url.replace(/^(https?:)?\/\//, "https://") : null;
|
|
|
|
return value;
|
|
|
|
};
|
2020-10-01 19:13:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @protected
|
|
|
|
* Check if the url belongs to the domain of the F95 platform.
|
2020-10-08 21:08:20 +00:00
|
|
|
* @param {String} url URL to check
|
2020-10-01 19:13:23 +00:00
|
|
|
* @returns {Boolean} true if the url belongs to the domain, false otherwise
|
|
|
|
*/
|
2020-10-08 21:09:05 +00:00
|
|
|
module.exports.isF95URL = function (url) {
|
2020-11-01 08:54:59 +00:00
|
|
|
if (url.toString().startsWith(f95url.F95_BASE_URL)) return true;
|
2020-10-29 21:14:40 +00:00
|
|
|
else return false;
|
2020-10-08 21:09:05 +00:00
|
|
|
};
|
2020-10-01 19:13:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @protected
|
|
|
|
* Checks if the string passed by parameter has a properly formatted and valid path to a URL.
|
|
|
|
* @param {String} url String to check for correctness
|
|
|
|
* @returns {Boolean} true if the string is a valid URL, false otherwise
|
|
|
|
*/
|
2020-10-09 14:45:17 +00:00
|
|
|
module.exports.isStringAValidURL = function (url) {
|
2020-10-29 21:14:40 +00:00
|
|
|
try {
|
|
|
|
new URL(url); // skipcq: JS-0078
|
|
|
|
return true;
|
|
|
|
} catch (err) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-10-09 14:45:17 +00:00
|
|
|
};
|
2020-10-09 14:42:13 +00:00
|
|
|
|
|
|
|
/**
|
2020-10-20 20:47:36 +00:00
|
|
|
* @protected
|
2020-10-09 14:42:13 +00:00
|
|
|
* Check if a particular URL is valid and reachable on the web.
|
|
|
|
* @param {String} url URL to check
|
|
|
|
* @param {Boolean} checkRedirect If true, the function will consider redirects a violation and return false
|
|
|
|
* @returns {Promise<Boolean>} true if the URL exists, false otherwise
|
|
|
|
*/
|
2020-10-09 14:45:17 +00:00
|
|
|
module.exports.urlExists = async function (url, checkRedirect) {
|
2020-10-29 21:14:40 +00:00
|
|
|
if (!exports.isStringAValidURL(url)) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-10-09 14:45:17 +00:00
|
|
|
|
2020-10-29 21:14:40 +00:00
|
|
|
const response = await ky.head(url);
|
|
|
|
let valid = response !== undefined && !/4\d\d/.test(response.status);
|
2020-10-09 14:45:17 +00:00
|
|
|
|
2020-10-29 21:14:40 +00:00
|
|
|
if (!valid) return false;
|
2020-10-09 14:45:17 +00:00
|
|
|
|
2020-10-29 21:14:40 +00:00
|
|
|
if (checkRedirect) {
|
|
|
|
const redirectUrl = await exports.getUrlRedirect(url);
|
|
|
|
if (redirectUrl === url) valid = true;
|
|
|
|
else valid = false;
|
|
|
|
}
|
2020-10-09 14:45:17 +00:00
|
|
|
|
2020-10-29 21:14:40 +00:00
|
|
|
return valid;
|
2020-10-09 14:45:17 +00:00
|
|
|
};
|
2020-10-20 20:47:36 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @protected
|
|
|
|
* Check if the URL has a redirect to another page.
|
|
|
|
* @param {String} url URL to check for redirect
|
|
|
|
* @returns {Promise<String>} Redirect URL or the passed URL
|
|
|
|
*/
|
2020-10-20 20:48:42 +00:00
|
|
|
module.exports.getUrlRedirect = async function (url) {
|
2020-10-29 21:14:40 +00:00
|
|
|
const response = await ky.head(url);
|
|
|
|
return response.url;
|
2020-10-31 15:00:26 +00:00
|
|
|
};
|