FIx import errors
							parent
							
								
									d969e7ff06
								
							
						
					
					
						commit
						2d396aaebe
					
				| 
						 | 
				
			
			@ -1,15 +1,8 @@
 | 
			
		|||
// Public modules from npm
 | 
			
		||||
import {
 | 
			
		||||
    IsIn,
 | 
			
		||||
    validateSync,
 | 
			
		||||
    IsInt,
 | 
			
		||||
    Min,
 | 
			
		||||
    ArrayMaxSize,
 | 
			
		||||
    IsArray,
 | 
			
		||||
} from 'class-validator';
 | 
			
		||||
import validator from 'class-validator';
 | 
			
		||||
 | 
			
		||||
// Modules from file
 | 
			
		||||
import { urls } from "../constants/url";
 | 
			
		||||
import { urls } from "../constants/url.js";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Query used to search for specific threads on the platform.
 | 
			
		||||
| 
						 | 
				
			
			@ -17,11 +10,11 @@ import { urls } from "../constants/url";
 | 
			
		|||
export default class SearchQuery {
 | 
			
		||||
 | 
			
		||||
    //#region Private fields
 | 
			
		||||
    private MAX_TAGS = 5;
 | 
			
		||||
    private MIN_PAGE = 1;
 | 
			
		||||
    private VALID_CATEGORY = ["games", "comics", "animations", "assets"];
 | 
			
		||||
    private VALID_SORT = ["date", "likes", "views", "title", "rating"];
 | 
			
		||||
    private VALID_DATE = [365, 180, 90, 30, 14, 7, 3, 1, null];
 | 
			
		||||
    private static MAX_TAGS = 5;
 | 
			
		||||
    private static MIN_PAGE = 1;
 | 
			
		||||
    private static VALID_CATEGORY = ["games", "comics", "animations", "assets"];
 | 
			
		||||
    private static VALID_SORT = ["date", "likes", "views", "title", "rating"];
 | 
			
		||||
    private static VALID_DATE = [365, 180, 90, 30, 14, 7, 3, 1, null];
 | 
			
		||||
    //#endregion Private fields
 | 
			
		||||
 | 
			
		||||
    //#region Properties
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +23,7 @@ export default class SearchQuery {
 | 
			
		|||
     * `games`, `comics`, `animations`, `assets`.
 | 
			
		||||
     * Default: `games`
 | 
			
		||||
     */
 | 
			
		||||
    @IsIn(SearchQuery.prototype.VALID_CATEGORY, {
 | 
			
		||||
    @validator.IsIn(SearchQuery.VALID_CATEGORY, {
 | 
			
		||||
        message: "Invalid $property parameter: $value"
 | 
			
		||||
    })
 | 
			
		||||
    public category = 'games';
 | 
			
		||||
| 
						 | 
				
			
			@ -38,17 +31,17 @@ export default class SearchQuery {
 | 
			
		|||
     * List of IDs of tags to be included in the search.
 | 
			
		||||
     * Max. 5 tags
 | 
			
		||||
     */
 | 
			
		||||
    @IsArray({
 | 
			
		||||
    @validator.IsArray({
 | 
			
		||||
        message: "Expected an array, received $value"
 | 
			
		||||
    })
 | 
			
		||||
    @ArrayMaxSize(SearchQuery.prototype.MAX_TAGS, {
 | 
			
		||||
    @validator.ArrayMaxSize(SearchQuery.MAX_TAGS, {
 | 
			
		||||
        message: "Too many tags: $value instead of $constraint1"
 | 
			
		||||
    })
 | 
			
		||||
    public tags: number[] = [];
 | 
			
		||||
    /**
 | 
			
		||||
     * List of IDs of prefixes to be included in the search.
 | 
			
		||||
     */
 | 
			
		||||
    @IsArray({
 | 
			
		||||
    @validator.IsArray({
 | 
			
		||||
        message: "Expected an array, received $value"
 | 
			
		||||
    })
 | 
			
		||||
    public prefixes: number[] = [];
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +49,7 @@ export default class SearchQuery {
 | 
			
		|||
     * Sorting type between (default: `date`):
 | 
			
		||||
     * `date`, `likes`, `views`, `title`, `rating`
 | 
			
		||||
     */
 | 
			
		||||
    @IsIn(SearchQuery.prototype.VALID_SORT, {
 | 
			
		||||
    @validator.IsIn(SearchQuery.VALID_SORT, {
 | 
			
		||||
        message: "Invalid $property parameter: $value"
 | 
			
		||||
    })
 | 
			
		||||
    public sort = 'date';
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +60,7 @@ export default class SearchQuery {
 | 
			
		|||
     * Use `1` to indicate "today" or `null` to indicate "anytime".
 | 
			
		||||
     * Default: `null`
 | 
			
		||||
     */
 | 
			
		||||
    @IsIn(SearchQuery.prototype.VALID_DATE, {
 | 
			
		||||
    @validator.IsIn(SearchQuery.VALID_DATE, {
 | 
			
		||||
        message: "Invalid $property parameter: $value"
 | 
			
		||||
    })
 | 
			
		||||
    public date: number = null;
 | 
			
		||||
| 
						 | 
				
			
			@ -76,13 +69,13 @@ export default class SearchQuery {
 | 
			
		|||
     * Between 1 and infinity.
 | 
			
		||||
     * Default: 1.
 | 
			
		||||
     */
 | 
			
		||||
    @IsInt({
 | 
			
		||||
    @validator.IsInt({
 | 
			
		||||
        message: "$property expect an integer, received $value"
 | 
			
		||||
    })
 | 
			
		||||
    @Min(SearchQuery.prototype.MIN_PAGE, {
 | 
			
		||||
    @validator.Min(SearchQuery.MIN_PAGE, {
 | 
			
		||||
        message: "The minimum $property value must be $constraint1, received $value"
 | 
			
		||||
    })
 | 
			
		||||
    public page = this.MIN_PAGE;
 | 
			
		||||
    public page = SearchQuery.MIN_PAGE;
 | 
			
		||||
    //#endregion Properties
 | 
			
		||||
    
 | 
			
		||||
    //#region Public methods
 | 
			
		||||
| 
						 | 
				
			
			@ -90,7 +83,7 @@ export default class SearchQuery {
 | 
			
		|||
     * Verify that the query values are valid.
 | 
			
		||||
     */
 | 
			
		||||
    public validate(): boolean {
 | 
			
		||||
        return validateSync(this).length === 0;
 | 
			
		||||
        return validator.validateSync(this).length === 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -121,8 +114,8 @@ export default class SearchQuery {
 | 
			
		|||
        
 | 
			
		||||
        // Set the other values
 | 
			
		||||
        url.searchParams.set("sort", this.sort.toString());
 | 
			
		||||
        url.searchParams.set("date", this.date.toString());
 | 
			
		||||
        url.searchParams.set("page", this.page.toString());
 | 
			
		||||
        if(this.date) url.searchParams.set("date", this.date.toString());
 | 
			
		||||
 | 
			
		||||
        return url;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
"use strict";
 | 
			
		||||
 | 
			
		||||
// Modules from file
 | 
			
		||||
import { fetchGETResponse } from "./network-helper";
 | 
			
		||||
import SearchQuery from "./classes/search-query";
 | 
			
		||||
import { urls as f95url } from "./constants/url";
 | 
			
		||||
import { fetchGETResponse } from "./network-helper.js";
 | 
			
		||||
import SearchQuery from "./classes/search-query.js";
 | 
			
		||||
import { urls as f95url } from "./constants/url.js";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @public
 | 
			
		||||
| 
						 | 
				
			
			@ -31,17 +31,17 @@ export async function fetchLatest(query: SearchQuery, limit = 30): Promise<strin
 | 
			
		|||
        const response = await fetchGETResponse(url);
 | 
			
		||||
 | 
			
		||||
        // Save the URLs
 | 
			
		||||
        for(const result of response.data.msg.data) {
 | 
			
		||||
            if(fetchedResults < limit) {
 | 
			
		||||
                const gameURL = new URL(result.thread_id, threadURL).href;
 | 
			
		||||
                resultURLs.push(gameURL);
 | 
			
		||||
                fetchedResults += 1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // for(const result of response.data.msg.data) {
 | 
			
		||||
        //     if(fetchedResults < limit) {
 | 
			
		||||
        //         const gameURL = new URL(result.thread_id, threadURL).href;
 | 
			
		||||
        //         resultURLs.push(gameURL);
 | 
			
		||||
        //         fetchedResults += 1;
 | 
			
		||||
        //     }
 | 
			
		||||
        // }
 | 
			
		||||
        
 | 
			
		||||
        // Increment page and check for it's existence
 | 
			
		||||
        page += 1;
 | 
			
		||||
        if (page > response.data.msg.pagination.total) noMorePages = true;
 | 
			
		||||
        //if (page > response.data.msg.pagination.total) noMorePages = true;
 | 
			
		||||
    }
 | 
			
		||||
    while (fetchedResults < limit && !noMorePages);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,16 +7,17 @@ import axiosCookieJarSupport from "axios-cookiejar-support";
 | 
			
		|||
import tough from "tough-cookie";
 | 
			
		||||
 | 
			
		||||
// Modules from file
 | 
			
		||||
import shared from "./shared";
 | 
			
		||||
import { urls as f95url } from "./constants/url";
 | 
			
		||||
import { selectors as f95selector } from "./constants/css-selector";
 | 
			
		||||
import LoginResult from "./classes/login-result";
 | 
			
		||||
import credentials from "./classes/credentials";
 | 
			
		||||
import shared from "./shared.js";
 | 
			
		||||
import { urls as f95url } from "./constants/url.js";
 | 
			
		||||
import { selectors as f95selector } from "./constants/css-selector.js";
 | 
			
		||||
import LoginResult from "./classes/login-result.js";
 | 
			
		||||
import credentials from "./classes/credentials.js";
 | 
			
		||||
 | 
			
		||||
// Global variables
 | 
			
		||||
const userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) " + 
 | 
			
		||||
    "AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0 Safari/605.1.15";
 | 
			
		||||
axiosCookieJarSupport(axios);
 | 
			
		||||
// @ts-ignore
 | 
			
		||||
axiosCookieJarSupport.default(axios);
 | 
			
		||||
 | 
			
		||||
const commonConfig = {
 | 
			
		||||
    headers: {
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +37,7 @@ export async function fetchHTML(url: string): Promise<string|null> {
 | 
			
		|||
    let returnValue = null;
 | 
			
		||||
 | 
			
		||||
    // Fetch the response of the platform
 | 
			
		||||
    const response = await exports.fetchGETResponse(url);
 | 
			
		||||
    const response = await fetchGETResponse(url);
 | 
			
		||||
 | 
			
		||||
    // Manage response
 | 
			
		||||
    /* istambul ignore next */
 | 
			
		||||
| 
						 | 
				
			
			@ -66,7 +67,7 @@ export async function authenticate(credentials: credentials, force: boolean = fa
 | 
			
		|||
    if (!credentials.token) throw new Error(`Invalid token for auth: ${credentials.token}`);
 | 
			
		||||
 | 
			
		||||
    // Secure the URL
 | 
			
		||||
    const secureURL = exports.enforceHttpsUrl(f95url.F95_LOGIN_URL);
 | 
			
		||||
    const secureURL = enforceHttpsUrl(f95url.F95_LOGIN_URL);
 | 
			
		||||
 | 
			
		||||
    // Prepare the parameters to send to the platform to authenticate
 | 
			
		||||
    const params = new URLSearchParams();
 | 
			
		||||
| 
						 | 
				
			
			@ -108,7 +109,7 @@ export async function authenticate(credentials: credentials, force: boolean = fa
 | 
			
		|||
 */
 | 
			
		||||
export async function getF95Token(): Promise<string|null> {
 | 
			
		||||
    // Fetch the response of the platform
 | 
			
		||||
    const response = await exports.fetchGETResponse(f95url.F95_LOGIN_URL);
 | 
			
		||||
    const response = await fetchGETResponse(f95url.F95_LOGIN_URL);
 | 
			
		||||
    /* istambul ignore next */
 | 
			
		||||
    if (!response) {
 | 
			
		||||
        shared.logger.warn("Unable to get the token for the session");
 | 
			
		||||
| 
						 | 
				
			
			@ -116,7 +117,7 @@ export async function getF95Token(): Promise<string|null> {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    // The response is a HTML page, we need to find the <input> with name "_xfToken"
 | 
			
		||||
    const $ = cheerio.load(response.data);
 | 
			
		||||
    const $ = cheerio.load(response.data as string);
 | 
			
		||||
    return $("body").find(f95selector.GET_REQUEST_TOKEN).attr("value");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -127,7 +128,7 @@ export async function getF95Token(): Promise<string|null> {
 | 
			
		|||
 */
 | 
			
		||||
export async function fetchGETResponse(url: string): Promise<AxiosResponse<unknown>> {
 | 
			
		||||
    // Secure the URL
 | 
			
		||||
    const secureURL = exports.enforceHttpsUrl(url);
 | 
			
		||||
    const secureURL = enforceHttpsUrl(url);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        // Fetch and return the response
 | 
			
		||||
| 
						 | 
				
			
			@ -144,7 +145,7 @@ export async function fetchGETResponse(url: string): Promise<AxiosResponse<unkno
 | 
			
		|||
 * @returns {String} Secure URL or `null` if the argument is not a string
 | 
			
		||||
 */
 | 
			
		||||
export function enforceHttpsUrl(url: string): string {
 | 
			
		||||
    return exports.isStringAValidURL(url) ? url.replace(/^(https?:)?\/\//, "https://") : null;
 | 
			
		||||
    return isStringAValidURL(url) ? url.replace(/^(https?:)?\/\//, "https://") : null;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -183,11 +184,11 @@ export async function urlExists(url: string, checkRedirect: boolean = false): Pr
 | 
			
		|||
    // Local variables
 | 
			
		||||
    let valid = false;
 | 
			
		||||
 | 
			
		||||
    if (exports.isStringAValidURL(url)) {
 | 
			
		||||
    if (isStringAValidURL(url)) {
 | 
			
		||||
        valid = await axiosUrlExists(url);
 | 
			
		||||
 | 
			
		||||
        if (valid && checkRedirect) {
 | 
			
		||||
            const redirectUrl = await exports.getUrlRedirect(url);
 | 
			
		||||
            const redirectUrl = await getUrlRedirect(url);
 | 
			
		||||
            valid = redirectUrl === url;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,10 +6,10 @@ import { tmpdir } from "os";
 | 
			
		|||
import { join } from "path";
 | 
			
		||||
 | 
			
		||||
// Public modules from npm
 | 
			
		||||
import { getLogger, Logger } from "log4js";
 | 
			
		||||
import log4js from "log4js";
 | 
			
		||||
 | 
			
		||||
// Modules from file
 | 
			
		||||
import Session from "./classes/session";
 | 
			
		||||
import Session from "./classes/session.js";
 | 
			
		||||
 | 
			
		||||
// Types declaration
 | 
			
		||||
export type DictType = { [n: number]: string; };
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +42,7 @@ export default abstract class Shared {
 | 
			
		|||
    /**
 | 
			
		||||
     * Logger object used to write to both file and console.
 | 
			
		||||
     */
 | 
			
		||||
    static _logger: Logger = getLogger();
 | 
			
		||||
    static _logger: log4js.Logger = log4js.getLogger();
 | 
			
		||||
    /**
 | 
			
		||||
     * Session on the F95Zone platform.
 | 
			
		||||
     */
 | 
			
		||||
| 
						 | 
				
			
			@ -83,7 +83,7 @@ export default abstract class Shared {
 | 
			
		|||
    /**
 | 
			
		||||
     * Logger object used to write to both file and console.
 | 
			
		||||
     */
 | 
			
		||||
    static get logger(): Logger {
 | 
			
		||||
    static get logger(): log4js.Logger {
 | 
			
		||||
        return this._logger;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -122,5 +122,3 @@ export default abstract class Shared {
 | 
			
		|||
    }
 | 
			
		||||
    //#endregion Setters
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = Shared;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue