// Copyright (c) 2021 MillenniumEarl // // This software is released under the MIT License. // https://opensource.org/licenses/MIT "use strict"; // Public modules from npm import cheerio from "cheerio"; // Modules from file import PlatformUser from "./platform-user"; 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 { InvalidID, INVALID_POST_ID, UserNotLogged, USER_NOT_LOGGED } from "../errors"; import { ILazy } from "../../interfaces"; /** * Represents a post published by a user on the F95Zone platform. */ export default class Post implements ILazy { //#region Fields private _id: number; private _number: number; private _published: Date; private _lastEdit: Date; private _owner: PlatformUser; private _bookmarked: boolean; private _message: string; private _body: IPostElement[]; //#endregion Fields //#region Getters /** * Represents a post published by a user on the F95Zone platform. */ public get id(): number { return this._id; } /** * Unique ID of the post within the thread in which it is present. */ public get number(): number { return this._number; } /** * Date the post was first published. */ public get published(): Date { return this._published; } /** * Date the post was last modified. */ public get lastEdit(): Date { return this._lastEdit; } /** * User who owns the post. */ public get owner(): PlatformUser { return this._owner; } /** * Indicates whether the post has been bookmarked. */ public get bookmarked(): boolean { return this._bookmarked; } /** * Post message text. */ public get message(): string { return this._message; } /** * Set of the elements that make up the body of the post. */ public get body(): IPostElement[] { return this._body; } //#endregion Getters constructor(id: number) { this._id = id; } //#region Public methods /** * Gets the post data starting from its unique ID for the entire platform. */ public async fetch(): Promise<void> { // Check login if (!shared.isLogged) throw new UserNotLogged(USER_NOT_LOGGED); // Check ID if (!this.id || this.id < 1) throw new InvalidID(INVALID_POST_ID); // Fetch HTML page containing the post const url = new URL(this.id.toString(), urls.POSTS).toString(); const response = await fetchHTML(url); if (response.isSuccess()) await this.elaborateResponse(response.value); else throw response.value; } //#endregion Public methods //#region Private methods /** * Process the HTML code received as * an answer and gets the data contained in it. */ private async elaborateResponse(html: string) { // Load cheerio and find post const $ = cheerio.load(html); const post = $(THREAD.POSTS_IN_PAGE) .toArray() .find((el, idx) => { // Fetch the ID and check if it is what we are searching const sid: string = $(el).find(POST.ID).attr("id").replace("post-", ""); const id = parseInt(sid, 10); if (id === this.id) return el; }); // Finally parse the post await this.parsePost($, $(post)); } private async parsePost($: cheerio.Root, post: cheerio.Cheerio): Promise<void> { // Find post's ID const sid: string = post.find(POST.ID).attr("id").replace("post-", ""); this._id = parseInt(sid, 10); // Find post's number const sNumber: string = post.find(POST.NUMBER).text().replace("#", ""); this._number = parseInt(sNumber, 10); // Find post's publishing date const sPublishing: string = post.find(POST.PUBLISH_DATE).attr("datetime"); this._published = new Date(sPublishing); // Find post's last edit date const sLastEdit: string = post.find(POST.LAST_EDIT).attr("datetime"); this._lastEdit = new Date(sLastEdit); // Find post's owner const sOwnerID: string = post.find(POST.OWNER_ID).attr("data-user-id").trim(); this._owner = new PlatformUser(parseInt(sOwnerID, 10)); await this._owner.fetch(); // Find if the post is bookmarked this._bookmarked = post.find(POST.BOOKMARKED).length !== 0; // Find post's message this._message = post.find(POST.BODY).text(); // Parse post's body const body = post.find(POST.BODY); this._body = parseF95ThreadPost($, body); } //#endregion }