UNPKG

@uwu-codes/furaffinity-api

Version:
393 lines (392 loc) 17.5 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ParseMyWatchingList = exports.ParseWatchingList = exports.ParseAuthor = exports.ParseSubmission = exports.ParseSubmissionsPaging = exports.ParseBrowsePaging = exports.ParseSearchPaging = exports.ParseScrapsPaging = exports.ParseGalleryPaging = exports.ParseFigures = exports.ParseFigure = void 0; const cheerio_1 = __importDefault(require("cheerio")); const cloneDeep_1 = __importDefault(require("lodash/cloneDeep")); const Enums_1 = require("./Enums"); const _1 = require("."); const Request_1 = require("./Request"); /** * Convert author name to author id * @param name author name */ function convertNameToId(name) { return name.trim().replace('_', '').toLowerCase(); } /** * Get class names from element * @param element CheerioElement */ function classNames(element) { return element.attribs.class.split(' '); } function checkSystemMessage($) { // Check system message const noticeMessage = $('section.notice-message'); if (noticeMessage.length !== 0) { const systemMessage = noticeMessage[0].childNodes[1].childNodes[3].childNodes[0].nodeValue; throw new Error(systemMessage); } } /** * Parse result from figure element * @param figure CheerioElement */ function ParseFigure(figure, selector) { var _a, _b, _c, _d; const id = (_a = figure.attribs.id.split('-').pop()) !== null && _a !== void 0 ? _a : ''; const thumb = 'http:' + figure.childNodes[0].childNodes[0].childNodes[0].childNodes[0].attribs.src; const authorName = selector.find('figcaption p:last-child a').first().attr().title; const authorId = convertNameToId(authorName); return { type: Enums_1.SubmissionType[classNames(figure)[1].split('-').pop()], id, title: (_c = (_b = figure.childNodes[1].childNodes[0].childNodes[0].childNodes[0]) === null || _b === void 0 ? void 0 : _b.nodeValue) !== null && _c !== void 0 ? _c : '', url: `${Request_1.ENDPOINT}/view/${id}`, rating: Enums_1.Rating[(_d = classNames(figure)[0] .split('-') .pop()) === null || _d === void 0 ? void 0 : _d.replace(/^[a-z]/, ($1) => $1.toUpperCase())], thumb: { icon: thumb.replace(/@\d+?-/g, '@75-'), tiny: thumb.replace(/@\d+?-/g, '@150-'), small: thumb.replace(/@\d+?-/g, '@300-'), medium: thumb.replace(/@\d+?-/g, '@800-'), large: thumb.replace(/@\d+?-/g, '@1600-'), }, author: { id: authorId, url: `${Request_1.ENDPOINT}/user/${authorId}`, name: authorName, }, getSubmission: () => __awaiter(this, void 0, void 0, function* () { return yield _1.Submission(id); }), }; } exports.ParseFigure = ParseFigure; /** * Parse all figure's info from HTML * @param body HTML document */ function ParseFigures(body) { const $ = cheerio_1.default.load(body); const results = []; $('figure').each((index, figure) => { results.push(ParseFigure(figure, $(figure))); }); return results; } exports.ParseFigures = ParseFigures; function ParseGalleryPaging(body, results, perpage) { const $ = cheerio_1.default.load(body); const links = $('.submission-list .aligncenter:nth-child(1) div'); if ($(links[0]).find('form').length > 0) { results.prevLink = Request_1.ENDPOINT + $(links[0]).find('form').attr()['action']; const matchs = results.prevLink.match(/\/gallery\/(.+?)\/(\d+?)\/$/); if (matchs) { const id = matchs[1]; const page = Number.parseInt(matchs[2]); results.prev = () => _1.Gallery(id, page, perpage); } } if ($(links[2]).find('form').length > 0) { results.nextLink = Request_1.ENDPOINT + $(links[2]).find('form').attr()['action']; const matchs = results.nextLink.match(/\/gallery\/(.+?)\/(\d+?)\/$/); if (matchs) { const id = matchs[1]; const page = Number.parseInt(matchs[2]); results.next = () => _1.Gallery(id, page, perpage); } } return results; } exports.ParseGalleryPaging = ParseGalleryPaging; function ParseScrapsPaging(body, results, perpage) { const $ = cheerio_1.default.load(body); const links = $('.submission-list .aligncenter:nth-child(1) div'); if ($(links[0]).find('form').length > 0) { results.prevLink = Request_1.ENDPOINT + $(links[0]).find('form').attr()['action']; const matchs = results.prevLink.match(/\/scraps\/(.+?)\/(\d+?)\/$/); if (matchs) { const id = matchs[1]; const page = Number.parseInt(matchs[2]); results.prev = () => _1.Scraps(id, page, perpage); } } if ($(links[2]).find('form').length > 0) { results.nextLink = Request_1.ENDPOINT + $(links[2]).find('form').attr()['action']; const matchs = results.nextLink.match(/\/scraps\/(.+?)\/(\d+?)\/$/); if (matchs) { const id = matchs[1]; const page = Number.parseInt(matchs[2]); results.next = () => _1.Scraps(id, page, perpage); } } return results; } exports.ParseScrapsPaging = ParseScrapsPaging; function ParseSearchPaging(body, results, query, options) { const $ = cheerio_1.default.load(body); const links = $('#search-results .pagination button'); if (!classNames(links[0]).includes('disabled')) { const newOptions = cloneDeep_1.default(options || {}); newOptions.page = newOptions.page ? newOptions.page - 1 : 1; newOptions.prev = true; results.prev = () => _1.Search(query, newOptions); } if (!classNames(links[1]).includes('disabled')) { const newOptions = cloneDeep_1.default(options || {}); newOptions.page = newOptions.page ? newOptions.page + 1 : 2; newOptions.prev = false; results.next = () => _1.Search(query, newOptions); } return results; } exports.ParseSearchPaging = ParseSearchPaging; function ParseBrowsePaging(body, results, options) { const $ = cheerio_1.default.load(body); const links = $('.section-body .navigation:nth-child(1) div'); if ($(links[0]).find('form').length > 0) { results.prevLink = Request_1.ENDPOINT + $(links[0]).find('form').attr()['action']; const matchs = results.prevLink.match(/\/browse\/(\d+?)$/); if (matchs) { const page = Number.parseInt(matchs[1]); options = options !== null && options !== void 0 ? options : {}; options.page = page; results.prev = () => _1.Browse(options); } } if ($(links[2]).find('form').length > 0) { results.nextLink = Request_1.ENDPOINT + $(links[2]).find('form').attr()['action']; const matchs = results.nextLink.match(/\/browse\/(\d+?)$/); if (matchs) { const page = Number.parseInt(matchs[1]); options = options !== null && options !== void 0 ? options : {}; options.page = page; results.next = () => _1.Browse(options); } } return results; } exports.ParseBrowsePaging = ParseBrowsePaging; function ParseSubmissionsPaging(body, results) { const $ = cheerio_1.default.load(body); const links = $('.section-body .aligncenter:nth-child(1)'); if ($(links).find('a.more-half').length === 2) { results.prevLink = Request_1.ENDPOINT + $(links).find('a.more-half').first().attr()['href']; results.nextLink = Request_1.ENDPOINT + $(links).find('a.more-half').last().attr()['href']; } else if ($(links).find('a.more.prev').length === 1) { results.prevLink = Request_1.ENDPOINT + $(links).find('a.more.prev').first().attr()['href']; } else if ($(links).find('a.more').length === 1) { results.nextLink = Request_1.ENDPOINT + $(links).find('a.more').first().attr()['href']; } if (results.prevLink) { const matchs = results.prevLink.match(/\/submissions\/(.+?)~(.+?)@(\d+)\/$/); if (matchs) { const sort = matchs[1]; const startAt = matchs[2]; const perpage = matchs[3]; const options = { sort: sort, startAt: startAt, perpage: perpage, }; results.prev = () => _1.Submissions(options); } } if (results.nextLink) { const matchs = results.nextLink.match(/\/submissions\/(.+?)~(.+?)@(\d+)\/$/); if (matchs) { const sort = matchs[1]; const startAt = matchs[2]; const perpage = matchs[3]; const options = { sort: sort, startAt: startAt, perpage: perpage, }; results.next = () => _1.Submissions(options); } } return results; } exports.ParseSubmissionsPaging = ParseSubmissionsPaging; /** * Get submission's info * @param body HTML document * @param id Subumission id */ function ParseSubmission(body, id) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p; const $ = cheerio_1.default.load(body); checkSystemMessage($); // Get main nodes const main = $('#columnpage'); const sidebar = main.find('.submission-sidebar'); const content = main.find('.submission-content'); const stats = sidebar.find('.stats-container'); const info = sidebar.find('.info'); const tags = sidebar.find('.tags-row .tags a'); // buttons let downloadUrl = `http:${sidebar.find('.buttons .download a')[0].attribs.href}`; const favLink = `http://furaffinity.net${sidebar.find('.buttons .fav a')[0].attribs.href}`; // header const title = (_b = (_a = content .find('.submission-id-sub-container .submission-title p')[0] .childNodes[0].data) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : ''; const authorName = (_d = (_c = content.find('.submission-id-sub-container a strong')[0].childNodes[0].data) === null || _c === void 0 ? void 0 : _c.trim()) !== null && _d !== void 0 ? _d : ''; const authorId = convertNameToId(authorName); const posted = content.find('.submission-id-sub-container strong span')[0].attribs.title; const authorAvatar = `http:${content.find('.submission-id-avatar img')[0].attribs.src}`; const authorShinies = !!$('.shinies-promo'); // stats const rating = Enums_1.Rating[(_e = stats.find('.rating span')[0].childNodes[0].data) === null || _e === void 0 ? void 0 : _e.trim()]; const favorites = Number.parseInt((_g = (_f = stats.find('.favorites span')[0].childNodes[0].data) === null || _f === void 0 ? void 0 : _f.trim()) !== null && _g !== void 0 ? _g : ''); const comments = Number.parseInt((_j = (_h = stats.find('.comments span')[0].childNodes[0].data) === null || _h === void 0 ? void 0 : _h.trim()) !== null && _j !== void 0 ? _j : ''); const views = Number.parseInt((_l = (_k = stats.find('.views span')[0].childNodes[0].data) === null || _k === void 0 ? void 0 : _k.trim()) !== null && _l !== void 0 ? _l : ''); // info const category = Enums_1.Category[(_m = info.find('.category-name')[0].childNodes[0].data) === null || _m === void 0 ? void 0 : _m.trim()]; const species = Enums_1.Species[(_o = info[0].childNodes[3].childNodes[2].childNodes[0].data) === null || _o === void 0 ? void 0 : _o.trim()]; const gender = Enums_1.Gender[(_p = info[0].childNodes[5].childNodes[2].childNodes[0].data) === null || _p === void 0 ? void 0 : _p.trim()]; // fix url when category is story or poetry if (category === Enums_1.Category.Story || category === Enums_1.Category.Poetry) { downloadUrl = downloadUrl.replace('d.facdn.net/download/', 'd.facdn.net/'); } const previewUrl = content.find('.submission-area img').length > 0 ? `http:${content.find('.submission-area img')[0].attribs['data-preview-src']}` : undefined; return { id, url: `http://www.furaffinity.net/view/${id}`, title: title, posted: Date.parse(posted), favLink, rating: rating, author: { id: authorId, name: authorName, url: `http://www.furaffinity.net/user/${authorId}`, avatar: authorAvatar, shinies: authorShinies, }, content: { category, species, gender, }, stats: { favorites, comments, views, }, downloadUrl, previewUrl, keywords: tags .map((index, tag) => { var _a, _b; return (_b = (_a = tag.childNodes[0].data) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : ''; }) .get(), fave: () => __awaiter(this, void 0, void 0, function* () { yield Request_1.FaveSubmission(favLink); }), }; } exports.ParseSubmission = ParseSubmission; /** * Get author's info * @param body HTML document */ function ParseAuthor(body) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p; const $ = cheerio_1.default.load(body); checkSystemMessage($); const name = (_b = (_a = $('.userpage-flex-item.username span')[0].childNodes[0].data) === null || _a === void 0 ? void 0 : _a.trim().slice(1)) !== null && _b !== void 0 ? _b : ''; const id = convertNameToId(name); const url = `http://www.furaffinity.net/user/${id}`; const shinies = !!$('.userpage-layout-left-col-content > a:nth-child(4)'); const avatar = `https:${$('.user-nav-avatar')[0].attribs.src}`; const statsCells = $('.userpage-section-right .cell'); const views = (_d = (_c = statsCells[0].childNodes[2].data) === null || _c === void 0 ? void 0 : _c.trim()) !== null && _d !== void 0 ? _d : '0'; const submissions = (_f = (_e = statsCells[0].childNodes[6].data) === null || _e === void 0 ? void 0 : _e.trim()) !== null && _f !== void 0 ? _f : '0'; const favs = (_h = (_g = statsCells[0].childNodes[10].data) === null || _g === void 0 ? void 0 : _g.trim()) !== null && _h !== void 0 ? _h : '0'; const commentsEarned = (_k = (_j = statsCells[1].childNodes[2].data) === null || _j === void 0 ? void 0 : _j.trim()) !== null && _k !== void 0 ? _k : '0'; const commentsMade = (_m = (_l = statsCells[1].childNodes[6].data) === null || _l === void 0 ? void 0 : _l.trim()) !== null && _m !== void 0 ? _m : '0'; const journals = (_p = (_o = statsCells[1].childNodes[10].data) === null || _o === void 0 ? void 0 : _o.trim()) !== null && _p !== void 0 ? _p : '0'; return { id, name, url, avatar, shinies, stats: { views: Number.parseInt(views), submissions: Number.parseInt(submissions), favs: Number.parseInt(favs), commentsEarned: Number.parseInt(commentsEarned), commentsMade: Number.parseInt(commentsMade), journals: Number.parseInt(journals), }, }; } exports.ParseAuthor = ParseAuthor; /** * Get all Author's info from peer page of watching list * @param body HTML document */ function ParseWatchingList(body) { const $ = cheerio_1.default.load(body); checkSystemMessage($); return $('.watch-list-items a') .map((index, a) => { var _a, _b; const name = (_b = (_a = a.childNodes[0].data) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : ''; const id = convertNameToId(name); const url = `${Request_1.ENDPOINT}/user/${id}`; return { id, name, url, }; }) .get(); } exports.ParseWatchingList = ParseWatchingList; /** * Get all Author's info from peer page of watching list * @param body HTML document */ function ParseMyWatchingList(body) { const $ = cheerio_1.default.load(body); checkSystemMessage($); return $('.flex-item-watchlist') .map((index, div) => { var _a, _b; const avatar = `https:${$(div).find('img.avatar')[0].attribs.src}`; const name = (_b = (_a = $(div).find('.flex-item-watchlist-controls a strong')[0].childNodes[0].data) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : ''; const id = convertNameToId(name); const url = `${Request_1.ENDPOINT}/user/${id}`; return { id, name, url, avatar, }; }) .get(); } exports.ParseMyWatchingList = ParseMyWatchingList;