Merge pull request #25 from MillenniumEarl/deepsource-fix-9cdc5080

Replace variables with const
pull/27/head
Millennium Earl 2020-10-16 09:29:18 +02:00 committed by GitHub
commit 5026094e07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 146 additions and 143 deletions

View File

@ -100,7 +100,7 @@ var _browser = null;
module.exports.login = async function (username, password) { module.exports.login = async function (username, password) {
if (shared.isLogged) { if (shared.isLogged) {
if (shared.debug) console.log("Already logged in"); if (shared.debug) console.log("Already logged in");
let result = new LoginResult(); const result = new LoginResult();
result.success = true; result.success = true;
result.message = "Already logged in"; result.message = "Already logged in";
return result; return result;
@ -111,7 +111,7 @@ module.exports.login = async function (username, password) {
if (shared.cookies !== null) { if (shared.cookies !== null) {
if (shared.debug) console.log("Valid session, no need to re-authenticate"); if (shared.debug) console.log("Valid session, no need to re-authenticate");
shared.isLogged = true; shared.isLogged = true;
let result = new LoginResult(); const result = new LoginResult();
result.success = true; result.success = true;
result.message = "Logged with cookies"; result.message = "Logged with cookies";
return result; 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"); console.log("No saved sessions or expired session, login on the platform");
if (_browser === null && !shared.isolation) _browser = await prepareBrowser(); 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; shared.isLogged = result.success;
if (result.success) { if (result.success) {
@ -154,9 +154,9 @@ module.exports.loadF95BaseData = async function () {
// Prepare a new web page // Prepare a new web page
if (_browser === null && !shared.isolation) _browser = await prepareBrowser(); 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 await page.setCookie(...shared.cookies); // Set cookies to avoid login
// Go to latest update page and wait for it to load // 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, // F95 change URL at every game update,
// so if the URL is different an update is available // 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; if (!exists) return true;
// Parse version from title // Parse version from title
if (_browser === null && !shared.isolation) _browser = await prepareBrowser(); 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(); 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 // Gets the search results of the game being searched for
if (_browser === null && !shared.isolation) _browser = await prepareBrowser(); if (_browser === null && !shared.isolation) _browser = await prepareBrowser();
let browser = shared.isolation ? await prepareBrowser() : _browser; const browser = shared.isolation ? await prepareBrowser() : _browser;
let urlList = await searcher.getSearchGameResults(browser, name); const urlList = await searcher.getSearchGameResults(browser, name);
// Process previous partial results // Process previous partial results
let promiseList = []; const promiseList = [];
for (let url of urlList) { for (const url of urlList) {
// Start looking for information // Start looking for information
promiseList.push(scraper.getGameInfo(browser, url)); promiseList.push(scraper.getGameInfo(browser, url));
} }
// Filter for mods // Filter for mods
let result = []; const result = [];
for (let info of await Promise.all(promiseList)) { for (const info of await Promise.all(promiseList)) {
// Skip mods if not required // Skip mods if not required
if (!info) continue; if (!info) continue;
if (info.isMod && !includeMods) 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 // Gets the search results of the game being searched for
if (_browser === null && !shared.isolation) _browser = await prepareBrowser(); 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 // Get game data
let result = await scraper.getGameInfo(browser, url); const result = await scraper.getGameInfo(browser, url);
if (shared.isolation) await browser.close(); if (shared.isolation) await browser.close();
return result; return result;
@ -294,8 +294,8 @@ module.exports.getUserData = async function () {
// Prepare a new web page // Prepare a new web page
if (_browser === null && !shared.isolation) _browser = await prepareBrowser(); 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 await page.setCookie(...shared.cookies); // Set cookies to avoid login
await page.goto(constURLs.F95_BASE_URL); // Go to base page 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.USERNAME_ELEMENT);
await page.waitForSelector(selectors.AVATAR_PIC); 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) => /* istanbul ignore next */ (selector) =>
document.querySelector(selector).innerText, document.querySelector(selector).innerText,
selectors.USERNAME_ELEMENT selectors.USERNAME_ELEMENT
); );
let avatarSrc = await page.evaluate( const avatarSrc = await page.evaluate(
/* istanbul ignore next */ (selector) => /* istanbul ignore next */ (selector) =>
document.querySelector(selector).getAttribute("src"), document.querySelector(selector).getAttribute("src"),
selectors.AVATAR_PIC selectors.AVATAR_PIC
); );
let ud = new UserData(); const ud = new UserData();
ud.username = username; ud.username = username;
ud.avatarSrc = isStringAValidURL(avatarSrc) ? avatarSrc : null; ud.avatarSrc = isStringAValidURL(avatarSrc) ? avatarSrc : null;
ud.watchedThreads = await threads; ud.watchedThreads = await threads;
@ -360,11 +360,11 @@ function loadCookies() {
// Check the existence of the cookie file // Check the existence of the cookie file
if (fs.existsSync(shared.cookiesCachePath)) { if (fs.existsSync(shared.cookiesCachePath)) {
// Read cookies // Read cookies
let cookiesJSON = fs.readFileSync(shared.cookiesCachePath); const cookiesJSON = fs.readFileSync(shared.cookiesCachePath);
let cookies = JSON.parse(cookiesJSON); const cookies = JSON.parse(cookiesJSON);
// Check if the cookies have expired // Check if the cookies have expired
for (let cookie of cookies) { for (const cookie of cookies) {
if (isCookieExpired(cookie)) return null; if (isCookieExpired(cookie)) return null;
} }
@ -383,11 +383,11 @@ function isCookieExpired(cookie) {
let expiredCookies = false; let expiredCookies = false;
// Ignore cookies that never expire // Ignore cookies that never expire
let expirationUnixTimestamp = cookie["expire"]; const expirationUnixTimestamp = cookie["expire"];
if (expirationUnixTimestamp !== "-1") { if (expirationUnixTimestamp !== "-1") {
// Convert UNIX epoch timestamp to normal Date // Convert UNIX epoch timestamp to normal Date
let expirationDate = new Date(expirationUnixTimestamp * 1000); const expirationDate = new Date(expirationUnixTimestamp * 1000);
if (expirationDate < Date.now()) { if (expirationDate < Date.now()) {
if (shared.debug) 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 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 (shared.debug) console.log("Load " + elementRequested + " from disk...");
if (fs.existsSync(path)) { if (fs.existsSync(path)) {
let valueJSON = fs.readFileSync(path); const valueJSON = fs.readFileSync(path);
return JSON.parse(valueJSON); return JSON.parse(valueJSON);
} }
// Otherwise, connect and download the data from the portal // Otherwise, connect and download the data from the portal
if (shared.debug) if (shared.debug)
console.log("No " + elementRequested + " cached, downloading..."); console.log("No " + elementRequested + " cached, downloading...");
let values = await getValuesFromLatestPage( const values = await getValuesFromLatestPage(
page, page,
selector, selector,
"Getting " + elementRequested + " from page" "Getting " + elementRequested + " from page"
@ -451,11 +451,11 @@ async function loadValuesFromLatestPage(
async function getValuesFromLatestPage(page, selector, logMessage) { async function getValuesFromLatestPage(page, selector, logMessage) {
if (shared.debug) console.log(logMessage); if (shared.debug) console.log(logMessage);
let result = []; const result = [];
let elements = await page.$$(selector); const elements = await page.$$(selector);
for (let element of elements) { for (const element of elements) {
let text = await element.evaluate( const text = await element.evaluate(
/* istanbul ignore next */ (e) => e.innerText /* istanbul ignore next */ (e) => e.innerText
); );
@ -476,7 +476,7 @@ async function getValuesFromLatestPage(page, selector, logMessage) {
* @returns {Promise<LoginResult>} Result of the operation * @returns {Promise<LoginResult>} Result of the operation
*/ */
async function loginF95(browser, username, password) { 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 await page.goto(constURLs.F95_LOGIN_URL); // Go to login page
// Explicitly wait for the required items to load // Explicitly wait for the required items to load
@ -494,7 +494,7 @@ async function loginF95(browser, username, password) {
]); ]);
// Prepare result // Prepare result
let result = new LoginResult(); const result = new LoginResult();
// Check if the user is logged in // Check if the user is logged in
result.success = await page.evaluate( result.success = await page.evaluate(
@ -505,7 +505,7 @@ async function loginF95(browser, username, password) {
// Save cookies to avoid re-auth // Save cookies to avoid re-auth
if (result.success) { if (result.success) {
let c = await page.cookies(); const c = await page.cookies();
fs.writeFileSync(shared.cookiesCachePath, JSON.stringify(c)); fs.writeFileSync(shared.cookiesCachePath, JSON.stringify(c));
result.message = "Authentication successful"; result.message = "Authentication successful";
} }
@ -517,7 +517,7 @@ async function loginF95(browser, username, password) {
selectors.LOGIN_MESSAGE_ERROR selectors.LOGIN_MESSAGE_ERROR
) )
) { ) {
let errorMessage = await page.evaluate( const errorMessage = await page.evaluate(
/* istanbul ignore next */ (selector) => /* istanbul ignore next */ (selector) =>
document.querySelector(selector).innerText, document.querySelector(selector).innerText,
selectors.LOGIN_MESSAGE_ERROR selectors.LOGIN_MESSAGE_ERROR
@ -543,7 +543,7 @@ async function loginF95(browser, username, password) {
* @returns {Promise<String[]>} URL list * @returns {Promise<String[]>} URL list
*/ */
async function getUserWatchedGameThreads(browser) { 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 await page.goto(constURLs.F95_WATCHED_THREADS); // Go to the thread page
// Explicitly wait for the required items to load // Explicitly wait for the required items to load
@ -569,17 +569,17 @@ async function getUserWatchedGameThreads(browser) {
await page.waitForSelector(selectors.WATCHED_THREAD_URLS); await page.waitForSelector(selectors.WATCHED_THREAD_URLS);
// Get the threads urls // Get the threads urls
let urls = []; const urls = [];
let nextPageExists = false; let nextPageExists = false;
do { do {
// Get all the URLs // Get all the URLs
for (let handle of await page.$$(selectors.WATCHED_THREAD_URLS)) { for (const handle of await page.$$(selectors.WATCHED_THREAD_URLS)) {
let src = await page.evaluate( const src = await page.evaluate(
/* istanbul ignore next */ (element) => element.href, /* istanbul ignore next */ (element) => element.href,
handle handle
); );
// If 'unread' is left, it will redirect to the last unread post // 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); urls.push(url);
} }

View File

@ -53,36 +53,36 @@ module.exports = GameDownload;
async function downloadMEGA(url, savepath) { async function downloadMEGA(url, savepath) {
// The URL is masked // The URL is masked
let browser = await prepareBrowser(); const browser = await prepareBrowser();
let page = await preparePage(browser); const page = await preparePage(browser);
await page.setCookie(...shared.cookies); // Set cookies to avoid login await page.setCookie(...shared.cookies); // Set cookies to avoid login
await page.goto(url); await page.goto(url);
await page.waitForSelector("a.host_link"); await page.waitForSelector("a.host_link");
// Obtain the link for the unmasked page and click it // 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 link.click();
await page.goto(url, { await page.goto(url, {
waitUntil: shared.WAIT_STATEMENT, waitUntil: shared.WAIT_STATEMENT,
}); // Go to the game page and wait until it loads }); // Go to the game page and wait until it loads
// Obtain the URL after the redirect // Obtain the URL after the redirect
let downloadURL = page.url(); const downloadURL = page.url();
// Close browser and page // Close browser and page
await page.close(); await page.close();
await browser.close(); await browser.close();
let stream = fs.createWriteStream(savepath); const stream = fs.createWriteStream(savepath);
let file = File.fromURL(downloadURL); const file = File.fromURL(downloadURL);
file.download().pipe(stream); file.download().pipe(stream);
return fs.existsSync(savepath); return fs.existsSync(savepath);
} }
async function downloadNOPY(url, savepath) { async function downloadNOPY(url, savepath) {
// Prepare browser // Prepare browser
let browser = await prepareBrowser(); const browser = await prepareBrowser();
let page = await preparePage(browser); const page = await preparePage(browser);
await page.goto(url); await page.goto(url);
await page.waitForSelector("#download"); await page.waitForSelector("#download");
@ -93,7 +93,7 @@ async function downloadNOPY(url, savepath) {
}); });
// Obtain the download button and click it // Obtain the download button and click it
let downloadButton = await page.$("#download"); const downloadButton = await page.$("#download");
await downloadButton.click(); await downloadButton.click();
// Await for all the connections to close // Await for all the connections to close

View File

@ -25,10 +25,10 @@ module.exports.getGameInfo = async function (browser, url) {
// Verify the correctness of the URL // Verify the correctness of the URL
if (!isF95URL(url)) throw url + " is not a valid F95Zone 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; 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.setCookie(...shared.cookies); // Set cookies to avoid login
await page.goto(url, { await page.goto(url, {
waitUntil: shared.WAIT_STATEMENT, waitUntil: shared.WAIT_STATEMENT,
@ -37,16 +37,16 @@ module.exports.getGameInfo = async function (browser, url) {
// It asynchronously searches for the elements and // It asynchronously searches for the elements and
// then waits at the end to compile the object to be returned // then waits at the end to compile the object to be returned
let info = new GameInfo(); let info = new GameInfo();
let title = getGameTitle(page); const title = getGameTitle(page);
let author = getGameAuthor(page); const author = getGameAuthor(page);
let tags = getGameTags(page); const tags = getGameTags(page);
let previewSource = getGamePreviewSource(page); const previewSource = getGamePreviewSource(page);
//let downloadData = getGameDownloadLink(page); //let downloadData = getGameDownloadLink(page);
info = await parsePrefixes(page, info); // Fill status/engines/isMod info = await parsePrefixes(page, info); // Fill status/engines/isMod
let structuredText = await getMainPostStructuredText(page); const structuredText = await getMainPostStructuredText(page);
let overview = getOverview(structuredText, info.isMod); const overview = getOverview(structuredText, info.isMod);
let parsedInfos = parseConversationPage(structuredText); const parsedInfos = parseConversationPage(structuredText);
let changelog = getLastChangelog(page); const changelog = getLastChangelog(page);
// Fill in the GameInfo element with the information obtained // Fill in the GameInfo element with the information obtained
info.name = await title; info.name = await title;
@ -61,7 +61,7 @@ module.exports.getGameInfo = async function (browser, url) {
? parsedInfos["UPDATED"] ? parsedInfos["UPDATED"]
: parsedInfos["THREAD UPDATED"]; : parsedInfos["THREAD UPDATED"];
info.previewSource = await previewSource; info.previewSource = await previewSource;
let temp = await changelog; const temp = await changelog;
info.changelog = temp ? temp : "Unknown changelog"; info.changelog = temp ? temp : "Unknown changelog";
//info.downloadInfo = await downloadData; //info.downloadInfo = await downloadData;
/* Downloading games without going directly to /* Downloading games without going directly to
@ -81,23 +81,23 @@ module.exports.getGameInfo = async function (browser, url) {
* @returns {Promise<String>} Online version of the game * @returns {Promise<String>} Online version of the game
*/ */
module.exports.getGameVersionFromTitle = async function (browser, info) { 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.setCookie(...shared.cookies); // Set cookies to avoid login
await page.goto(info.f95url, { await page.goto(info.f95url, {
waitUntil: shared.WAIT_STATEMENT, waitUntil: shared.WAIT_STATEMENT,
}); // Go to the game page and wait until it loads }); // Go to the game page and wait until it loads
// Get the title // Get the title
let titleHTML = await page.evaluate( const titleHTML = await page.evaluate(
/* istanbul ignore next */ /* istanbul ignore next */
(selector) => document.querySelector(selector).innerHTML, (selector) => document.querySelector(selector).innerHTML,
selectors.GAME_TITLE 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] // The title is in the following format: [PREFIXES] NAME GAME [VERSION] [AUTHOR]
let startIndex = title.indexOf("[") + 1; const startIndex = title.indexOf("[") + 1;
let endIndex = title.indexOf("]", startIndex); const endIndex = title.indexOf("]", startIndex);
let version = title.substring(startIndex, endIndex).trim().toUpperCase(); let version = title.substring(startIndex, endIndex).trim().toUpperCase();
if (version.startsWith("V")) version = version.replace("V", ""); // Replace only the first occurrence if (version.startsWith("V")) version = version.replace("V", ""); // Replace only the first occurrence
return version; return version;
@ -129,10 +129,10 @@ function getOverview(text, isMod) {
*/ */
async function getMainPostStructuredText(page) { async function getMainPostStructuredText(page) {
// Gets the first post, where are listed all the game's informations // 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 // 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, /* istanbul ignore next */ (mainPost) => mainPost.innerHTML,
post post
); );
@ -147,18 +147,18 @@ async function getMainPostStructuredText(page) {
*/ */
async function getGameAuthor(page) { async function getGameAuthor(page) {
// Get the game/mod name (without square brackets) // Get the game/mod name (without square brackets)
let titleHTML = await page.evaluate( const titleHTML = await page.evaluate(
/* istanbul ignore next */ (selector) => /* istanbul ignore next */ (selector) =>
document.querySelector(selector).innerHTML, document.querySelector(selector).innerHTML,
selectors.GAME_TITLE 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...) // 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 // 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(); return gameTitle.substring(startTitleIndex, gameTitle.length - 1).trim();
} }
@ -170,17 +170,17 @@ async function getGameAuthor(page) {
* @returns {Object} Dictionary of information * @returns {Object} Dictionary of information
*/ */
function parseConversationPage(text) { function parseConversationPage(text) {
let dataPairs = {}; const dataPairs = {};
// The information searched in the game post are one per line // The information searched in the game post are one per line
let splittedText = text.split("\n"); const splittedText = text.split("\n");
for (let line of splittedText) { for (const line of splittedText) {
if (!line.includes(":")) continue; if (!line.includes(":")) continue;
// Create pair key/value // Create pair key/value
let splitted = line.split(":"); const splitted = line.split(":");
let key = splitted[0].trim().toUpperCase(); // Uppercase to avoid mismatch const key = splitted[0].trim().toUpperCase(); // Uppercase to avoid mismatch
let value = splitted[1].trim(); const value = splitted[1].trim();
// Add pair to the dict if valid // Add pair to the dict if valid
if (value != "") dataPairs[key] = value; if (value != "") dataPairs[key] = value;
@ -196,10 +196,10 @@ function parseConversationPage(text) {
* @returns {Promise<String>} URL (String) of the image or null if failed to get it * @returns {Promise<String>} URL (String) of the image or null if failed to get it
*/ */
async function getGamePreviewSource(page) { async function getGamePreviewSource(page) {
let src = await page.evaluate( const src = await page.evaluate(
/* istanbul ignore next */ (selector) => { /* istanbul ignore next */ (selector) => {
// Get the firs image available // Get the firs image available
let img = document.querySelector(selector); const img = document.querySelector(selector);
if (img) return img.getAttribute("src"); if (img) return img.getAttribute("src");
else return null; else return null;
@ -219,16 +219,16 @@ async function getGamePreviewSource(page) {
*/ */
async function getGameTitle(page) { async function getGameTitle(page) {
// Get the game/mod name (without square brackets) // Get the game/mod name (without square brackets)
let titleHTML = await page.evaluate( const titleHTML = await page.evaluate(
/* istanbul ignore next */ (selector) => /* istanbul ignore next */ (selector) =>
document.querySelector(selector).innerHTML, document.querySelector(selector).innerHTML,
selectors.GAME_TITLE 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...) // The last element **shoud be** the title without prefixes (engines, status, other...)
let gameTitle = structuredTitle.childNodes.pop().rawText; const gameTitle = structuredTitle.childNodes.pop().rawText;
let endTitleIndex = gameTitle.indexOf("["); const endTitleIndex = gameTitle.indexOf("[");
return gameTitle.substring(0, endTitleIndex).trim(); return gameTitle.substring(0, endTitleIndex).trim();
} }
@ -239,11 +239,11 @@ async function getGameTitle(page) {
* @returns {Promise<String[]>} List of uppercase tags * @returns {Promise<String[]>} List of uppercase tags
*/ */
async function getGameTags(page) { async function getGameTags(page) {
let tags = []; const tags = [];
// Get the game tags // Get the game tags
for (let handle of await page.$$(selectors.GAME_TAGS)) { for (const handle of await page.$$(selectors.GAME_TAGS)) {
let tag = await page.evaluate( const tag = await page.evaluate(
/* istanbul ignore next */ (element) => element.innerText, /* istanbul ignore next */ (element) => element.innerText,
handle handle
); );
@ -265,14 +265,14 @@ async function parsePrefixes(page, info) {
// The 'Ongoing' status is not specified, only 'Abandoned'/'OnHold'/'Complete' // The 'Ongoing' status is not specified, only 'Abandoned'/'OnHold'/'Complete'
info.status = "Ongoing"; info.status = "Ongoing";
for (let handle of await page.$$(selectors.GAME_TITLE_PREFIXES)) { for (const handle of await page.$$(selectors.GAME_TITLE_PREFIXES)) {
let value = await page.evaluate( const value = await page.evaluate(
/* istanbul ignore next */ (element) => element.innerText, /* istanbul ignore next */ (element) => element.innerText,
handle handle
); );
// Clean the prefix // Clean the prefix
let prefix = value.toUpperCase().replace("[", "").replace("]", "").trim(); const prefix = value.toUpperCase().replace("[", "").replace("]", "").trim();
// Getting infos... // Getting infos...
if (shared.statuses.includes(prefix)) info.status = prefix; if (shared.statuses.includes(prefix)) info.status = prefix;
@ -291,17 +291,17 @@ async function parsePrefixes(page, info) {
*/ */
async function getLastChangelog(page) { async function getLastChangelog(page) {
// Gets the first post, where are listed all the game's informations // 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; if (!spoiler) return null;
let changelogHTML = await page.evaluate( const changelogHTML = await page.evaluate(
/* istanbul ignore next */ /* istanbul ignore next */
(e) => e.innerText, (e) => e.innerText,
spoiler spoiler
); );
let parsedText = HTMLParser.parse(changelogHTML).structuredText; const parsedText = HTMLParser.parse(changelogHTML).structuredText;
return parsedText.replace("Spoiler", "").trim(); return parsedText.replace("Spoiler", "").trim();
} }
@ -313,7 +313,7 @@ async function getLastChangelog(page) {
*/ */
async function getGameDownloadLink(page) { async function getGameDownloadLink(page) {
// Most used hosting platforms // Most used hosting platforms
let hostingPlatforms = [ const hostingPlatforms = [
"MEGA", "MEGA",
"NOPY", "NOPY",
"FILESUPLOAD", "FILESUPLOAD",
@ -324,19 +324,19 @@ async function getGameDownloadLink(page) {
]; ];
// Supported OS platforms // Supported OS platforms
let platformOS = ["WIN", "LINUX", "MAC", "ALL"]; const platformOS = ["WIN", "LINUX", "MAC", "ALL"];
// Gets the <span> which contains the download links // 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 []; if (temp.length === 0) return [];
// Look for the container that contains the links // Look for the container that contains the links
// It is necessary because the same css selector // It is necessary because the same css selector
// also identifies other elements on the page // also identifies other elements on the page
let container = null; let container = null;
for (let candidate of temp) { for (const candidate of temp) {
if (container !== null) break; if (container !== null) break;
let upperText = ( const upperText = (
await page.evaluate( await page.evaluate(
/* istanbul ignore next */ (e) => e.innerText, /* istanbul ignore next */ (e) => e.innerText,
candidate candidate
@ -344,7 +344,7 @@ async function getGameDownloadLink(page) {
).toUpperCase(); ).toUpperCase();
// Search if the container contains the name of a hosting platform // 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)) { if (upperText.includes(p)) {
container = candidate; container = candidate;
break; break;
@ -354,7 +354,7 @@ async function getGameDownloadLink(page) {
if (container === null) return []; if (container === null) return [];
// Extract the HTML text from the container // Extract the HTML text from the container
let searchText = ( const searchText = (
await page.evaluate( await page.evaluate(
/* istanbul ignore next */ (e) => e.innerHTML, /* istanbul ignore next */ (e) => e.innerHTML,
container container
@ -362,9 +362,9 @@ async function getGameDownloadLink(page) {
).toLowerCase(); ).toLowerCase();
// Parse the download links // Parse the download links
let downloadData = []; const downloadData = [];
for (let platform of platformOS) { for (const platform of platformOS) {
let data = extractGameHostingData(platform, searchText); const data = extractGameHostingData(platform, searchText);
downloadData.push(...data); downloadData.push(...data);
} }
return downloadData; return downloadData;
@ -404,24 +404,24 @@ function extractGameHostingData(platform, text) {
text = text.substring(startIndex, endIndex); text = text.substring(startIndex, endIndex);
let downloadData = []; const downloadData = [];
let linkTags = text.split(LINK_OPEN); const linkTags = text.split(LINK_OPEN);
for (let tag of linkTags) { for (const tag of linkTags) {
// Ignore non-link string // Ignore non-link string
if (!tag.includes(HREF_START)) continue; if (!tag.includes(HREF_START)) continue;
// Find the hosting platform name // Find the hosting platform name
startIndex = tag.indexOf(TAG_CLOSE) + TAG_CLOSE.length; startIndex = tag.indexOf(TAG_CLOSE) + TAG_CLOSE.length;
endIndex = tag.indexOf(LINK_CLOSE, startIndex); endIndex = tag.indexOf(LINK_CLOSE, startIndex);
let hosting = tag.substring(startIndex, endIndex); const hosting = tag.substring(startIndex, endIndex);
// Find the 'href' attribute // Find the 'href' attribute
startIndex = tag.indexOf(HREF_START) + HREF_START.length; startIndex = tag.indexOf(HREF_START) + HREF_START.length;
endIndex = tag.indexOf(HREF_END, startIndex); endIndex = tag.indexOf(HREF_END, startIndex);
let link = tag.substring(startIndex, endIndex); const link = tag.substring(startIndex, endIndex);
if (isStringAValidURL(link)) { if (isStringAValidURL(link)) {
let gd = new GameDownload(); const gd = new GameDownload();
gd.hosting = hosting.toUpperCase(); gd.hosting = hosting.toUpperCase();
gd.link = link; gd.link = link;
gd.supportedOS = platform.toUpperCase(); gd.supportedOS = platform.toUpperCase();

View File

@ -20,7 +20,7 @@ const { isF95URL } = require("./urls-helper.js");
module.exports.getSearchGameResults = async function (browser, gamename) { module.exports.getSearchGameResults = async function (browser, gamename) {
if (shared.debug) console.log("Searching " + gamename + " on F95Zone"); 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.setCookie(...shared.cookies); // Set cookies to avoid login
await page.goto(constURLs.F95_SEARCH_URL, { await page.goto(constURLs.F95_SEARCH_URL, {
waitUntil: shared.WAIT_STATEMENT, waitUntil: shared.WAIT_STATEMENT,
@ -41,13 +41,13 @@ module.exports.getSearchGameResults = async function (browser, gamename) {
]); ]);
// Select all conversation titles // 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 // For each element found extract the info about the conversation
if (shared.debug) console.log("Extracting info from conversations"); if (shared.debug) console.log("Extracting info from conversations");
let results = []; const results = [];
for (let element of resultsThread) { for (const element of resultsThread) {
let gameUrl = await getOnlyGameThreads(page, element); const gameUrl = await getOnlyGameThreads(page, element);
if (gameUrl !== null) results.push(gameUrl); if (gameUrl !== null) results.push(gameUrl);
} }
if (shared.debug) console.log("Find " + results.length + " conversations"); 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) { async function getOnlyGameThreads(page, divHandle) {
// Obtain the elements containing the basic information // Obtain the elements containing the basic information
let titleHandle = await divHandle.$(selectors.THREAD_TITLE); const titleHandle = await divHandle.$(selectors.THREAD_TITLE);
let forumHandle = await divHandle.$(selectors.SEARCH_THREADS_MEMBERSHIP); const forumHandle = await divHandle.$(selectors.SEARCH_THREADS_MEMBERSHIP);
// Get the forum where the thread was posted // 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; if (forum !== "GAMES" && forum != "MODS") return null;
// Get the URL of the thread from the title // Get the URL of the thread from the title
@ -98,8 +98,8 @@ async function getMembershipForum(page, handle) {
// Parse link // Parse link
link = link.replace("/forums/", ""); link = link.replace("/forums/", "");
let endIndex = link.indexOf("."); const endIndex = link.indexOf(".");
let forum = link.substring(0, endIndex); const forum = link.substring(0, endIndex);
return forum.toUpperCase(); return forum.toUpperCase();
} }
@ -112,7 +112,7 @@ async function getMembershipForum(page, handle) {
* @returns {Promise<String>} URL of the thread * @returns {Promise<String>} URL of the thread
*/ */
async function getThreadURL(page, handle) { async function getThreadURL(page, handle) {
let relativeURLThread = await page.evaluate( const relativeURLThread = await page.evaluate(
/* istanbul ignore next */ /* istanbul ignore next */
(e) => e.querySelector("a").href, (e) => e.querySelector("a").href,
handle handle
@ -121,7 +121,10 @@ async function getThreadURL(page, handle) {
// Some game already have a full URL // Some game already have a full URL
if (isF95URL(relativeURLThread)) return relativeURLThread; 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; return urlThread;
} }
//#endregion Private methods //#endregion Private methods

View File

@ -38,7 +38,7 @@ module.exports.prepareBrowser = async function () {
*/ */
module.exports.preparePage = async function (browser) { module.exports.preparePage = async function (browser) {
// Create new page in the browser argument // Create new page in the browser argument
let page = await browser.newPage(); const page = await browser.newPage();
// Block image download // Block image download
await page.setRequestInterception(true); await page.setRequestInterception(true);
@ -51,7 +51,7 @@ module.exports.preparePage = async function (browser) {
}); });
// Set custom user-agent // Set custom user-agent
let userAgent = const userAgent =
"Mozilla/5.0 (X11; Linux x86_64)" + "Mozilla/5.0 (X11; Linux x86_64)" +
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.39 Safari/537.36"; "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.39 Safari/537.36";
await page.setUserAgent(userAgent); await page.setUserAgent(userAgent);

View File

@ -18,7 +18,7 @@ const FAKE_PASSWORD = "fake_password";
F95API.debug(false); F95API.debug(false);
function randomSleep() { function randomSleep() {
let random = Math.floor(Math.random() * 500) + 50; const random = Math.floor(Math.random() * 500) + 50;
sleep.msleep(500 + random); sleep.msleep(500 + random);
} }
@ -112,13 +112,13 @@ describe("Load base data without cookies", function () {
//#endregion Set-up //#endregion Set-up
it("With login", async function () { 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; expect(loginResult.success).to.be.true;
let result = await F95API.loadF95BaseData(); const result = await F95API.loadF95BaseData();
let enginesCacheExists = fs.existsSync(ENGINES_SAVE_PATH); const enginesCacheExists = fs.existsSync(ENGINES_SAVE_PATH);
let statusesCacheExists = fs.existsSync(STATUSES_SAVE_PATH); const statusesCacheExists = fs.existsSync(STATUSES_SAVE_PATH);
expect(result).to.be.true; expect(result).to.be.true;
expect(enginesCacheExists).to.be.true; expect(enginesCacheExists).to.be.true;
@ -127,7 +127,7 @@ describe("Load base data without cookies", function () {
it("Without login", async function () { it("Without login", async function () {
if (F95API.isLogged()) F95API.logout(); if (F95API.isLogged()) F95API.logout();
let result = await F95API.loadF95BaseData(); const result = await F95API.loadF95BaseData();
expect(result).to.be.false; expect(result).to.be.false;
}); });
}); });
@ -154,7 +154,7 @@ describe("Search game data", function () {
const gamesList = await F95API.getGameData("Kingdom of Deception", false); const gamesList = await F95API.getGameData("Kingdom of Deception", false);
expect(gamesList.length, "Should find only the game").to.equal(1); expect(gamesList.length, "Should find only the game").to.equal(1);
const result = gamesList[0]; 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 // Test only the main information
expect(result.name).to.equal("Kingdom of Deception"); expect(result.name).to.equal("Kingdom of Deception");
@ -179,7 +179,7 @@ describe("Load user data", function () {
await F95API.login(USERNAME, PASSWORD); await F95API.login(USERNAME, PASSWORD);
// Then retrieve user data // Then retrieve user data
let data = await F95API.getUserData(); const data = await F95API.getUserData();
expect(data).to.exist; expect(data).to.exist;
expect(data.username).to.equal(USERNAME); expect(data.username).to.equal(USERNAME);
@ -189,7 +189,7 @@ describe("Load user data", function () {
if (F95API.isLogged()) F95API.logout(); if (F95API.isLogged()) F95API.logout();
// Try to retrieve user data // Try to retrieve user data
let data = await F95API.getUserData(); const data = await F95API.getUserData();
expect(data).to.be.null; 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/ // https://f95zone.to/threads/kingdom-of-deception-v0-10-8-hreinn-games.2733/
const result = (await F95API.getGameData("Kingdom of Deception", false))[0]; 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; expect(update).to.be.false;
}); });
@ -221,12 +221,12 @@ describe("Check game update", function () {
// This test depend on the data on F95Zone at // This test depend on the data on F95Zone at
// https://f95zone.to/threads/perverted-education-v0-9701-april-ryan.1854/ // 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/"; "https://f95zone.to/threads/perverted-education-v0-9701-april-ryan.1854/";
const result = await F95API.getGameDataFromURL(url); const result = await F95API.getGameDataFromURL(url);
result.version = "0.9600"; result.version = "0.9600";
let update = await F95API.chekIfGameHasUpdate(result); const update = await F95API.chekIfGameHasUpdate(result);
expect(update).to.be.true; expect(update).to.be.true;
}); });
}); });

View File

@ -14,11 +14,11 @@ main();
//downloadGameMEGA(); //downloadGameMEGA();
async function main() { async function main() {
let loginResult = await login("MillenniumEarl", "f9vTcRNuvxj4YpK"); const loginResult = await login("MillenniumEarl", "f9vTcRNuvxj4YpK");
if (loginResult.success) { if (loginResult.success) {
await loadF95BaseData(); await loadF95BaseData();
let gameData = await getGameData("queen's brothel", false); const gameData = await getGameData("queen's brothel", false);
console.log(gameData); console.log(gameData);
// let userData = await getUserData(); // let userData = await getUserData();
@ -28,11 +28,11 @@ async function main() {
} }
async function downloadGameMEGA() { async function downloadGameMEGA() {
let gd = new GameDownload(); const gd = new GameDownload();
gd.hosting = "NOPY"; gd.hosting = "NOPY";
gd.link = gd.link =
"https://f95zone.to/masked/mega.nz/2733/1470797/4O5LKwMx4ZSlw0QYTVMP0uDK660/hoobTb44f0IKx7Yio2SE2w/loX_px2vLRyNRQCnkNn5U7nnQe7jGmpEVERvH1tk7RjAFkQbs2kH_vCK6zVmRDuqiypPoIx358MNHHCd3QCdVvEsClSiAq4rwjK0r_ruXIs"; "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"); const savepath = join(__dirname, "Kingdom_of_Deception-pc0.10.8.zip");
let result = await gd.download(savepath); const result = await gd.download(savepath);
console.log(result); console.log(result);
} }