Run prettier
parent
48885a8604
commit
3014ce350a
|
@ -74,8 +74,7 @@ async function main() {
|
||||||
// Get user data
|
// Get user data
|
||||||
console.log("Fetching user data...");
|
console.log("Fetching user data...");
|
||||||
const userdata = await getUserData();
|
const userdata = await getUserData();
|
||||||
const gameThreads = userdata.watched.filter((e) => e.forum === "Games")
|
const gameThreads = userdata.watched.filter((e) => e.forum === "Games").length;
|
||||||
.length;
|
|
||||||
console.log(
|
console.log(
|
||||||
`${userdata.name} follows ${userdata.watched.length} threads of which ${gameThreads} are games\n`
|
`${userdata.name} follows ${userdata.watched.length} threads of which ${gameThreads} are games\n`
|
||||||
);
|
);
|
||||||
|
@ -87,9 +86,7 @@ async function main() {
|
||||||
|
|
||||||
const latestUpdates = await getLatestUpdates<Game>(latestQuery, 1);
|
const latestUpdates = await getLatestUpdates<Game>(latestQuery, 1);
|
||||||
console.log(
|
console.log(
|
||||||
`"${
|
`"${latestUpdates.shift().name}" was the last "3d game" tagged game to be updated\n`
|
||||||
latestUpdates.shift().name
|
|
||||||
}" was the last "3d game" tagged game to be updated\n`
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get game data
|
// Get game data
|
||||||
|
@ -114,8 +111,6 @@ async function main() {
|
||||||
// Extract first game
|
// Extract first game
|
||||||
const gamedata = searchResult.shift();
|
const gamedata = searchResult.shift();
|
||||||
const authors = gamedata.authors.map((a, idx) => a.name).join(", ");
|
const authors = gamedata.authors.map((a, idx) => a.name).join(", ");
|
||||||
console.log(
|
console.log(`Found: ${gamedata.name} (${gamedata.version}) by ${authors}\n`);
|
||||||
`Found: ${gamedata.name} (${gamedata.version}) by ${authors}\n`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,9 +141,7 @@ export async function login(
|
||||||
*
|
*
|
||||||
* You **must** be logged in to the portal before calling this method.
|
* You **must** be logged in to the portal before calling this method.
|
||||||
*/
|
*/
|
||||||
export async function checkIfHandiworkHasUpdate(
|
export async function checkIfHandiworkHasUpdate(hw: HandiWork): Promise<boolean> {
|
||||||
hw: HandiWork
|
|
||||||
): Promise<boolean> {
|
|
||||||
// Local variables
|
// Local variables
|
||||||
let hasUpdate = false;
|
let hasUpdate = false;
|
||||||
|
|
||||||
|
@ -186,9 +184,7 @@ export async function searchHandiwork<T extends IBasic>(
|
||||||
*
|
*
|
||||||
* You **must** be logged in to the portal before calling this method.
|
* You **must** be logged in to the portal before calling this method.
|
||||||
*/
|
*/
|
||||||
export async function getHandiworkFromURL<T extends IBasic>(
|
export async function getHandiworkFromURL<T extends IBasic>(url: string): Promise<T> {
|
||||||
url: string
|
|
||||||
): Promise<T> {
|
|
||||||
// Check if the user is logged
|
// Check if the user is logged
|
||||||
if (!shared.isLogged) throw new UserNotLogged(USER_NOT_LOGGED);
|
if (!shared.isLogged) throw new UserNotLogged(USER_NOT_LOGGED);
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// Modules from files
|
// Modules from files
|
||||||
import {
|
import { TAuthor, TEngine, IGame, TRating, TStatus, TCategory } from "../../interfaces";
|
||||||
TAuthor,
|
|
||||||
TEngine,
|
|
||||||
IGame,
|
|
||||||
TRating,
|
|
||||||
TStatus,
|
|
||||||
TCategory
|
|
||||||
} from "../../interfaces";
|
|
||||||
|
|
||||||
export default class Game implements IGame {
|
export default class Game implements IGame {
|
||||||
//#region Properties
|
//#region Properties
|
||||||
|
|
|
@ -180,12 +180,10 @@ export default class PlatformUser {
|
||||||
|
|
||||||
// Parse date
|
// Parse date
|
||||||
const joined = $(MEMBER.JOINED)?.attr("datetime");
|
const joined = $(MEMBER.JOINED)?.attr("datetime");
|
||||||
if (luxon.DateTime.fromISO(joined).isValid)
|
if (luxon.DateTime.fromISO(joined).isValid) this._joined = new Date(joined);
|
||||||
this._joined = new Date(joined);
|
|
||||||
|
|
||||||
const lastSeen = $(MEMBER.LAST_SEEN)?.attr("datetime");
|
const lastSeen = $(MEMBER.LAST_SEEN)?.attr("datetime");
|
||||||
if (luxon.DateTime.fromISO(lastSeen).isValid)
|
if (luxon.DateTime.fromISO(lastSeen).isValid) this._joined = new Date(lastSeen);
|
||||||
this._joined = new Date(lastSeen);
|
|
||||||
|
|
||||||
// Parse donation
|
// Parse donation
|
||||||
const donation = $(MEMBER.AMOUNT_DONATED)?.text().replace("$", "");
|
const donation = $(MEMBER.AMOUNT_DONATED)?.text().replace("$", "");
|
||||||
|
|
|
@ -10,10 +10,7 @@ import cheerio from "cheerio";
|
||||||
|
|
||||||
// Modules from file
|
// Modules from file
|
||||||
import PlatformUser from "./platform-user.js";
|
import PlatformUser from "./platform-user.js";
|
||||||
import {
|
import { IPostElement, parseF95ThreadPost } from "../../scrape-data/post-parse.js";
|
||||||
IPostElement,
|
|
||||||
parseF95ThreadPost
|
|
||||||
} from "../../scrape-data/post-parse.js";
|
|
||||||
import { POST, THREAD } from "../../constants/css-selector.js";
|
import { POST, THREAD } from "../../constants/css-selector.js";
|
||||||
import { urls } from "../../constants/url.js";
|
import { urls } from "../../constants/url.js";
|
||||||
import { fetchHTML } from "../../network-helper.js";
|
import { fetchHTML } from "../../network-helper.js";
|
||||||
|
@ -110,10 +107,7 @@ export default class Post {
|
||||||
.toArray()
|
.toArray()
|
||||||
.find((el, idx) => {
|
.find((el, idx) => {
|
||||||
// Fetch the ID and check if it is what we are searching
|
// Fetch the ID and check if it is what we are searching
|
||||||
const sid: string = $(el)
|
const sid: string = $(el).find(POST.ID).attr("id").replace("post-", "");
|
||||||
.find(POST.ID)
|
|
||||||
.attr("id")
|
|
||||||
.replace("post-", "");
|
|
||||||
const id = parseInt(sid, 10);
|
const id = parseInt(sid, 10);
|
||||||
|
|
||||||
if (id === this.id) return el;
|
if (id === this.id) return el;
|
||||||
|
@ -128,10 +122,7 @@ export default class Post {
|
||||||
|
|
||||||
//#region Private methods
|
//#region Private methods
|
||||||
|
|
||||||
private async parsePost(
|
private async parsePost($: cheerio.Root, post: cheerio.Cheerio): Promise<void> {
|
||||||
$: cheerio.Root,
|
|
||||||
post: cheerio.Cheerio
|
|
||||||
): Promise<void> {
|
|
||||||
// Find post's ID
|
// Find post's ID
|
||||||
const sid: string = post.find(POST.ID).attr("id").replace("post-", "");
|
const sid: string = post.find(POST.ID).attr("id").replace("post-", "");
|
||||||
this._id = parseInt(sid, 10);
|
this._id = parseInt(sid, 10);
|
||||||
|
@ -149,10 +140,7 @@ export default class Post {
|
||||||
this._lastEdit = new Date(sLastEdit);
|
this._lastEdit = new Date(sLastEdit);
|
||||||
|
|
||||||
// Find post's owner
|
// Find post's owner
|
||||||
const sOwnerID: string = post
|
const sOwnerID: string = post.find(POST.OWNER_ID).attr("data-user-id").trim();
|
||||||
.find(POST.OWNER_ID)
|
|
||||||
.attr("data-user-id")
|
|
||||||
.trim();
|
|
||||||
this._owner = new PlatformUser(parseInt(sOwnerID, 10));
|
this._owner = new PlatformUser(parseInt(sOwnerID, 10));
|
||||||
await this._owner.fetch();
|
await this._owner.fetch();
|
||||||
|
|
||||||
|
|
|
@ -195,9 +195,7 @@ export default class Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sorts the list of posts
|
// Sorts the list of posts
|
||||||
return fetchedPosts.sort((a, b) =>
|
return fetchedPosts.sort((a, b) => (a.id > b.id ? 1 : b.id > a.id ? -1 : 0));
|
||||||
a.id > b.id ? 1 : b.id > a.id ? -1 : 0
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -267,8 +265,7 @@ export default class Thread {
|
||||||
this._category = JSONLD["articleSection"] as TCategory;
|
this._category = JSONLD["articleSection"] as TCategory;
|
||||||
|
|
||||||
// Validate the dates
|
// Validate the dates
|
||||||
if (luxon.DateTime.fromISO(modified).isValid)
|
if (luxon.DateTime.fromISO(modified).isValid) this._modified = new Date(modified);
|
||||||
this._modified = new Date(modified);
|
|
||||||
if (luxon.DateTime.fromISO(published).isValid)
|
if (luxon.DateTime.fromISO(published).isValid)
|
||||||
this._publication = new Date(published);
|
this._publication = new Date(published);
|
||||||
} else throw htmlResponse.value;
|
} else throw htmlResponse.value;
|
||||||
|
@ -282,8 +279,7 @@ export default class Thread {
|
||||||
*/
|
*/
|
||||||
public async getPost(index: number): Promise<Post | null> {
|
public async getPost(index: number): Promise<Post | null> {
|
||||||
// Validate parameters
|
// Validate parameters
|
||||||
if (index < 1)
|
if (index < 1) throw new ParameterError("Index must be greater or equal than 1");
|
||||||
throw new ParameterError("Index must be greater or equal than 1");
|
|
||||||
|
|
||||||
// Local variables
|
// Local variables
|
||||||
let returnValue = null;
|
let returnValue = null;
|
||||||
|
|
|
@ -34,10 +34,7 @@ interface IWatchedThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
type TFetchResult = Result<
|
type TFetchResult = Result<GenericAxiosError | UnexpectedResponseContentType, string>;
|
||||||
GenericAxiosError | UnexpectedResponseContentType,
|
|
||||||
string
|
|
||||||
>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class containing the data of the user currently connected to the F95Zone platform.
|
* Class containing the data of the user currently connected to the F95Zone platform.
|
||||||
|
@ -151,11 +148,7 @@ export default class UserProfile extends PlatformUser {
|
||||||
* @param n Total number of pages
|
* @param n Total number of pages
|
||||||
* @param s Page to start from
|
* @param s Page to start from
|
||||||
*/
|
*/
|
||||||
private async fetchPages(
|
private async fetchPages(url: URL, n: number, s = 1): Promise<TFetchResult[]> {
|
||||||
url: URL,
|
|
||||||
n: number,
|
|
||||||
s = 1
|
|
||||||
): Promise<TFetchResult[]> {
|
|
||||||
// Local variables
|
// Local variables
|
||||||
const responsePromiseList: Promise<TFetchResult>[] = [];
|
const responsePromiseList: Promise<TFetchResult>[] = [];
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,7 @@ export default class PrefixParser {
|
||||||
* @param {Any} value Value associated with the key
|
* @param {Any} value Value associated with the key
|
||||||
* @returns {String|undefined} Key found or undefined
|
* @returns {String|undefined} Key found or undefined
|
||||||
*/
|
*/
|
||||||
private getKeyByValue(
|
private getKeyByValue(object: TPrefixDict, value: string): string | undefined {
|
||||||
object: TPrefixDict,
|
|
||||||
value: string
|
|
||||||
): string | undefined {
|
|
||||||
return Object.keys(object).find((key) => object[key] === value);
|
return Object.keys(object).find((key) => object[key] === value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,9 +51,7 @@ export default class PrefixParser {
|
||||||
* desired element and return the dictionary that contains it.
|
* desired element and return the dictionary that contains it.
|
||||||
* @param element Element to search in the prefixes as a key or as a value
|
* @param element Element to search in the prefixes as a key or as a value
|
||||||
*/
|
*/
|
||||||
private searchElementInPrefixes(
|
private searchElementInPrefixes(element: string | number): TPrefixDict | null {
|
||||||
element: string | number
|
|
||||||
): TPrefixDict | null {
|
|
||||||
// Local variables
|
// Local variables
|
||||||
let dictName = null;
|
let dictName = null;
|
||||||
|
|
||||||
|
@ -64,13 +59,11 @@ export default class PrefixParser {
|
||||||
for (const [key, subdict] of Object.entries(shared.prefixes)) {
|
for (const [key, subdict] of Object.entries(shared.prefixes)) {
|
||||||
// Check if the element is a value in the sub-dict
|
// Check if the element is a value in the sub-dict
|
||||||
const valueInDict =
|
const valueInDict =
|
||||||
typeof element === "string" &&
|
typeof element === "string" && this.valueInDict(subdict, element as string);
|
||||||
this.valueInDict(subdict, element as string);
|
|
||||||
|
|
||||||
// Check if the element is a key in the subdict
|
// Check if the element is a key in the subdict
|
||||||
const keyInDict =
|
const keyInDict =
|
||||||
typeof element === "number" &&
|
typeof element === "number" && Object.keys(subdict).includes(element.toString());
|
||||||
Object.keys(subdict).includes(element.toString());
|
|
||||||
|
|
||||||
if (valueInDict || keyInDict) {
|
if (valueInDict || keyInDict) {
|
||||||
dictName = key;
|
dictName = key;
|
||||||
|
|
|
@ -35,13 +35,7 @@ import ThreadSearchQuery, { TThreadOrder } from "./thread-search-query.js";
|
||||||
*
|
*
|
||||||
* `views`: Order based on the number of visits. Replacement: `replies`.
|
* `views`: Order based on the number of visits. Replacement: `replies`.
|
||||||
*/
|
*/
|
||||||
type THandiworkOrder =
|
type THandiworkOrder = "date" | "likes" | "relevance" | "replies" | "title" | "views";
|
||||||
| "date"
|
|
||||||
| "likes"
|
|
||||||
| "relevance"
|
|
||||||
| "replies"
|
|
||||||
| "title"
|
|
||||||
| "views";
|
|
||||||
type TExecuteResult = Result<GenericAxiosError, AxiosResponse<any>>;
|
type TExecuteResult = Result<GenericAxiosError, AxiosResponse<any>>;
|
||||||
|
|
||||||
export default class HandiworkSearchQuery implements IQuery {
|
export default class HandiworkSearchQuery implements IQuery {
|
||||||
|
@ -118,20 +112,13 @@ export default class HandiworkSearchQuery implements IQuery {
|
||||||
|
|
||||||
// Check if the query is valid
|
// Check if the query is valid
|
||||||
if (!this.validate()) {
|
if (!this.validate()) {
|
||||||
throw new Error(
|
throw new Error(`Invalid query: ${validator.validateSync(this).join("\n")}`);
|
||||||
`Invalid query: ${validator.validateSync(this).join("\n")}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the query
|
// Convert the query
|
||||||
if (this.selectSearchType() === "latest")
|
if (this.selectSearchType() === "latest")
|
||||||
response = await this.cast<LatestSearchQuery>(
|
response = await this.cast<LatestSearchQuery>("LatestSearchQuery").execute();
|
||||||
"LatestSearchQuery"
|
else response = await this.cast<ThreadSearchQuery>("ThreadSearchQuery").execute();
|
||||||
).execute();
|
|
||||||
else
|
|
||||||
response = await this.cast<ThreadSearchQuery>(
|
|
||||||
"ThreadSearchQuery"
|
|
||||||
).execute();
|
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,14 +72,10 @@ export default class LatestSearchQuery implements IQuery {
|
||||||
return validator.validateSync(this).length === 0;
|
return validator.validateSync(this).length === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async execute(): Promise<
|
public async execute(): Promise<Result<GenericAxiosError, AxiosResponse<any>>> {
|
||||||
Result<GenericAxiosError, AxiosResponse<any>>
|
|
||||||
> {
|
|
||||||
// Check if the query is valid
|
// Check if the query is valid
|
||||||
if (!this.validate()) {
|
if (!this.validate()) {
|
||||||
throw new Error(
|
throw new Error(`Invalid query: ${validator.validateSync(this).join("\n")}`);
|
||||||
`Invalid query: ${validator.validateSync(this).join("\n")}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the URL
|
// Prepare the URL
|
||||||
|
@ -98,10 +94,7 @@ export default class LatestSearchQuery implements IQuery {
|
||||||
const diff = this.dateDiffInDays(new Date(), d);
|
const diff = this.dateDiffInDays(new Date(), d);
|
||||||
|
|
||||||
// Find the closest valid value in the array
|
// Find the closest valid value in the array
|
||||||
const closest = [365, 180, 90, 30, 14, 7, 3, 1].reduce(function (
|
const closest = [365, 180, 90, 30, 14, 7, 3, 1].reduce(function (prev, curr) {
|
||||||
prev,
|
|
||||||
curr
|
|
||||||
) {
|
|
||||||
return Math.abs(curr - diff) < Math.abs(prev - diff) ? curr : prev;
|
return Math.abs(curr - diff) < Math.abs(prev - diff) ? curr : prev;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -78,14 +78,10 @@ export default class ThreadSearchQuery implements IQuery {
|
||||||
return validator.validateSync(this).length === 0;
|
return validator.validateSync(this).length === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async execute(): Promise<
|
public async execute(): Promise<Result<GenericAxiosError, AxiosResponse<any>>> {
|
||||||
Result<GenericAxiosError, AxiosResponse<any>>
|
|
||||||
> {
|
|
||||||
// Check if the query is valid
|
// Check if the query is valid
|
||||||
if (!this.validate()) {
|
if (!this.validate()) {
|
||||||
throw new Error(
|
throw new Error(`Invalid query: ${validator.validateSync(this).join("\n")}`);
|
||||||
`Invalid query: ${validator.validateSync(this).join("\n")}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define the POST parameters
|
// Define the POST parameters
|
||||||
|
@ -131,8 +127,7 @@ export default class ThreadSearchQuery implements IQuery {
|
||||||
|
|
||||||
// Set included and excluded tags (joined with a comma)
|
// Set included and excluded tags (joined with a comma)
|
||||||
if (this.includedTags) params["c[tags]"] = this.includedTags.join(",");
|
if (this.includedTags) params["c[tags]"] = this.includedTags.join(",");
|
||||||
if (this.excludedTags)
|
if (this.excludedTags) params["c[excludeTags]"] = this.excludedTags.join(",");
|
||||||
params["c[excludeTags]"] = this.excludedTags.join(",");
|
|
||||||
|
|
||||||
// Set minimum reply number
|
// Set minimum reply number
|
||||||
if (this.minimumReplies > 0)
|
if (this.minimumReplies > 0)
|
||||||
|
|
|
@ -210,9 +210,8 @@ export default class Session {
|
||||||
|
|
||||||
// Search for expired cookies
|
// Search for expired cookies
|
||||||
const jarValid =
|
const jarValid =
|
||||||
this._cookieJar
|
this._cookieJar.getCookiesSync("https://f95zone.to").filter((el) => el.TTL() === 0)
|
||||||
.getCookiesSync("https://f95zone.to")
|
.length === 0;
|
||||||
.filter((el) => el.TTL() === 0).length === 0;
|
|
||||||
|
|
||||||
return dateValid && hashValid && jarValid;
|
return dateValid && hashValid && jarValid;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,7 @@ export const selectors = {
|
||||||
GET_REQUEST_TOKEN: 'input[name="_xfToken"]',
|
GET_REQUEST_TOKEN: 'input[name="_xfToken"]',
|
||||||
UD_USERNAME_ELEMENT: 'a[href="/account/"] > span.p-navgroup-linkText',
|
UD_USERNAME_ELEMENT: 'a[href="/account/"] > span.p-navgroup-linkText',
|
||||||
UD_AVATAR_PIC: 'a[href="/account/"] > span.avatar > img[class^="avatar"]',
|
UD_AVATAR_PIC: 'a[href="/account/"] > span.avatar > img[class^="avatar"]',
|
||||||
LOGIN_MESSAGE_ERROR:
|
LOGIN_MESSAGE_ERROR: "div.blockMessage.blockMessage--error.blockMessage--iconic",
|
||||||
"div.blockMessage.blockMessage--error.blockMessage--iconic",
|
|
||||||
LU_TAGS_SCRIPT: "script:contains('latestUpdates')",
|
LU_TAGS_SCRIPT: "script:contains('latestUpdates')",
|
||||||
BK_RESULTS: "ol.listPlain > * div.contentRow-main",
|
BK_RESULTS: "ol.listPlain > * div.contentRow-main",
|
||||||
BK_POST_URL: "div.contentRow-title > a",
|
BK_POST_URL: "div.contentRow-title > a",
|
||||||
|
@ -117,8 +116,7 @@ export const POST = {
|
||||||
*
|
*
|
||||||
* For use within a `THREAD.POSTS_IN_PAGE` selector.
|
* For use within a `THREAD.POSTS_IN_PAGE` selector.
|
||||||
*/
|
*/
|
||||||
NUMBER:
|
NUMBER: '* ul.message-attribution-opposite > li > a:not([id])[rel="nofollow"]',
|
||||||
'* ul.message-attribution-opposite > li > a:not([id])[rel="nofollow"]',
|
|
||||||
/**
|
/**
|
||||||
* Unique ID of the post in the F95Zone platform in the `id` attribute.
|
* Unique ID of the post in the F95Zone platform in the `id` attribute.
|
||||||
*
|
*
|
||||||
|
@ -154,8 +152,7 @@ export const POST = {
|
||||||
*
|
*
|
||||||
* For use within a `THREAD.POSTS_IN_PAGE` selector.
|
* For use within a `THREAD.POSTS_IN_PAGE` selector.
|
||||||
*/
|
*/
|
||||||
BOOKMARKED:
|
BOOKMARKED: '* ul.message-attribution-opposite >li > a[title="Bookmark"].is-bookmarked'
|
||||||
'* ul.message-attribution-opposite >li > a[title="Bookmark"].is-bookmarked'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MEMBER = {
|
export const MEMBER = {
|
||||||
|
@ -188,15 +185,13 @@ export const MEMBER = {
|
||||||
*
|
*
|
||||||
* The date is contained in the `datetime` attribute as an ISO string.
|
* The date is contained in the `datetime` attribute as an ISO string.
|
||||||
*/
|
*/
|
||||||
JOINED:
|
JOINED: "div.uix_memberHeader__extra > div.memberHeader-blurb:nth-child(1) > * time",
|
||||||
"div.uix_memberHeader__extra > div.memberHeader-blurb:nth-child(1) > * time",
|
|
||||||
/**
|
/**
|
||||||
* Last time the user connected to the platform.
|
* Last time the user connected to the platform.
|
||||||
*
|
*
|
||||||
* The date is contained in the `datetime` attribute as an ISO string.
|
* The date is contained in the `datetime` attribute as an ISO string.
|
||||||
*/
|
*/
|
||||||
LAST_SEEN:
|
LAST_SEEN: "div.uix_memberHeader__extra > div.memberHeader-blurb:nth-child(2) > * time",
|
||||||
"div.uix_memberHeader__extra > div.memberHeader-blurb:nth-child(2) > * time",
|
|
||||||
MESSAGES: "div.pairJustifier > dl:nth-child(1) > * a",
|
MESSAGES: "div.pairJustifier > dl:nth-child(1) > * a",
|
||||||
REACTION_SCORE: "div.pairJustifier > dl:nth-child(2) > dd",
|
REACTION_SCORE: "div.pairJustifier > dl:nth-child(2) > dd",
|
||||||
POINTS: "div.pairJustifier > dl:nth-child(3) > * a",
|
POINTS: "div.pairJustifier > dl:nth-child(3) > * a",
|
||||||
|
@ -216,6 +211,5 @@ export const MEMBER = {
|
||||||
* If the text is `Unignore` then the user is ignored.
|
* If the text is `Unignore` then the user is ignored.
|
||||||
* If the text is `Ignore` then the user is not ignored.
|
* If the text is `Ignore` then the user is not ignored.
|
||||||
*/
|
*/
|
||||||
IGNORED:
|
IGNORED: "div.memberHeader-buttons > div.buttonGroup:first-child > a[data-sk-ignore]"
|
||||||
"div.memberHeader-buttons > div.buttonGroup:first-child > a[data-sk-ignore]"
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,10 +24,7 @@ export default async function fetchLatestHandiworkURLs(
|
||||||
limit = 30
|
limit = 30
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
// Local variables
|
// Local variables
|
||||||
const shallowQuery: LatestSearchQuery = Object.assign(
|
const shallowQuery: LatestSearchQuery = Object.assign(new LatestSearchQuery(), query);
|
||||||
new LatestSearchQuery(),
|
|
||||||
query
|
|
||||||
);
|
|
||||||
const resultURLs = [];
|
const resultURLs = [];
|
||||||
let fetchedResults = 0;
|
let fetchedResults = 0;
|
||||||
let noMorePages = false;
|
let noMorePages = false;
|
||||||
|
@ -44,8 +41,7 @@ export default async function fetchLatestHandiworkURLs(
|
||||||
|
|
||||||
data.map((e, idx) => {
|
data.map((e, idx) => {
|
||||||
if (fetchedResults < limit) {
|
if (fetchedResults < limit) {
|
||||||
const gameURL = new URL(e.thread_id.toString(), urls.F95_THREADS)
|
const gameURL = new URL(e.thread_id.toString(), urls.F95_THREADS).href;
|
||||||
.href;
|
|
||||||
resultURLs.push(gameURL);
|
resultURLs.push(gameURL);
|
||||||
|
|
||||||
fetchedResults += 1;
|
fetchedResults += 1;
|
||||||
|
|
|
@ -34,8 +34,7 @@ export default async function fetchThreadHandiworkURLs(
|
||||||
const response = await query.execute();
|
const response = await query.execute();
|
||||||
|
|
||||||
// Fetch the results from F95 and return the handiwork urls
|
// Fetch the results from F95 and return the handiwork urls
|
||||||
if (response.isSuccess())
|
if (response.isSuccess()) return fetchResultURLs(response.value.data as string, limit);
|
||||||
return fetchResultURLs(response.value.data as string, limit);
|
|
||||||
else throw response.value;
|
else throw response.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,8 +150,7 @@ export async function send2faCode(
|
||||||
// Prepare the parameters to send via POST request
|
// Prepare the parameters to send via POST request
|
||||||
const params = {
|
const params = {
|
||||||
_xfRedirect: urls.F95_BASE_URL,
|
_xfRedirect: urls.F95_BASE_URL,
|
||||||
_xfRequestUri:
|
_xfRequestUri: "/login/two-step?_xfRedirect=https%3A%2F%2Ff95zone.to%2F&remember=1",
|
||||||
"/login/two-step?_xfRedirect=https%3A%2F%2Ff95zone.to%2F&remember=1",
|
|
||||||
_xfResponseType: "json",
|
_xfResponseType: "json",
|
||||||
_xfToken: token,
|
_xfToken: token,
|
||||||
_xfWithData: "1",
|
_xfWithData: "1",
|
||||||
|
@ -167,9 +166,7 @@ export async function send2faCode(
|
||||||
return response.applyOnSuccess((r: AxiosResponse<any>) => {
|
return response.applyOnSuccess((r: AxiosResponse<any>) => {
|
||||||
// r.data.status is 'ok' if the authentication is successful
|
// r.data.status is 'ok' if the authentication is successful
|
||||||
const result = r.data.status === "ok";
|
const result = r.data.status === "ok";
|
||||||
const message = result
|
const message = result ? "Authentication successful" : r.data.errors.join(",");
|
||||||
? "Authentication successful"
|
|
||||||
: r.data.errors.join(",");
|
|
||||||
const code = result
|
const code = result
|
||||||
? LoginResult.AUTH_SUCCESSFUL_2FA
|
? LoginResult.AUTH_SUCCESSFUL_2FA
|
||||||
: message ===
|
: message ===
|
||||||
|
@ -239,8 +236,7 @@ export async function fetchPOSTResponse(
|
||||||
|
|
||||||
// Prepare the parameters for the POST request
|
// Prepare the parameters for the POST request
|
||||||
const urlParams = new URLSearchParams();
|
const urlParams = new URLSearchParams();
|
||||||
for (const [key, value] of Object.entries(params))
|
for (const [key, value] of Object.entries(params)) urlParams.append(key, value);
|
||||||
urlParams.append(key, value);
|
|
||||||
|
|
||||||
// Shallow copy of the common configuration object
|
// Shallow copy of the common configuration object
|
||||||
commonConfig.jar = shared.session.cookieJar;
|
commonConfig.jar = shared.session.cookieJar;
|
||||||
|
|
|
@ -11,23 +11,13 @@ import luxon from "luxon";
|
||||||
// Modules from files
|
// Modules from files
|
||||||
import HandiWork from "../classes/handiwork/handiwork.js";
|
import HandiWork from "../classes/handiwork/handiwork.js";
|
||||||
import Thread from "../classes/mapping/thread.js";
|
import Thread from "../classes/mapping/thread.js";
|
||||||
import {
|
import { IBasic, TAuthor, TEngine, TExternalPlatform, TStatus } from "../interfaces.js";
|
||||||
IBasic,
|
|
||||||
TAuthor,
|
|
||||||
TEngine,
|
|
||||||
TExternalPlatform,
|
|
||||||
TStatus
|
|
||||||
} from "../interfaces.js";
|
|
||||||
import shared, { TPrefixDict } from "../shared.js";
|
import shared, { TPrefixDict } from "../shared.js";
|
||||||
import { ILink, IPostElement } from "./post-parse.js";
|
import { ILink, IPostElement } from "./post-parse.js";
|
||||||
|
|
||||||
export async function getHandiworkInformation<T extends IBasic>(
|
export async function getHandiworkInformation<T extends IBasic>(url: string): Promise<T>;
|
||||||
url: string
|
|
||||||
): Promise<T>;
|
|
||||||
|
|
||||||
export async function getHandiworkInformation<T extends IBasic>(
|
export async function getHandiworkInformation<T extends IBasic>(url: string): Promise<T>;
|
||||||
url: string
|
|
||||||
): Promise<T>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets information of a particular handiwork from its thread.
|
* Gets information of a particular handiwork from its thread.
|
||||||
|
@ -175,8 +165,7 @@ function fillWithPrefixes(hw: HandiWork, prefixes: string[]) {
|
||||||
const prefix = item.replace("[", "").replace("]", "");
|
const prefix = item.replace("[", "").replace("]", "");
|
||||||
|
|
||||||
// Check what the prefix indicates
|
// Check what the prefix indicates
|
||||||
if (stringInDict(prefix, shared.prefixes["engines"]))
|
if (stringInDict(prefix, shared.prefixes["engines"])) engine = prefix as TEngine;
|
||||||
engine = prefix as TEngine;
|
|
||||||
else if (stringInDict(prefix, shared.prefixes["statuses"]))
|
else if (stringInDict(prefix, shared.prefixes["statuses"]))
|
||||||
status = prefix as TStatus;
|
status = prefix as TStatus;
|
||||||
else if (stringInDict(prefix, fakeModDict)) mod = true;
|
else if (stringInDict(prefix, fakeModDict)) mod = true;
|
||||||
|
@ -212,10 +201,7 @@ function fillWithPostData(hw: HandiWork, elements: IPostElement[]) {
|
||||||
?.text?.split(",")
|
?.text?.split(",")
|
||||||
.map((s) => s.trim());
|
.map((s) => s.trim());
|
||||||
hw.version = getPostElementByName(elements, "version")?.text;
|
hw.version = getPostElementByName(elements, "version")?.text;
|
||||||
hw.installation = getPostElementByName(
|
hw.installation = getPostElementByName(elements, "installation")?.content.shift()?.text;
|
||||||
elements,
|
|
||||||
"installation"
|
|
||||||
)?.content.shift()?.text;
|
|
||||||
hw.pages = getPostElementByName(elements, "pages")?.text;
|
hw.pages = getPostElementByName(elements, "pages")?.text;
|
||||||
hw.resolution = getPostElementByName(elements, "resolution")
|
hw.resolution = getPostElementByName(elements, "resolution")
|
||||||
?.text?.split(",")
|
?.text?.split(",")
|
||||||
|
@ -240,8 +226,7 @@ function fillWithPostData(hw: HandiWork, elements: IPostElement[]) {
|
||||||
|
|
||||||
// Fill the dates
|
// Fill the dates
|
||||||
const releaseDate = getPostElementByName(elements, "release date")?.text;
|
const releaseDate = getPostElementByName(elements, "release date")?.text;
|
||||||
if (luxon.DateTime.fromISO(releaseDate).isValid)
|
if (luxon.DateTime.fromISO(releaseDate).isValid) hw.lastRelease = new Date(releaseDate);
|
||||||
hw.lastRelease = new Date(releaseDate);
|
|
||||||
|
|
||||||
//#region Convert the author
|
//#region Convert the author
|
||||||
const authorElement =
|
const authorElement =
|
||||||
|
|
|
@ -173,8 +173,7 @@ function reducePostElement(element: IPostElement): IPostElement {
|
||||||
const content = element.content[0] as IPostElement;
|
const content = element.content[0] as IPostElement;
|
||||||
const nullValues =
|
const nullValues =
|
||||||
(!element.name || !content.name) && (!element.text || !content.text);
|
(!element.name || !content.name) && (!element.text || !content.text);
|
||||||
const sameValues =
|
const sameValues = element.name === content.name || element.text === content.text;
|
||||||
element.name === content.name || element.text === content.text;
|
|
||||||
|
|
||||||
if (nullValues || sameValues) {
|
if (nullValues || sameValues) {
|
||||||
element.name = element.name || content.name;
|
element.name = element.name || content.name;
|
||||||
|
@ -245,10 +244,7 @@ function parseCheerioNode(
|
||||||
const childElement = parseCheerioNode($, el);
|
const childElement = parseCheerioNode($, el);
|
||||||
|
|
||||||
// If the children is valid (not empty) push it
|
// If the children is valid (not empty) push it
|
||||||
if (
|
if ((childElement.text || childElement.content.length !== 0) && !isTextNode(el)) {
|
||||||
(childElement.text || childElement.content.length !== 0) &&
|
|
||||||
!isTextNode(el)
|
|
||||||
) {
|
|
||||||
content.content.push(childElement);
|
content.content.push(childElement);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue