Resolve conflicts
commit
987a9f08f0
86
app/index.js
86
app/index.js
|
@ -100,7 +100,7 @@ var _browser = null;
|
|||
module.exports.login = async function (username, password) {
|
||||
if (shared.isLogged) {
|
||||
if (shared.debug) console.log("Already logged in");
|
||||
let result = new LoginResult();
|
||||
const result = new LoginResult();
|
||||
result.success = true;
|
||||
result.message = "Already logged in";
|
||||
return result;
|
||||
|
@ -111,7 +111,7 @@ module.exports.login = async function (username, password) {
|
|||
if (shared.cookies !== null) {
|
||||
if (shared.debug) console.log("Valid session, no need to re-authenticate");
|
||||
shared.isLogged = true;
|
||||
let result = new LoginResult();
|
||||
const result = new LoginResult();
|
||||
result.success = true;
|
||||
result.message = "Logged with cookies";
|
||||
return result;
|
||||
|
@ -122,9 +122,9 @@ module.exports.login = async function (username, password) {
|
|||
console.log("No saved sessions or expired session, login on the platform");
|
||||
|
||||
if (_browser === null && !shared.isolation) _browser = await prepareBrowser();
|
||||
let browser = shared.isolation ? await prepareBrowser() : _browser;
|
||||
const browser = shared.isolation ? await prepareBrowser() : _browser;
|
||||
|
||||
let result = await loginF95(browser, username, password);
|
||||
const result = await loginF95(browser, username, password);
|
||||
shared.isLogged = result.success;
|
||||
|
||||
if (result.success) {
|
||||
|
@ -154,9 +154,9 @@ module.exports.loadF95BaseData = async function () {
|
|||
|
||||
// Prepare a new web page
|
||||
if (_browser === null && !shared.isolation) _browser = await prepareBrowser();
|
||||
let browser = shared.isolation ? await prepareBrowser() : _browser;
|
||||
const browser = shared.isolation ? await prepareBrowser() : _browser;
|
||||
|
||||
let page = await preparePage(browser); // Set new isolated page
|
||||
const page = await preparePage(browser); // Set new isolated page
|
||||
await page.setCookie(...shared.cookies); // Set cookies to avoid login
|
||||
|
||||
// Go to latest update page and wait for it to load
|
||||
|
@ -201,14 +201,14 @@ module.exports.chekIfGameHasUpdate = async function (info) {
|
|||
|
||||
// F95 change URL at every game update,
|
||||
// so if the URL is different an update is available
|
||||
let exists = await urlExists(info.f95url, true);
|
||||
const exists = await urlExists(info.f95url, true);
|
||||
if (!exists) return true;
|
||||
|
||||
// Parse version from title
|
||||
if (_browser === null && !shared.isolation) _browser = await prepareBrowser();
|
||||
let browser = shared.isolation ? await prepareBrowser() : _browser;
|
||||
const browser = shared.isolation ? await prepareBrowser() : _browser;
|
||||
|
||||
let onlineVersion = await scraper.getGameVersionFromTitle(browser, info);
|
||||
const onlineVersion = await scraper.getGameVersionFromTitle(browser, info);
|
||||
|
||||
if (shared.isolation) await browser.close();
|
||||
|
||||
|
@ -231,19 +231,19 @@ module.exports.getGameData = async function (name, includeMods) {
|
|||
|
||||
// Gets the search results of the game being searched for
|
||||
if (_browser === null && !shared.isolation) _browser = await prepareBrowser();
|
||||
let browser = shared.isolation ? await prepareBrowser() : _browser;
|
||||
let urlList = await searcher.getSearchGameResults(browser, name);
|
||||
const browser = shared.isolation ? await prepareBrowser() : _browser;
|
||||
const urlList = await searcher.getSearchGameResults(browser, name);
|
||||
|
||||
// Process previous partial results
|
||||
let promiseList = [];
|
||||
for (let url of urlList) {
|
||||
const promiseList = [];
|
||||
for (const url of urlList) {
|
||||
// Start looking for information
|
||||
promiseList.push(scraper.getGameInfo(browser, url));
|
||||
}
|
||||
|
||||
// Filter for mods
|
||||
let result = [];
|
||||
for (let info of await Promise.all(promiseList)) {
|
||||
const result = [];
|
||||
for (const info of await Promise.all(promiseList)) {
|
||||
// Skip mods if not required
|
||||
if (!info) continue;
|
||||
if (info.isMod && !includeMods) continue;
|
||||
|
@ -272,10 +272,10 @@ module.exports.getGameDataFromURL = async function (url) {
|
|||
|
||||
// Gets the search results of the game being searched for
|
||||
if (_browser === null && !shared.isolation) _browser = await prepareBrowser();
|
||||
let browser = shared.isolation ? await prepareBrowser() : _browser;
|
||||
const browser = shared.isolation ? await prepareBrowser() : _browser;
|
||||
|
||||
// Get game data
|
||||
let result = await scraper.getGameInfo(browser, url);
|
||||
const result = await scraper.getGameInfo(browser, url);
|
||||
|
||||
if (shared.isolation) await browser.close();
|
||||
return result;
|
||||
|
@ -294,8 +294,8 @@ module.exports.getUserData = async function () {
|
|||
|
||||
// Prepare a new web page
|
||||
if (_browser === null && !shared.isolation) _browser = await prepareBrowser();
|
||||
let browser = shared.isolation ? await prepareBrowser() : _browser;
|
||||
let page = await preparePage(browser); // Set new isolated page
|
||||
const browser = shared.isolation ? await prepareBrowser() : _browser;
|
||||
const page = await preparePage(browser); // Set new isolated page
|
||||
await page.setCookie(...shared.cookies); // Set cookies to avoid login
|
||||
await page.goto(constURLs.F95_BASE_URL); // Go to base page
|
||||
|
||||
|
@ -303,21 +303,21 @@ module.exports.getUserData = async function () {
|
|||
await page.waitForSelector(selectors.USERNAME_ELEMENT);
|
||||
await page.waitForSelector(selectors.AVATAR_PIC);
|
||||
|
||||
let threads = getUserWatchedGameThreads(browser);
|
||||
const threads = getUserWatchedGameThreads(browser);
|
||||
|
||||
let username = await page.evaluate(
|
||||
const username = await page.evaluate(
|
||||
/* istanbul ignore next */ (selector) =>
|
||||
document.querySelector(selector).innerText,
|
||||
selectors.USERNAME_ELEMENT
|
||||
);
|
||||
|
||||
let avatarSrc = await page.evaluate(
|
||||
const avatarSrc = await page.evaluate(
|
||||
/* istanbul ignore next */ (selector) =>
|
||||
document.querySelector(selector).getAttribute("src"),
|
||||
selectors.AVATAR_PIC
|
||||
);
|
||||
|
||||
let ud = new UserData();
|
||||
const ud = new UserData();
|
||||
ud.username = username;
|
||||
ud.avatarSrc = isStringAValidURL(avatarSrc) ? avatarSrc : null;
|
||||
ud.watchedThreads = await threads;
|
||||
|
@ -360,11 +360,11 @@ function loadCookies() {
|
|||
// Check the existence of the cookie file
|
||||
if (fs.existsSync(shared.cookiesCachePath)) {
|
||||
// Read cookies
|
||||
let cookiesJSON = fs.readFileSync(shared.cookiesCachePath);
|
||||
let cookies = JSON.parse(cookiesJSON);
|
||||
const cookiesJSON = fs.readFileSync(shared.cookiesCachePath);
|
||||
const cookies = JSON.parse(cookiesJSON);
|
||||
|
||||
// Check if the cookies have expired
|
||||
for (let cookie of cookies) {
|
||||
for (const cookie of cookies) {
|
||||
if (isCookieExpired(cookie)) return null;
|
||||
}
|
||||
|
||||
|
@ -383,11 +383,11 @@ function isCookieExpired(cookie) {
|
|||
let expiredCookies = false;
|
||||
|
||||
// Ignore cookies that never expire
|
||||
let expirationUnixTimestamp = cookie["expire"];
|
||||
const expirationUnixTimestamp = cookie["expire"];
|
||||
|
||||
if (expirationUnixTimestamp !== "-1") {
|
||||
// Convert UNIX epoch timestamp to normal Date
|
||||
let expirationDate = new Date(expirationUnixTimestamp * 1000);
|
||||
const expirationDate = new Date(expirationUnixTimestamp * 1000);
|
||||
|
||||
if (expirationDate < Date.now()) {
|
||||
if (shared.debug)
|
||||
|
@ -423,14 +423,14 @@ async function loadValuesFromLatestPage(
|
|||
// If the values already exist they are loaded from disk without having to connect to F95
|
||||
if (shared.debug) console.log("Load " + elementRequested + " from disk...");
|
||||
if (fs.existsSync(path)) {
|
||||
let valueJSON = fs.readFileSync(path);
|
||||
const valueJSON = fs.readFileSync(path);
|
||||
return JSON.parse(valueJSON);
|
||||
}
|
||||
|
||||
// Otherwise, connect and download the data from the portal
|
||||
if (shared.debug)
|
||||
console.log("No " + elementRequested + " cached, downloading...");
|
||||
let values = await getValuesFromLatestPage(
|
||||
const values = await getValuesFromLatestPage(
|
||||
page,
|
||||
selector,
|
||||
"Getting " + elementRequested + " from page"
|
||||
|
@ -451,11 +451,11 @@ async function loadValuesFromLatestPage(
|
|||
async function getValuesFromLatestPage(page, selector, logMessage) {
|
||||
if (shared.debug) console.log(logMessage);
|
||||
|
||||
let result = [];
|
||||
let elements = await page.$$(selector);
|
||||
const result = [];
|
||||
const elements = await page.$$(selector);
|
||||
|
||||
for (let element of elements) {
|
||||
let text = await element.evaluate(
|
||||
for (const element of elements) {
|
||||
const text = await element.evaluate(
|
||||
/* istanbul ignore next */ (e) => e.innerText
|
||||
);
|
||||
|
||||
|
@ -476,7 +476,7 @@ async function getValuesFromLatestPage(page, selector, logMessage) {
|
|||
* @returns {Promise<LoginResult>} Result of the operation
|
||||
*/
|
||||
async function loginF95(browser, username, password) {
|
||||
let page = await preparePage(browser); // Set new isolated page
|
||||
const page = await preparePage(browser); // Set new isolated page
|
||||
await page.goto(constURLs.F95_LOGIN_URL); // Go to login page
|
||||
|
||||
// Explicitly wait for the required items to load
|
||||
|
@ -494,7 +494,7 @@ async function loginF95(browser, username, password) {
|
|||
]);
|
||||
|
||||
// Prepare result
|
||||
let result = new LoginResult();
|
||||
const result = new LoginResult();
|
||||
|
||||
// Check if the user is logged in
|
||||
result.success = await page.evaluate(
|
||||
|
@ -505,7 +505,7 @@ async function loginF95(browser, username, password) {
|
|||
|
||||
// Save cookies to avoid re-auth
|
||||
if (result.success) {
|
||||
let c = await page.cookies();
|
||||
const c = await page.cookies();
|
||||
fs.writeFileSync(shared.cookiesCachePath, JSON.stringify(c));
|
||||
result.message = "Authentication successful";
|
||||
}
|
||||
|
@ -517,7 +517,7 @@ async function loginF95(browser, username, password) {
|
|||
selectors.LOGIN_MESSAGE_ERROR
|
||||
)
|
||||
) {
|
||||
let errorMessage = await page.evaluate(
|
||||
const errorMessage = await page.evaluate(
|
||||
/* istanbul ignore next */ (selector) =>
|
||||
document.querySelector(selector).innerText,
|
||||
selectors.LOGIN_MESSAGE_ERROR
|
||||
|
@ -543,7 +543,7 @@ async function loginF95(browser, username, password) {
|
|||
* @returns {Promise<String[]>} URL list
|
||||
*/
|
||||
async function getUserWatchedGameThreads(browser) {
|
||||
let page = await preparePage(browser); // Set new isolated page
|
||||
const page = await preparePage(browser); // Set new isolated page
|
||||
await page.goto(constURLs.F95_WATCHED_THREADS); // Go to the thread page
|
||||
|
||||
// Explicitly wait for the required items to load
|
||||
|
@ -569,17 +569,17 @@ async function getUserWatchedGameThreads(browser) {
|
|||
await page.waitForSelector(selectors.WATCHED_THREAD_URLS);
|
||||
|
||||
// Get the threads urls
|
||||
let urls = [];
|
||||
const urls = [];
|
||||
let nextPageExists = false;
|
||||
do {
|
||||
// Get all the URLs
|
||||
for (let handle of await page.$$(selectors.WATCHED_THREAD_URLS)) {
|
||||
let src = await page.evaluate(
|
||||
for (const handle of await page.$$(selectors.WATCHED_THREAD_URLS)) {
|
||||
const src = await page.evaluate(
|
||||
/* istanbul ignore next */ (element) => element.href,
|
||||
handle
|
||||
);
|
||||
// If 'unread' is left, it will redirect to the last unread post
|
||||
let url = src.replace("/unread", "");
|
||||
const url = src.replace("/unread", "");
|
||||
urls.push(url);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,36 +53,36 @@ module.exports = GameDownload;
|
|||
|
||||
async function downloadMEGA(url, savepath) {
|
||||
// The URL is masked
|
||||
let browser = await prepareBrowser();
|
||||
let page = await preparePage(browser);
|
||||
const browser = await prepareBrowser();
|
||||
const page = await preparePage(browser);
|
||||
await page.setCookie(...shared.cookies); // Set cookies to avoid login
|
||||
await page.goto(url);
|
||||
await page.waitForSelector("a.host_link");
|
||||
|
||||
// Obtain the link for the unmasked page and click it
|
||||
let link = await page.$("a.host_link");
|
||||
const link = await page.$("a.host_link");
|
||||
await link.click();
|
||||
await page.goto(url, {
|
||||
waitUntil: shared.WAIT_STATEMENT,
|
||||
}); // Go to the game page and wait until it loads
|
||||
|
||||
// Obtain the URL after the redirect
|
||||
let downloadURL = page.url();
|
||||
const downloadURL = page.url();
|
||||
|
||||
// Close browser and page
|
||||
await page.close();
|
||||
await browser.close();
|
||||
|
||||
let stream = fs.createWriteStream(savepath);
|
||||
let file = File.fromURL(downloadURL);
|
||||
const stream = fs.createWriteStream(savepath);
|
||||
const file = File.fromURL(downloadURL);
|
||||
file.download().pipe(stream);
|
||||
return fs.existsSync(savepath);
|
||||
}
|
||||
|
||||
async function downloadNOPY(url, savepath) {
|
||||
// Prepare browser
|
||||
let browser = await prepareBrowser();
|
||||
let page = await preparePage(browser);
|
||||
const browser = await prepareBrowser();
|
||||
const page = await preparePage(browser);
|
||||
await page.goto(url);
|
||||
await page.waitForSelector("#download");
|
||||
|
||||
|
@ -93,7 +93,7 @@ async function downloadNOPY(url, savepath) {
|
|||
});
|
||||
|
||||
// Obtain the download button and click it
|
||||
let downloadButton = await page.$("#download");
|
||||
const downloadButton = await page.$("#download");
|
||||
await downloadButton.click();
|
||||
|
||||
// Await for all the connections to close
|
||||
|
|
|
@ -25,10 +25,10 @@ module.exports.getGameInfo = async function (browser, url) {
|
|||
|
||||
// Verify the correctness of the URL
|
||||
if (!isF95URL(url)) throw url + " is not a valid F95Zone URL";
|
||||
let exists = await urlExists(url);
|
||||
const exists = await urlExists(url);
|
||||
if (!exists) return null;
|
||||
|
||||
let page = await preparePage(browser); // Set new isolated page
|
||||
const page = await preparePage(browser); // Set new isolated page
|
||||
await page.setCookie(...shared.cookies); // Set cookies to avoid login
|
||||
await page.goto(url, {
|
||||
waitUntil: shared.WAIT_STATEMENT,
|
||||
|
@ -37,16 +37,16 @@ module.exports.getGameInfo = async function (browser, url) {
|
|||
// It asynchronously searches for the elements and
|
||||
// then waits at the end to compile the object to be returned
|
||||
let info = new GameInfo();
|
||||
let title = getGameTitle(page);
|
||||
let author = getGameAuthor(page);
|
||||
let tags = getGameTags(page);
|
||||
let previewSource = getGamePreviewSource(page);
|
||||
const title = getGameTitle(page);
|
||||
const author = getGameAuthor(page);
|
||||
const tags = getGameTags(page);
|
||||
const previewSource = getGamePreviewSource(page);
|
||||
//let downloadData = getGameDownloadLink(page);
|
||||
info = await parsePrefixes(page, info); // Fill status/engines/isMod
|
||||
let structuredText = await getMainPostStructuredText(page);
|
||||
let overview = getOverview(structuredText, info.isMod);
|
||||
let parsedInfos = parseConversationPage(structuredText);
|
||||
let changelog = getLastChangelog(page);
|
||||
const structuredText = await getMainPostStructuredText(page);
|
||||
const overview = getOverview(structuredText, info.isMod);
|
||||
const parsedInfos = parseConversationPage(structuredText);
|
||||
const changelog = getLastChangelog(page);
|
||||
|
||||
// Fill in the GameInfo element with the information obtained
|
||||
info.name = await title;
|
||||
|
@ -80,23 +80,23 @@ module.exports.getGameInfo = async function (browser, url) {
|
|||
* @returns {Promise<String>} Online version of the game
|
||||
*/
|
||||
module.exports.getGameVersionFromTitle = async function (browser, info) {
|
||||
let page = await preparePage(browser); // Set new isolated page
|
||||
const page = await preparePage(browser); // Set new isolated page
|
||||
await page.setCookie(...shared.cookies); // Set cookies to avoid login
|
||||
await page.goto(info.f95url, {
|
||||
waitUntil: shared.WAIT_STATEMENT,
|
||||
}); // Go to the game page and wait until it loads
|
||||
|
||||
// Get the title
|
||||
let titleHTML = await page.evaluate(
|
||||
const titleHTML = await page.evaluate(
|
||||
/* istanbul ignore next */
|
||||
(selector) => document.querySelector(selector).innerHTML,
|
||||
selectors.GAME_TITLE
|
||||
);
|
||||
let title = HTMLParser.parse(titleHTML).childNodes.pop().rawText;
|
||||
const title = HTMLParser.parse(titleHTML).childNodes.pop().rawText;
|
||||
|
||||
// The title is in the following format: [PREFIXES] NAME GAME [VERSION] [AUTHOR]
|
||||
let startIndex = title.indexOf("[") + 1;
|
||||
let endIndex = title.indexOf("]", startIndex);
|
||||
const startIndex = title.indexOf("[") + 1;
|
||||
const endIndex = title.indexOf("]", startIndex);
|
||||
let version = title.substring(startIndex, endIndex).trim().toUpperCase();
|
||||
if (version.startsWith("V")) version = version.replace("V", ""); // Replace only the first occurrence
|
||||
return version;
|
||||
|
@ -128,10 +128,10 @@ function getOverview(text, isMod) {
|
|||
*/
|
||||
async function getMainPostStructuredText(page) {
|
||||
// Gets the first post, where are listed all the game's informations
|
||||
let post = (await page.$$(selectors.THREAD_POSTS))[0];
|
||||
const post = (await page.$$(selectors.THREAD_POSTS))[0];
|
||||
|
||||
// The info are plain text so we need to parse the HTML code
|
||||
let bodyHTML = await page.evaluate(
|
||||
const bodyHTML = await page.evaluate(
|
||||
/* istanbul ignore next */ (mainPost) => mainPost.innerHTML,
|
||||
post
|
||||
);
|
||||
|
@ -146,18 +146,18 @@ async function getMainPostStructuredText(page) {
|
|||
*/
|
||||
async function getGameAuthor(page) {
|
||||
// Get the game/mod name (without square brackets)
|
||||
let titleHTML = await page.evaluate(
|
||||
const titleHTML = await page.evaluate(
|
||||
/* istanbul ignore next */ (selector) =>
|
||||
document.querySelector(selector).innerHTML,
|
||||
selectors.GAME_TITLE
|
||||
);
|
||||
let structuredTitle = HTMLParser.parse(titleHTML);
|
||||
const structuredTitle = HTMLParser.parse(titleHTML);
|
||||
|
||||
// The last element **shoud be** the title without prefixes (engines, status, other...)
|
||||
let gameTitle = structuredTitle.childNodes.pop().rawText;
|
||||
const gameTitle = structuredTitle.childNodes.pop().rawText;
|
||||
|
||||
// The last square brackets contain the author
|
||||
let startTitleIndex = gameTitle.lastIndexOf("[") + 1;
|
||||
const startTitleIndex = gameTitle.lastIndexOf("[") + 1;
|
||||
return gameTitle.substring(startTitleIndex, gameTitle.length - 1).trim();
|
||||
}
|
||||
|
||||
|
@ -169,17 +169,17 @@ async function getGameAuthor(page) {
|
|||
* @returns {Object} Dictionary of information
|
||||
*/
|
||||
function parseConversationPage(text) {
|
||||
let dataPairs = {};
|
||||
const dataPairs = {};
|
||||
|
||||
// The information searched in the game post are one per line
|
||||
let splittedText = text.split("\n");
|
||||
for (let line of splittedText) {
|
||||
const splittedText = text.split("\n");
|
||||
for (const line of splittedText) {
|
||||
if (!line.includes(":")) continue;
|
||||
|
||||
// Create pair key/value
|
||||
let splitted = line.split(":");
|
||||
let key = splitted[0].trim().toUpperCase(); // Uppercase to avoid mismatch
|
||||
let value = splitted[1].trim();
|
||||
const splitted = line.split(":");
|
||||
const key = splitted[0].trim().toUpperCase(); // Uppercase to avoid mismatch
|
||||
const value = splitted[1].trim();
|
||||
|
||||
// Add pair to the dict if valid
|
||||
if (value != "") dataPairs[key] = value;
|
||||
|
@ -195,10 +195,10 @@ function parseConversationPage(text) {
|
|||
* @returns {Promise<String>} URL (String) of the image or null if failed to get it
|
||||
*/
|
||||
async function getGamePreviewSource(page) {
|
||||
let src = await page.evaluate(
|
||||
const src = await page.evaluate(
|
||||
/* istanbul ignore next */ (selector) => {
|
||||
// Get the firs image available
|
||||
let img = document.querySelector(selector);
|
||||
const img = document.querySelector(selector);
|
||||
|
||||
if (img) return img.getAttribute("src");
|
||||
else return null;
|
||||
|
@ -218,16 +218,16 @@ async function getGamePreviewSource(page) {
|
|||
*/
|
||||
async function getGameTitle(page) {
|
||||
// Get the game/mod name (without square brackets)
|
||||
let titleHTML = await page.evaluate(
|
||||
const titleHTML = await page.evaluate(
|
||||
/* istanbul ignore next */ (selector) =>
|
||||
document.querySelector(selector).innerHTML,
|
||||
selectors.GAME_TITLE
|
||||
);
|
||||
let structuredTitle = HTMLParser.parse(titleHTML);
|
||||
const structuredTitle = HTMLParser.parse(titleHTML);
|
||||
|
||||
// The last element **shoud be** the title without prefixes (engines, status, other...)
|
||||
let gameTitle = structuredTitle.childNodes.pop().rawText;
|
||||
let endTitleIndex = gameTitle.indexOf("[");
|
||||
const gameTitle = structuredTitle.childNodes.pop().rawText;
|
||||
const endTitleIndex = gameTitle.indexOf("[");
|
||||
return gameTitle.substring(0, endTitleIndex).trim();
|
||||
}
|
||||
|
||||
|
@ -238,11 +238,11 @@ async function getGameTitle(page) {
|
|||
* @returns {Promise<String[]>} List of uppercase tags
|
||||
*/
|
||||
async function getGameTags(page) {
|
||||
let tags = [];
|
||||
const tags = [];
|
||||
|
||||
// Get the game tags
|
||||
for (let handle of await page.$$(selectors.GAME_TAGS)) {
|
||||
let tag = await page.evaluate(
|
||||
for (const handle of await page.$$(selectors.GAME_TAGS)) {
|
||||
const tag = await page.evaluate(
|
||||
/* istanbul ignore next */ (element) => element.innerText,
|
||||
handle
|
||||
);
|
||||
|
@ -264,14 +264,14 @@ async function parsePrefixes(page, info) {
|
|||
|
||||
// The 'Ongoing' status is not specified, only 'Abandoned'/'OnHold'/'Complete'
|
||||
info.status = "Ongoing";
|
||||
for (let handle of await page.$$(selectors.GAME_TITLE_PREFIXES)) {
|
||||
let value = await page.evaluate(
|
||||
for (const handle of await page.$$(selectors.GAME_TITLE_PREFIXES)) {
|
||||
const value = await page.evaluate(
|
||||
/* istanbul ignore next */ (element) => element.innerText,
|
||||
handle
|
||||
);
|
||||
|
||||
// Clean the prefix
|
||||
let prefix = value.toUpperCase().replace("[", "").replace("]", "").trim();
|
||||
const prefix = value.toUpperCase().replace("[", "").replace("]", "").trim();
|
||||
|
||||
// Getting infos...
|
||||
if (shared.statuses.includes(prefix)) info.status = prefix;
|
||||
|
@ -290,17 +290,17 @@ async function parsePrefixes(page, info) {
|
|||
*/
|
||||
async function getLastChangelog(page) {
|
||||
// Gets the first post, where are listed all the game's informations
|
||||
let post = (await page.$$(selectors.THREAD_POSTS))[0];
|
||||
const post = (await page.$$(selectors.THREAD_POSTS))[0];
|
||||
|
||||
let spoiler = await post.$(selectors.THREAD_LAST_CHANGELOG);
|
||||
const spoiler = await post.$(selectors.THREAD_LAST_CHANGELOG);
|
||||
if (!spoiler) return null;
|
||||
|
||||
let changelogHTML = await page.evaluate(
|
||||
const changelogHTML = await page.evaluate(
|
||||
/* istanbul ignore next */
|
||||
(e) => e.innerText,
|
||||
spoiler
|
||||
);
|
||||
let parsedText = HTMLParser.parse(changelogHTML).structuredText;
|
||||
const parsedText = HTMLParser.parse(changelogHTML).structuredText;
|
||||
return parsedText.replace("Spoiler", "").trim();
|
||||
}
|
||||
|
||||
|
@ -312,7 +312,7 @@ async function getLastChangelog(page) {
|
|||
*/
|
||||
async function getGameDownloadLink(page) {
|
||||
// Most used hosting platforms
|
||||
let hostingPlatforms = [
|
||||
const hostingPlatforms = [
|
||||
"MEGA",
|
||||
"NOPY",
|
||||
"FILESUPLOAD",
|
||||
|
@ -323,19 +323,19 @@ async function getGameDownloadLink(page) {
|
|||
];
|
||||
|
||||
// Supported OS platforms
|
||||
let platformOS = ["WIN", "LINUX", "MAC", "ALL"];
|
||||
const platformOS = ["WIN", "LINUX", "MAC", "ALL"];
|
||||
|
||||
// Gets the <span> which contains the download links
|
||||
let temp = await page.$$(selectors.DOWNLOAD_LINKS_CONTAINER);
|
||||
const temp = await page.$$(selectors.DOWNLOAD_LINKS_CONTAINER);
|
||||
if (temp.length === 0) return [];
|
||||
|
||||
// Look for the container that contains the links
|
||||
// It is necessary because the same css selector
|
||||
// also identifies other elements on the page
|
||||
let container = null;
|
||||
for (let candidate of temp) {
|
||||
for (const candidate of temp) {
|
||||
if (container !== null) break;
|
||||
let upperText = (
|
||||
const upperText = (
|
||||
await page.evaluate(
|
||||
/* istanbul ignore next */ (e) => e.innerText,
|
||||
candidate
|
||||
|
@ -343,7 +343,7 @@ async function getGameDownloadLink(page) {
|
|||
).toUpperCase();
|
||||
|
||||
// Search if the container contains the name of a hosting platform
|
||||
for (let p of hostingPlatforms) {
|
||||
for (const p of hostingPlatforms) {
|
||||
if (upperText.includes(p)) {
|
||||
container = candidate;
|
||||
break;
|
||||
|
@ -353,7 +353,7 @@ async function getGameDownloadLink(page) {
|
|||
if (container === null) return [];
|
||||
|
||||
// Extract the HTML text from the container
|
||||
let searchText = (
|
||||
const searchText = (
|
||||
await page.evaluate(
|
||||
/* istanbul ignore next */ (e) => e.innerHTML,
|
||||
container
|
||||
|
@ -361,9 +361,9 @@ async function getGameDownloadLink(page) {
|
|||
).toLowerCase();
|
||||
|
||||
// Parse the download links
|
||||
let downloadData = [];
|
||||
for (let platform of platformOS) {
|
||||
let data = extractGameHostingData(platform, searchText);
|
||||
const downloadData = [];
|
||||
for (const platform of platformOS) {
|
||||
const data = extractGameHostingData(platform, searchText);
|
||||
downloadData.push(...data);
|
||||
}
|
||||
return downloadData;
|
||||
|
@ -397,29 +397,30 @@ function extractGameHostingData(platform, text) {
|
|||
|
||||
// Find the end of the container
|
||||
if (endIndex === -1)
|
||||
endIndex = text.indexOf(CONTAINER_SPAN_CLOSE, startIndex) +
|
||||
endIndex =
|
||||
text.indexOf(CONTAINER_SPAN_CLOSE, startIndex) +
|
||||
CONTAINER_SPAN_CLOSE.length;
|
||||
|
||||
text = text.substring(startIndex, endIndex);
|
||||
|
||||
let downloadData = [];
|
||||
let linkTags = text.split(LINK_OPEN);
|
||||
for (let tag of linkTags) {
|
||||
const downloadData = [];
|
||||
const linkTags = text.split(LINK_OPEN);
|
||||
for (const tag of linkTags) {
|
||||
// Ignore non-link string
|
||||
if (!tag.includes(HREF_START)) continue;
|
||||
|
||||
// Find the hosting platform name
|
||||
startIndex = tag.indexOf(TAG_CLOSE) + TAG_CLOSE.length;
|
||||
endIndex = tag.indexOf(LINK_CLOSE, startIndex);
|
||||
let hosting = tag.substring(startIndex, endIndex);
|
||||
const hosting = tag.substring(startIndex, endIndex);
|
||||
|
||||
// Find the 'href' attribute
|
||||
startIndex = tag.indexOf(HREF_START) + HREF_START.length;
|
||||
endIndex = tag.indexOf(HREF_END, startIndex);
|
||||
let link = tag.substring(startIndex, endIndex);
|
||||
const link = tag.substring(startIndex, endIndex);
|
||||
|
||||
if (isStringAValidURL(link)) {
|
||||
let gd = new GameDownload();
|
||||
const gd = new GameDownload();
|
||||
gd.hosting = hosting.toUpperCase();
|
||||
gd.link = link;
|
||||
gd.supportedOS = platform.toUpperCase();
|
||||
|
|
|
@ -20,7 +20,7 @@ const { isF95URL } = require("./urls-helper.js");
|
|||
module.exports.getSearchGameResults = async function (browser, gamename) {
|
||||
if (shared.debug) console.log("Searching " + gamename + " on F95Zone");
|
||||
|
||||
let page = await preparePage(browser); // Set new isolated page
|
||||
const page = await preparePage(browser); // Set new isolated page
|
||||
await page.setCookie(...shared.cookies); // Set cookies to avoid login
|
||||
await page.goto(constURLs.F95_SEARCH_URL, {
|
||||
waitUntil: shared.WAIT_STATEMENT,
|
||||
|
@ -41,13 +41,13 @@ module.exports.getSearchGameResults = async function (browser, gamename) {
|
|||
]);
|
||||
|
||||
// Select all conversation titles
|
||||
let resultsThread = await page.$$(selectors.SEARCH_THREADS_RESULTS_BODY);
|
||||
const resultsThread = await page.$$(selectors.SEARCH_THREADS_RESULTS_BODY);
|
||||
|
||||
// For each element found extract the info about the conversation
|
||||
if (shared.debug) console.log("Extracting info from conversations");
|
||||
let results = [];
|
||||
for (let element of resultsThread) {
|
||||
let gameUrl = await getOnlyGameThreads(page, element);
|
||||
const results = [];
|
||||
for (const element of resultsThread) {
|
||||
const gameUrl = await getOnlyGameThreads(page, element);
|
||||
if (gameUrl !== null) results.push(gameUrl);
|
||||
}
|
||||
if (shared.debug) console.log("Find " + results.length + " conversations");
|
||||
|
@ -66,11 +66,11 @@ module.exports.getSearchGameResults = async function (browser, gamename) {
|
|||
*/
|
||||
async function getOnlyGameThreads(page, divHandle) {
|
||||
// Obtain the elements containing the basic information
|
||||
let titleHandle = await divHandle.$(selectors.THREAD_TITLE);
|
||||
let forumHandle = await divHandle.$(selectors.SEARCH_THREADS_MEMBERSHIP);
|
||||
const titleHandle = await divHandle.$(selectors.THREAD_TITLE);
|
||||
const forumHandle = await divHandle.$(selectors.SEARCH_THREADS_MEMBERSHIP);
|
||||
|
||||
// Get the forum where the thread was posted
|
||||
let forum = await getMembershipForum(page, forumHandle);
|
||||
const forum = await getMembershipForum(page, forumHandle);
|
||||
if (forum !== "GAMES" && forum != "MODS") return null;
|
||||
|
||||
// Get the URL of the thread from the title
|
||||
|
@ -98,8 +98,8 @@ async function getMembershipForum(page, handle) {
|
|||
|
||||
// Parse link
|
||||
link = link.replace("/forums/", "");
|
||||
let endIndex = link.indexOf(".");
|
||||
let forum = link.substring(0, endIndex);
|
||||
const endIndex = link.indexOf(".");
|
||||
const forum = link.substring(0, endIndex);
|
||||
|
||||
return forum.toUpperCase();
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ async function getMembershipForum(page, handle) {
|
|||
* @returns {Promise<String>} URL of the thread
|
||||
*/
|
||||
async function getThreadURL(page, handle) {
|
||||
let relativeURLThread = await page.evaluate(
|
||||
const relativeURLThread = await page.evaluate(
|
||||
/* istanbul ignore next */
|
||||
(e) => e.querySelector("a").href,
|
||||
handle
|
||||
|
@ -121,7 +121,10 @@ async function getThreadURL(page, handle) {
|
|||
// Some game already have a full URL
|
||||
if (isF95URL(relativeURLThread)) return relativeURLThread;
|
||||
|
||||
let urlThread = new URL(relativeURLThread, constURLs.F95_BASE_URL).toString();
|
||||
const urlThread = new URL(
|
||||
relativeURLThread,
|
||||
constURLs.F95_BASE_URL
|
||||
).toString();
|
||||
return urlThread;
|
||||
}
|
||||
//#endregion Private methods
|
||||
|
|
|
@ -38,7 +38,7 @@ module.exports.prepareBrowser = async function () {
|
|||
*/
|
||||
module.exports.preparePage = async function (browser) {
|
||||
// Create new page in the browser argument
|
||||
let page = await browser.newPage();
|
||||
const page = await browser.newPage();
|
||||
|
||||
// Block image download
|
||||
await page.setRequestInterception(true);
|
||||
|
@ -51,7 +51,7 @@ module.exports.preparePage = async function (browser) {
|
|||
});
|
||||
|
||||
// Set custom user-agent
|
||||
let userAgent =
|
||||
const userAgent =
|
||||
"Mozilla/5.0 (X11; Linux x86_64)" +
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.39 Safari/537.36";
|
||||
await page.setUserAgent(userAgent);
|
||||
|
|
|
@ -18,7 +18,7 @@ const FAKE_PASSWORD = "fake_password";
|
|||
F95API.debug(false);
|
||||
|
||||
function randomSleep() {
|
||||
let random = Math.floor(Math.random() * 500) + 50;
|
||||
const random = Math.floor(Math.random() * 500) + 50;
|
||||
sleep.msleep(500 + random);
|
||||
}
|
||||
|
||||
|
@ -112,13 +112,13 @@ describe("Load base data without cookies", function () {
|
|||
//#endregion Set-up
|
||||
|
||||
it("With login", async function () {
|
||||
let loginResult = await F95API.login(USERNAME, PASSWORD);
|
||||
const loginResult = await F95API.login(USERNAME, PASSWORD);
|
||||
expect(loginResult.success).to.be.true;
|
||||
|
||||
let result = await F95API.loadF95BaseData();
|
||||
const result = await F95API.loadF95BaseData();
|
||||
|
||||
let enginesCacheExists = fs.existsSync(ENGINES_SAVE_PATH);
|
||||
let statusesCacheExists = fs.existsSync(STATUSES_SAVE_PATH);
|
||||
const enginesCacheExists = fs.existsSync(ENGINES_SAVE_PATH);
|
||||
const statusesCacheExists = fs.existsSync(STATUSES_SAVE_PATH);
|
||||
|
||||
expect(result).to.be.true;
|
||||
expect(enginesCacheExists).to.be.true;
|
||||
|
@ -127,7 +127,7 @@ describe("Load base data without cookies", function () {
|
|||
|
||||
it("Without login", async function () {
|
||||
if (F95API.isLogged()) F95API.logout();
|
||||
let result = await F95API.loadF95BaseData();
|
||||
const result = await F95API.loadF95BaseData();
|
||||
expect(result).to.be.false;
|
||||
});
|
||||
});
|
||||
|
@ -154,7 +154,7 @@ describe("Search game data", function () {
|
|||
const gamesList = await F95API.getGameData("Kingdom of Deception", false);
|
||||
expect(gamesList.length, "Should find only the game").to.equal(1);
|
||||
const result = gamesList[0];
|
||||
let src = "https://attachments.f95zone.to/2018/09/162821_f9nXfwF.png";
|
||||
const src = "https://attachments.f95zone.to/2018/09/162821_f9nXfwF.png";
|
||||
|
||||
// Test only the main information
|
||||
expect(result.name).to.equal("Kingdom of Deception");
|
||||
|
@ -179,7 +179,7 @@ describe("Load user data", function () {
|
|||
await F95API.login(USERNAME, PASSWORD);
|
||||
|
||||
// Then retrieve user data
|
||||
let data = await F95API.getUserData();
|
||||
const data = await F95API.getUserData();
|
||||
|
||||
expect(data).to.exist;
|
||||
expect(data.username).to.equal(USERNAME);
|
||||
|
@ -189,7 +189,7 @@ describe("Load user data", function () {
|
|||
if (F95API.isLogged()) F95API.logout();
|
||||
|
||||
// Try to retrieve user data
|
||||
let data = await F95API.getUserData();
|
||||
const data = await F95API.getUserData();
|
||||
|
||||
expect(data).to.be.null;
|
||||
});
|
||||
|
@ -211,7 +211,7 @@ describe("Check game update", function () {
|
|||
// https://f95zone.to/threads/kingdom-of-deception-v0-10-8-hreinn-games.2733/
|
||||
const result = (await F95API.getGameData("Kingdom of Deception", false))[0];
|
||||
|
||||
let update = await F95API.chekIfGameHasUpdate(result);
|
||||
const update = await F95API.chekIfGameHasUpdate(result);
|
||||
expect(update).to.be.false;
|
||||
});
|
||||
|
||||
|
@ -221,12 +221,12 @@ describe("Check game update", function () {
|
|||
|
||||
// This test depend on the data on F95Zone at
|
||||
// https://f95zone.to/threads/perverted-education-v0-9701-april-ryan.1854/
|
||||
let url =
|
||||
const url =
|
||||
"https://f95zone.to/threads/perverted-education-v0-9701-april-ryan.1854/";
|
||||
const result = await F95API.getGameDataFromURL(url);
|
||||
result.version = "0.9600";
|
||||
|
||||
let update = await F95API.chekIfGameHasUpdate(result);
|
||||
const update = await F95API.chekIfGameHasUpdate(result);
|
||||
expect(update).to.be.true;
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,11 +14,11 @@ main();
|
|||
//downloadGameMEGA();
|
||||
|
||||
async function main() {
|
||||
let loginResult = await login("MillenniumEarl", "f9vTcRNuvxj4YpK");
|
||||
const loginResult = await login("MillenniumEarl", "f9vTcRNuvxj4YpK");
|
||||
|
||||
if (loginResult.success) {
|
||||
await loadF95BaseData();
|
||||
let gameData = await getGameData("queen's brothel", false);
|
||||
const gameData = await getGameData("queen's brothel", false);
|
||||
console.log(gameData);
|
||||
|
||||
// let userData = await getUserData();
|
||||
|
@ -28,11 +28,11 @@ async function main() {
|
|||
}
|
||||
|
||||
async function downloadGameMEGA() {
|
||||
let gd = new GameDownload();
|
||||
const gd = new GameDownload();
|
||||
gd.hosting = "NOPY";
|
||||
gd.link =
|
||||
"https://f95zone.to/masked/mega.nz/2733/1470797/4O5LKwMx4ZSlw0QYTVMP0uDK660/hoobTb44f0IKx7Yio2SE2w/loX_px2vLRyNRQCnkNn5U7nnQe7jGmpEVERvH1tk7RjAFkQbs2kH_vCK6zVmRDuqiypPoIx358MNHHCd3QCdVvEsClSiAq4rwjK0r_ruXIs";
|
||||
let savepath = join(__dirname, "Kingdom_of_Deception-pc0.10.8.zip");
|
||||
let result = await gd.download(savepath);
|
||||
const savepath = join(__dirname, "Kingdom_of_Deception-pc0.10.8.zip");
|
||||
const result = await gd.download(savepath);
|
||||
console.log(result);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue