diff --git a/src/scripts/fetch-data/fetch-handiwork.ts b/src/scripts/fetch-data/fetch-handiwork.ts new file mode 100644 index 0000000..4bc7571 --- /dev/null +++ b/src/scripts/fetch-data/fetch-handiwork.ts @@ -0,0 +1,41 @@ +"use strict"; + +// Modules from file +import HandiworkSearchQuery from "../classes/query/handiwork-search-query"; +import LatestSearchQuery from "../classes/query/latest-search-query"; +import ThreadSearchQuery from "../classes/query/thread-search-query"; +import fetchLatestHandiworkURLs from "./fetch-latest.js"; +import fetchThreadHandiworkURLs from "./fetch-thread.js"; + +/** + * Gets the URLs of the handiworks that match the passed parameters. + * You *must* be logged. + * @param {LatestSearchQuery} query + * Query used for the search + * @param {Number} limit + * Maximum number of items to get. Default: 30 + * @returns {Promise} URLs of the handiworks + */ +export default async function fetchHandiworkURLs(query: HandiworkSearchQuery, limit: number = 30): Promise { + // Local variables + let urls: string[] = null; + const searchType = query.selectSearchType(); + + // Convert the query + if (searchType === "latest") { + // Cast the query + const castedQuery = query.cast(); + + // Fetch the urls + urls = await fetchLatestHandiworkURLs(castedQuery, limit); + } + else { + // Cast the query + const castedQuery = query.cast(); + + // Fetch the urls + urls = await fetchThreadHandiworkURLs(castedQuery, limit); + } + + return urls; +} \ No newline at end of file diff --git a/src/scripts/fetch-data/fetch-query.ts b/src/scripts/fetch-data/fetch-query.ts new file mode 100644 index 0000000..91e1fda --- /dev/null +++ b/src/scripts/fetch-data/fetch-query.ts @@ -0,0 +1,41 @@ +"use strict"; + +// Modules from files +import fetchHandiworkURLs from "./fetch-handiwork.js"; +import fetchLatestHandiworkURLs from "./fetch-latest.js"; +import fetchThreadHandiworkURLs from "./fetch-thread.js"; +import HandiworkSearchQuery from "../classes/query/handiwork-search-query.js"; +import LatestSearchQuery from "../classes/query/latest-search-query.js"; +import ThreadSearchQuery from "../classes/query/thread-search-query.js"; + +//#region Public methods +export default async function executeQuery(query: LatestSearchQuery, limit: number): Promise + +export default async function executeQuery(query: ThreadSearchQuery, limit: number): Promise + +export default async function executeQuery(query: HandiworkSearchQuery, limit: number): Promise + +/** + * @param query Query used for the search + * @param limit Maximum number of items to get. Default: 30 + * @returns URLs of the fetched games + */ +export default async function executeQuery(query: any, limit: number = 30): Promise { + // Local variables + const searchMap = { + "latest": fetchLatestHandiworkURLs, + "thread": fetchThreadHandiworkURLs, + "handiwork": fetchHandiworkURLs, + } + + // Find the key for the mapping dict + const key = query instanceof LatestSearchQuery ? + "latest" : + (query instanceof ThreadSearchQuery ? + "thread" : + "handiwork"); + + // Fetch and return the urls + return await searchMap[key](query, limit); +} +//#endregion \ No newline at end of file diff --git a/src/scripts/fetch-data/fetch-thread.ts b/src/scripts/fetch-data/fetch-thread.ts new file mode 100644 index 0000000..c203b80 --- /dev/null +++ b/src/scripts/fetch-data/fetch-thread.ts @@ -0,0 +1,75 @@ +"use strict"; + +// Public modules from npm +import cheerio from "cheerio"; + +// Modules from file +import { fetchHTML } from "../network-helper.js"; +import shared from "../shared.js"; +import { selectors as f95Selector } from "../constants/css-selector.js"; +import { urls as f95urls } from "../constants/url.js"; +import ThreadSearchQuery from "../classes/query/thread-search-query.js"; + +//#region Public methods +/** + * Gets the URLs of the handiwork' threads that match the passed parameters. + * You *must* be logged. + * @param {ThreadSearchQuery} query + * Query used for the search + * @param {number} limit + * Maximum number of items to get. Default: 30 + * @returns {Promise} URLs of the handiworks + */ +export default async function fetchThreadHandiworkURLs(query: ThreadSearchQuery, limit:number = 30): Promise { + // Get the query + const url = query.createURL().toString(); + + // Fetch the results from F95 and return the handiwork urls + return await fetchResultURLs(url, limit); +} + +//#endregion Public methods + +//#region Private methods +/** + * Gets the URLs of the threads resulting from the F95Zone search. + * @param {number} limit + * Maximum number of items to get. Default: 30 + * @return {Promise} List of URLs + */ +async function fetchResultURLs(url: string, limit: number = 30): Promise { + shared.logger.trace(`Fetching ${url}...`); + + // Fetch HTML and prepare Cheerio + const html = await fetchHTML(url); + const $ = cheerio.load(html); + + // Here we get all the DIV that are the body of the various query results + const results = $("body").find(f95Selector.GS_RESULT_BODY); + + // Than we extract the URLs + const urls = results.slice(0, limit).map((idx, el) => { + const elementSelector = $(el); + return extractLinkFromResult(elementSelector); + }).get(); + + return urls; +} + +/** + * Look for the URL to the thread referenced by the item. + * @param {cheerio.Cheerio} selector Element to search + * @returns {String} URL to thread + */ +function extractLinkFromResult(selector: cheerio.Cheerio): string { + shared.logger.trace("Extracting thread link from result..."); + + const partialLink = selector + .find(f95Selector.GS_RESULT_THREAD_TITLE) + .attr("href") + .trim(); + + // Compose and return the URL + return new URL(partialLink, f95urls.F95_BASE_URL).toString(); +} +//#endregion Private methods \ No newline at end of file