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