Merge branch 'master' of https://github.com/MillenniumEarl/F95API into master
						commit
						09e77f6804
					
				| 
						 | 
				
			
			@ -13,6 +13,7 @@ enabled = true
 | 
			
		|||
    "nodejs",
 | 
			
		||||
    "mocha"
 | 
			
		||||
  ]
 | 
			
		||||
  style_guide = "standard"
 | 
			
		||||
 | 
			
		||||
[[transformers]]
 | 
			
		||||
name = "prettier"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								app/index.js
								
								
								
								
							
							
						
						
									
										15
									
								
								app/index.js
								
								
								
								
							| 
						 | 
				
			
			@ -98,7 +98,6 @@ var _browser = null;
 | 
			
		|||
 * @returns {Promise<LoginResult>} Result of the operation
 | 
			
		||||
 */
 | 
			
		||||
module.exports.login = async function (username, password) {
 | 
			
		||||
  
 | 
			
		||||
  if (shared.isLogged) {
 | 
			
		||||
    if (shared.debug) console.log("Already logged in");
 | 
			
		||||
    let result = new LoginResult();
 | 
			
		||||
| 
						 | 
				
			
			@ -146,7 +145,6 @@ module.exports.login = async function (username, password) {
 | 
			
		|||
 * @returns {Promise<Boolean>} Result of the operation
 | 
			
		||||
 */
 | 
			
		||||
module.exports.loadF95BaseData = async function () {
 | 
			
		||||
  
 | 
			
		||||
  if (!shared.isLogged || !shared.cookies) {
 | 
			
		||||
    console.warn("User not authenticated, unable to continue");
 | 
			
		||||
    return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -196,7 +194,6 @@ module.exports.loadF95BaseData = async function () {
 | 
			
		|||
 * @returns {Promise<Boolean>} true if an update is available, false otherwise
 | 
			
		||||
 */
 | 
			
		||||
module.exports.chekIfGameHasUpdate = async function (info) {
 | 
			
		||||
  
 | 
			
		||||
  if (!shared.isLogged || !shared.cookies) {
 | 
			
		||||
    console.warn("user not authenticated, unable to continue");
 | 
			
		||||
    return info.version;
 | 
			
		||||
| 
						 | 
				
			
			@ -227,7 +224,6 @@ module.exports.chekIfGameHasUpdate = async function (info) {
 | 
			
		|||
 * an identified game (in the case of homonymy). If no games were found, null is returned
 | 
			
		||||
 */
 | 
			
		||||
module.exports.getGameData = async function (name, includeMods) {
 | 
			
		||||
  
 | 
			
		||||
  if (!shared.isLogged || !shared.cookies) {
 | 
			
		||||
    console.warn("user not authenticated, unable to continue");
 | 
			
		||||
    return null;
 | 
			
		||||
| 
						 | 
				
			
			@ -265,7 +261,6 @@ module.exports.getGameData = async function (name, includeMods) {
 | 
			
		|||
 * @returns {Promise<GameInfo>} Information about the game. If no game was found, null is returned
 | 
			
		||||
 */
 | 
			
		||||
module.exports.getGameDataFromURL = async function (url) {
 | 
			
		||||
  
 | 
			
		||||
  if (!shared.isLogged || !shared.cookies) {
 | 
			
		||||
    console.warn("user not authenticated, unable to continue");
 | 
			
		||||
    return null;
 | 
			
		||||
| 
						 | 
				
			
			@ -292,7 +287,6 @@ module.exports.getGameDataFromURL = async function (url) {
 | 
			
		|||
 * @returns {Promise<UserData>} Data of the user currently logged in or null if an error arise
 | 
			
		||||
 */
 | 
			
		||||
module.exports.getUserData = async function () {
 | 
			
		||||
  
 | 
			
		||||
  if (!shared.isLogged || !shared.cookies) {
 | 
			
		||||
    console.warn("user not authenticated, unable to continue");
 | 
			
		||||
    return null;
 | 
			
		||||
| 
						 | 
				
			
			@ -339,7 +333,6 @@ module.exports.getUserData = async function () {
 | 
			
		|||
 * You **must** be logged in to the portal before calling this method.
 | 
			
		||||
 */
 | 
			
		||||
module.exports.logout = async function () {
 | 
			
		||||
  
 | 
			
		||||
  if (!shared.isLogged || !shared.cookies) {
 | 
			
		||||
    console.warn("user not authenticated, unable to continue");
 | 
			
		||||
    return;
 | 
			
		||||
| 
						 | 
				
			
			@ -493,10 +486,12 @@ async function loginF95(browser, username, password) {
 | 
			
		|||
 | 
			
		||||
  await page.type(selectors.USERNAME_INPUT, username); // Insert username
 | 
			
		||||
  await page.type(selectors.PASSWORD_INPUT, password); // Insert password
 | 
			
		||||
  await page.click(selectors.LOGIN_BUTTON); // Click on the login button
 | 
			
		||||
  await page.waitForNavigation({
 | 
			
		||||
  await Promise.all([
 | 
			
		||||
    page.click(selectors.LOGIN_BUTTON), // Click on the login button
 | 
			
		||||
    page.waitForNavigation({
 | 
			
		||||
      waitUntil: shared.WAIT_STATEMENT,
 | 
			
		||||
  }); // Wait for page to load
 | 
			
		||||
    }), // Wait for page to load
 | 
			
		||||
  ]);
 | 
			
		||||
 | 
			
		||||
  // Prepare result
 | 
			
		||||
  let result = new LoginResult();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,6 +65,11 @@ class GameInfo {
 | 
			
		|||
     * @type Boolean
 | 
			
		||||
     */
 | 
			
		||||
    this.isMod = false;
 | 
			
		||||
    /**
 | 
			
		||||
     * Changelog for the last version.
 | 
			
		||||
     * @type String
 | 
			
		||||
     */
 | 
			
		||||
    this.changelog = null;
 | 
			
		||||
    /**
 | 
			
		||||
     * Directory containing the local copy of the game
 | 
			
		||||
     * @type String
 | 
			
		||||
| 
						 | 
				
			
			@ -96,6 +101,7 @@ class GameInfo {
 | 
			
		|||
      lastUpdate: this.lastUpdate,
 | 
			
		||||
      lastPlayed: this.lastPlayed,
 | 
			
		||||
      isMod: this.isMod,
 | 
			
		||||
      changelog: this.changelog,
 | 
			
		||||
      gameDir: this.gameDir,
 | 
			
		||||
      downloadInfo: this.downloadInfo,
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,4 +28,5 @@ module.exports = Object.freeze({
 | 
			
		|||
  DOWNLOAD_LINKS_CONTAINER: 'span[style="font-size: 18px"]',
 | 
			
		||||
  SEARCH_THREADS_RESULTS_BODY: "div.contentRow-main",
 | 
			
		||||
  SEARCH_THREADS_MEMBERSHIP: "li > a:not(.username)",
 | 
			
		||||
  THREAD_LAST_CHANGELOG: "div.bbCodeBlock-content > div:first-of-type",
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,6 +46,7 @@ module.exports.getGameInfo = async function (browser, url) {
 | 
			
		|||
  let structuredText = await getMainPostStructuredText(page);
 | 
			
		||||
  let overview = getOverview(structuredText, info.isMod);
 | 
			
		||||
  let parsedInfos = parseConversationPage(structuredText);
 | 
			
		||||
  let changelog = getLastChangelog(page);
 | 
			
		||||
 | 
			
		||||
  // Fill in the GameInfo element with the information obtained
 | 
			
		||||
  info.name = await title;
 | 
			
		||||
| 
						 | 
				
			
			@ -60,6 +61,8 @@ module.exports.getGameInfo = async function (browser, url) {
 | 
			
		|||
    ? parsedInfos["UPDATED"]
 | 
			
		||||
    : parsedInfos["THREAD UPDATED"];
 | 
			
		||||
  info.previewSource = await previewSource;
 | 
			
		||||
  let temp = await changelog;
 | 
			
		||||
  info.changelog = temp ? temp : "Unknown changelog";
 | 
			
		||||
  //info.downloadInfo = await downloadData;
 | 
			
		||||
  /* Downloading games without going directly to
 | 
			
		||||
   * the platform appears to be prohibited by
 | 
			
		||||
| 
						 | 
				
			
			@ -280,6 +283,28 @@ async function parsePrefixes(page, info) {
 | 
			
		|||
  return info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @private
 | 
			
		||||
 * Get the last changelog available for the game.
 | 
			
		||||
 * @param {puppeteer.Page} page Page containing the changelog
 | 
			
		||||
 * @returns {Promise<String>} Changelog for the last version or null if no changelog is found
 | 
			
		||||
 */
 | 
			
		||||
async function getLastChangelog(page) {
 | 
			
		||||
  // Gets the first post, where are listed all the game's informations
 | 
			
		||||
  let post = (await page.$$(selectors.THREAD_POSTS))[0];
 | 
			
		||||
 | 
			
		||||
  let spoiler = await post.$(selectors.THREAD_LAST_CHANGELOG);
 | 
			
		||||
  if (!spoiler) return null;
 | 
			
		||||
 | 
			
		||||
  let changelogHTML = await page.evaluate(
 | 
			
		||||
    /* istanbul ignore next */
 | 
			
		||||
    (e) => e.innerText,
 | 
			
		||||
    spoiler
 | 
			
		||||
  );
 | 
			
		||||
  let parsedText = HTMLParser.parse(changelogHTML).structuredText;
 | 
			
		||||
  return parsedText.replace("Spoiler", "").trim();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @private
 | 
			
		||||
 * Get game download links for different platforms.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ const shared = require("./shared.js");
 | 
			
		|||
const constURLs = require("./constants/urls.js");
 | 
			
		||||
const selectors = require("./constants/css-selectors.js");
 | 
			
		||||
const { preparePage } = require("./puppeteer-helper.js");
 | 
			
		||||
const { isF95URL } = require("./urls-helper.js");
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @protected
 | 
			
		||||
| 
						 | 
				
			
			@ -32,10 +33,12 @@ module.exports.getSearchGameResults = async function (browser, gamename) {
 | 
			
		|||
 | 
			
		||||
  await page.type(selectors.SEARCH_FORM_TEXTBOX, gamename); // Type the game we desire
 | 
			
		||||
  await page.click(selectors.TITLE_ONLY_CHECKBOX); // Select only the thread with the game in the titles
 | 
			
		||||
  await page.click(selectors.SEARCH_BUTTON); // Execute search
 | 
			
		||||
  await page.waitForNavigation({
 | 
			
		||||
  await Promise.all([
 | 
			
		||||
    page.click(selectors.SEARCH_BUTTON), // Execute search
 | 
			
		||||
    page.waitForNavigation({
 | 
			
		||||
      waitUntil: shared.WAIT_STATEMENT,
 | 
			
		||||
  }); // Wait for page to load
 | 
			
		||||
    }), // Wait for page to load
 | 
			
		||||
  ]);
 | 
			
		||||
 | 
			
		||||
  // Select all conversation titles
 | 
			
		||||
  let resultsThread = await page.$$(selectors.SEARCH_THREADS_RESULTS_BODY);
 | 
			
		||||
| 
						 | 
				
			
			@ -114,6 +117,10 @@ async function getThreadURL(page, handle) {
 | 
			
		|||
    (e) => e.querySelector("a").href,
 | 
			
		||||
    handle
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  // Some game already have a full URL
 | 
			
		||||
  if (isF95URL(relativeURLThread)) return relativeURLThread;
 | 
			
		||||
 | 
			
		||||
  let urlThread = new URL(relativeURLThread, constURLs.F95_BASE_URL).toString();
 | 
			
		||||
  return urlThread;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,10 +14,17 @@ const shared = require("./shared.js");
 | 
			
		|||
 */
 | 
			
		||||
module.exports.prepareBrowser = async function () {
 | 
			
		||||
  // Create a headless browser
 | 
			
		||||
  let browser = await puppeteer.launch({
 | 
			
		||||
  let browser = null;
 | 
			
		||||
  if (shared.chromiumLocalPath) {
 | 
			
		||||
    browser = await puppeteer.launch({
 | 
			
		||||
      executablePath: shared.chromiumLocalPath,
 | 
			
		||||
      headless: !shared.debug, // Use GUI when debug = true
 | 
			
		||||
    });
 | 
			
		||||
  } else {
 | 
			
		||||
    browser = await puppeteer.launch({
 | 
			
		||||
      headless: !shared.debug, // Use GUI when debug = true
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return browser;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1370
									
								
								coverage.lcov
								
								
								
								
							
							
						
						
									
										1370
									
								
								coverage.lcov
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
{
 | 
			
		||||
  "main": "./app/index.js",
 | 
			
		||||
  "name": "f95api",
 | 
			
		||||
  "version": "1.2.3",
 | 
			
		||||
  "version": "1.2.4",
 | 
			
		||||
  "author": {
 | 
			
		||||
    "name": "Millennium Earl"
 | 
			
		||||
  },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,6 @@ const GameDownload = require("../app/scripts/classes/game-download.js");
 | 
			
		|||
 | 
			
		||||
debug(true);
 | 
			
		||||
main();
 | 
			
		||||
//downloadGameNOPY();
 | 
			
		||||
//downloadGameMEGA();
 | 
			
		||||
 | 
			
		||||
async function main() {
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +18,7 @@ async function main() {
 | 
			
		|||
 | 
			
		||||
  if (loginResult.success) {
 | 
			
		||||
    await loadF95BaseData();
 | 
			
		||||
    let gameData = await getGameData("employee benefits", false);
 | 
			
		||||
    let gameData = await getGameData("queen's brothel", false);
 | 
			
		||||
    console.log(gameData);
 | 
			
		||||
 | 
			
		||||
    // let userData = await getUserData();
 | 
			
		||||
| 
						 | 
				
			
			@ -28,15 +27,6 @@ async function main() {
 | 
			
		|||
  logout();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function downloadGameNOPY() {
 | 
			
		||||
  let gd = new GameDownload();
 | 
			
		||||
  gd.hosting = "NOPY";
 | 
			
		||||
  gd.link = "https://nopy.to/50jmNQbo/Kingdom_of_Deception-pc0.10.8.zip";
 | 
			
		||||
  let savepath = join(__dirname, "Kingdom_of_Deception-pc0.10.8.zip");
 | 
			
		||||
  let result = await gd.download(savepath);
 | 
			
		||||
  console.log(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function downloadGameMEGA() {
 | 
			
		||||
  let gd = new GameDownload();
 | 
			
		||||
  gd.hosting = "NOPY";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue