diff --git a/src/scripts/classes/mapping/platform-user.ts b/src/scripts/classes/mapping/platform-user.ts index 09edb42..e497cf5 100644 --- a/src/scripts/classes/mapping/platform-user.ts +++ b/src/scripts/classes/mapping/platform-user.ts @@ -13,6 +13,8 @@ import { DateTime } from "luxon"; import { urls } from "../../constants/url"; import { fetchHTML } from "../../network-helper"; import { GENERIC, MEMBER } from "../../constants/css-selector"; +import shared from "../../shared"; +import { UserNotLogged, USER_NOT_LOGGED } from "../errors"; /** * Represents a generic user registered on the platform. @@ -144,6 +146,9 @@ export default class PlatformUser { } public async fetch(): Promise { + // Check login + if (!shared.isLogged) throw new UserNotLogged(USER_NOT_LOGGED); + // Check ID if (!this.id && this.id < 1) throw new Error("Invalid user ID"); @@ -152,45 +157,51 @@ export default class PlatformUser { // Fetch the page const htmlResponse = await fetchHTML(url); - - if (htmlResponse.isSuccess()) { - // Prepare cheerio - const $ = cheerio.load(htmlResponse.value); - - // Check if the profile is private - this._private = - $(GENERIC.ERROR_BANNER)?.text().trim() === - "This member limits who may view their full profile."; - - if (!this._private) { - // Parse the elements - this._name = $(MEMBER.NAME).text(); - this._title = $(MEMBER.TITLE).text(); - this._banners = $(MEMBER.BANNERS) - .toArray() - .map((el, idx) => $(el).text().trim()) - .filter((el) => el); - this._avatar = $(MEMBER.AVATAR).attr("src"); - this._followed = $(MEMBER.FOLLOWED).text() === "Unfollow"; - this._ignored = $(MEMBER.IGNORED).text() === "Unignore"; - this._messages = parseInt($(MEMBER.MESSAGES).text(), 10); - this._reactionScore = parseInt($(MEMBER.REACTION_SCORE).text(), 10); - this._points = parseInt($(MEMBER.POINTS).text(), 10); - this._ratingsReceived = parseInt($(MEMBER.RATINGS_RECEIVED).text(), 10); - - // Parse date - const joined = $(MEMBER.JOINED)?.attr("datetime"); - if (DateTime.fromISO(joined).isValid) this._joined = new Date(joined); - - const lastSeen = $(MEMBER.LAST_SEEN)?.attr("datetime"); - if (DateTime.fromISO(lastSeen).isValid) this._joined = new Date(lastSeen); - - // Parse donation - const donation = $(MEMBER.AMOUNT_DONATED)?.text().replace("$", ""); - this._amountDonated = donation ? parseInt(donation, 10) : 0; - } - } else throw htmlResponse.value; + const result = htmlResponse.applyOnSuccess(this.elaborateResponse); + if (result.isFailure()) throw htmlResponse.value; } - //#endregion Public method + //#endregion Public methods + + //#region Private methods + + private elaborateResponse(html: string): void { + // Prepare cheerio + const $ = cheerio.load(html); + + // Check if the profile is private + this._private = + $(GENERIC.ERROR_BANNER)?.text().trim() === + "This member limits who may view their full profile."; + + if (!this._private) { + // Parse the elements + this._name = $(MEMBER.NAME).text(); + this._title = $(MEMBER.TITLE).text(); + this._banners = $(MEMBER.BANNERS) + .toArray() + .map((el, idx) => $(el).text().trim()) + .filter((el) => el); + this._avatar = $(MEMBER.AVATAR).attr("src"); + this._followed = $(MEMBER.FOLLOWED).text() === "Unfollow"; + this._ignored = $(MEMBER.IGNORED).text() === "Unignore"; + this._messages = parseInt($(MEMBER.MESSAGES).text(), 10); + this._reactionScore = parseInt($(MEMBER.REACTION_SCORE).text(), 10); + this._points = parseInt($(MEMBER.POINTS).text(), 10); + this._ratingsReceived = parseInt($(MEMBER.RATINGS_RECEIVED).text(), 10); + + // Parse date + const joined = $(MEMBER.JOINED)?.attr("datetime"); + if (DateTime.fromISO(joined).isValid) this._joined = new Date(joined); + + const lastSeen = $(MEMBER.LAST_SEEN)?.attr("datetime"); + if (DateTime.fromISO(lastSeen).isValid) this._joined = new Date(lastSeen); + + // Parse donation + const donation = $(MEMBER.AMOUNT_DONATED)?.text().replace("$", ""); + this._amountDonated = donation ? parseInt(donation, 10) : 0; + } + } + + //#endregion Private methods } diff --git a/src/scripts/classes/mapping/post.ts b/src/scripts/classes/mapping/post.ts index a630c0d..5f16abf 100644 --- a/src/scripts/classes/mapping/post.ts +++ b/src/scripts/classes/mapping/post.ts @@ -14,6 +14,8 @@ import { IPostElement, parseF95ThreadPost } from "../../scrape-data/post-parse"; import { POST, THREAD } from "../../constants/css-selector"; import { urls } from "../../constants/url"; import { fetchHTML } from "../../network-helper"; +import shared from "../../shared"; +import { UserNotLogged, USER_NOT_LOGGED } from "../errors"; /** * Represents a post published by a user on the F95Zone platform. @@ -95,6 +97,9 @@ export default class Post { * Gets the post data starting from its unique ID for the entire platform. */ public async fetch(): Promise { + // Check login + if (!shared.isLogged) throw new UserNotLogged(USER_NOT_LOGGED); + // Fetch HTML page containing the post const url = new URL(this.id.toString(), urls.POSTS).toString(); const htmlResponse = await fetchHTML(url); diff --git a/src/scripts/classes/mapping/thread.ts b/src/scripts/classes/mapping/thread.ts index a20740b..a87d177 100644 --- a/src/scripts/classes/mapping/thread.ts +++ b/src/scripts/classes/mapping/thread.ts @@ -20,10 +20,13 @@ import Shared from "../../shared"; import { GenericAxiosError, ParameterError, - UnexpectedResponseContentType + UnexpectedResponseContentType, + UserNotLogged, + USER_NOT_LOGGED } from "../errors"; import { Result } from "../result"; import { getJSONLD, TJsonLD } from "../../scrape-data/json-ld"; +import shared from "../../shared"; /** * Represents a generic F95Zone platform thread. @@ -237,6 +240,9 @@ export default class Thread { * Gets information about this thread. */ public async fetch(): Promise { + // Check login + if (!shared.isLogged) throw new UserNotLogged(USER_NOT_LOGGED); + // Prepare the url this._url = new URL(this.id.toString(), urls.THREADS).toString(); diff --git a/src/scripts/classes/mapping/user-profile.ts b/src/scripts/classes/mapping/user-profile.ts index 308e573..9fd8650 100644 --- a/src/scripts/classes/mapping/user-profile.ts +++ b/src/scripts/classes/mapping/user-profile.ts @@ -14,8 +14,14 @@ import PlatformUser from "./platform-user"; import { urls } from "../../constants/url"; import { GENERIC, WATCHED_THREAD } from "../../constants/css-selector"; import { fetchHTML } from "../../network-helper"; -import { GenericAxiosError, UnexpectedResponseContentType } from "../errors"; +import { + GenericAxiosError, + UnexpectedResponseContentType, + UserNotLogged, + USER_NOT_LOGGED +} from "../errors"; import { Result } from "../result"; +import shared from "../../shared"; // Interfaces interface IWatchedThread { @@ -88,6 +94,9 @@ export default class UserProfile extends PlatformUser { //#region Public methods public async fetch(): Promise { + // Check login + if (!shared.isLogged) throw new UserNotLogged(USER_NOT_LOGGED); + // First get the user ID and set it const id = await this.fetchUserID(); super.setID(id);