// ==UserScript==
// @name Furaffinity-Request-Helper
// @namespace Violentmonkey Scripts
// @grant none
// @version 1.1.0
// @author Midori Dragon
// @description Helper Library to simplify requests to Furaffinity
// @icon https://www.furaffinity.net/themes/beta/img/banners/fa_logo.png?v2
// @license MIT
// ==/UserScript==
// jshint esversion: 8
(() => {
"use strict";
class Semaphore {
constructor(maxConcurrency) {
this.maxConcurrency = maxConcurrency, this.currentConcurrency = 0, this.waitingQueue = [];
}
acquire() {
return new Promise(((resolve, _) => {
this.currentConcurrency < this.maxConcurrency ? (this.currentConcurrency++, resolve()) : this.waitingQueue.push(resolve);
}));
}
release() {
if (this.waitingQueue.length > 0) {
this.waitingQueue.shift()();
} else this.currentConcurrency--;
}
}
class PercentHelper {
constructor() {
throw new Error("The PercentHelper class is static and cannot be instantiated.");
}
static percentAll={};
static setPercentValue(id, value) {
return !!(id && value && PercentHelper.percentAll.hasOwnProperty(id)) && (PercentHelper.percentAll[id] = value,
!0);
}
static getPercentValue(id, decimalPlaces = 2) {
if (!id) return -1;
const percent = PercentHelper.percentAll[id];
return percent ? parseFloat(percent.toFixed(decimalPlaces)) : -1;
}
static createPercentValue(uniqueId) {
return uniqueId || (uniqueId = Date.now() + Math.random()), PercentHelper.percentAll[uniqueId] = 0,
uniqueId;
}
static deletePercentValue(id) {
PercentHelper.percentAll.hasOwnProperty(id) && delete PercentHelper.percentAll[id];
}
}
class WaitAndCallAction {
constructor(action, usePercent, delay) {
this.action = action, this.delay = delay, this.intervalId, this.usePercent = usePercent,
this._running = !1;
}
start() {
if (this.action && this.delay && !1 === this._running) return this._running = !0,
this.usePercent && PercentHelper.createPercentValue(this.intervalId.toString()),
this.intervalId = setInterval((() => {
this.usePercent ? this.action(PercentHelper.getPercentValue(this.intervalId.toString())) : this.action();
}), this.delay), this.intervalId;
}
stop() {
this._running && (this._running = !1, clearInterval(this.intervalId), this.usePercent && PercentHelper.deletePercentValue(this.intervalId.toString()));
}
static async callFunctionAsync(functionToCall, params, action, delay, usePercent) {
const waitAndCallAction = new WaitAndCallAction(action, usePercent, delay), percentId = waitAndCallAction.start();
usePercent && params.push(percentId);
const result = await functionToCall(...params);
return waitAndCallAction.stop(), result;
}
static callFunction(functionToCall, params, action, delay, usePercent) {
const waitAndCallAction = new WaitAndCallAction(action, usePercent, delay), percentId = waitAndCallAction.start();
usePercent && params.push(percentId);
const result = functionToCall(...params);
return waitAndCallAction.stop(), result;
}
}
class Logger {
constructor() {
throw new Error("The Logger class is static and cannot be instantiated.");
}
static logMessage(message) {
FuraffinityRequests.logLevel >= 3 && console.log(message);
}
static logWarning(message) {
FuraffinityRequests.logLevel >= 2 && console.warn(message);
}
static logError(message) {
FuraffinityRequests.logLevel >= 1 && console.error(message);
}
static setLogLevel(level) {
FuraffinityRequests.logLevel = level;
}
}
class IdArray {
constructor() {
throw new Error("The IdArray class is static and cannot be instantiated.");
}
static getTillId(collection, toId) {
const result = [];
for (const elem of Array.from(collection)) if (result.push(elem), elem.id.toString().replace("sid-", "") == toId) break;
return result;
}
static getSinceId(collection, fromId) {
const array = Array.from(collection);
array.reverse();
const result = [];
for (const elem of array) if (result.push(elem), elem.id.toString().replace("sid-", "") == fromId) break;
return result.reverse(), result;
}
static getBetweenIds(collection, fromId, toId) {
const array = Array.from(collection);
let startIndex = -1, endIndex = -1;
for (let i = 0; i < array.length && (array[i].id.toString().replace("sid-", "") == fromId && (startIndex = i),
array[i].id.toString().replace("sid-", "") == toId && (endIndex = i), -1 == startIndex || -1 == endIndex); i++) ;
if (-1 == startIndex && -1 == endIndex) return array;
-1 == startIndex && (startIndex = 0), -1 == endIndex && (endIndex = array.length - 1);
const result = [];
for (let i = startIndex; i <= endIndex; i++) result.push(array[i]);
return result;
}
static containsId(collection, id) {
for (const elem of Array.from(collection)) if (elem.id.toString().replace("sid-", "") == id) return !0;
return !1;
}
}
class Scraps {
constructor(semaphore) {
this.semaphore = semaphore;
}
static get hardLink() {
return FuraffinityRequests.getUrl() + "/scraps/";
}
async getFiguresBetweenIds(username, fromId, toId, action, delay = 100) {
return fromId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresTillId, [ username, toId, null, "scraps", this.semaphore ], action, delay) : toId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresSinceId, [ username, fromId, null, "scraps", this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresBetweenIds, [ username, fromId, toId, null, null, "scraps", this.semaphore ], action, delay, !0);
}
async getFiguresBetweenIdsBetweenPages(username, fromId, toId, fromPageNumber, toPageNumber, action, delay = 100) {
return fromId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresTillId, [ username, toId, fromPageNumber, "scraps", this.semaphore ], action, delay) : toId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresSinceId, [ username, fromId, toPageNumber, "scraps", this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresBetweenIds, [ username, fromId, toId, fromPageNumber, toPageNumber, "scraps", this.semaphore ], action, delay, !0);
}
async getFiguresBetweenPages(username, fromPageNumber, toPageNumber, action, delay = 100) {
return fromPageNumber <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresTillPage, [ username, toPageNumber, "scraps", this.semaphore ], action, delay, !0) : toPageNumber <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresSincePage, [ username, fromPageNumber, "scraps", this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresBetweenPages, [ username, fromPageNumber, toPageNumber, "scraps", this.semaphore ], action, delay, !0);
}
async getFigures(username, pageNumber, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFigures, [ username, null, pageNumber, "scraps", this.semaphore ], action, delay);
}
async getPage(username, pageNumber, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(Page.getGalleryPage, [ username, null, pageNumber, "scraps", this.semaphore ], action, delay);
}
}
class Favorites {
constructor(semaphore) {
this.semaphore = semaphore;
}
static get hardLink() {
return FuraffinityRequests.getUrl() + "/favorites/";
}
async getFiguresBetweenIds(username, fromId, toId, action, delay = 100) {
return fromId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresTillId, [ username, toId, null, "favorites", this.semaphore ], action, delay) : toId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresSinceId, [ username, fromId, null, "favorites", this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresBetweenIds, [ username, fromId, toId, null, null, "favorites", this.semaphore ], action, delay, !0);
}
async getFiguresBetweenIdsBetweenPages(username, fromId, toId, fromPageNumber, toPageNumber, action, delay = 100) {
return fromId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresTillId, [ username, toId, fromPageNumber, "favorites", this.semaphore ], action, delay) : toId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresSinceId, [ username, fromId, toPageNumber, "favorites", this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresBetweenIds, [ username, fromId, toId, fromPageNumber, toPageNumber, "favorites", this.semaphore ], action, delay, !0);
}
async getFiguresBetweenPages(username, fromPageNumber, toPageNumber, action, delay = 100) {
return fromPageNumber <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresTillPage, [ username, toPageNumber, "favorites", this.semaphore ], action, delay, !0) : toPageNumber <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresSincePage, [ username, fromPageNumber, "favorites", this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresBetweenPages, [ username, fromPageNumber, toPageNumber, "favorites", this.semaphore ], action, delay, !0);
}
async getFigures(username, pageNumber, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFigures, [ username, null, pageNumber, "favorites", this.semaphore ], action, delay);
}
async getPage(username, pageNumber, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(Page.getGalleryPage, [ username, null, pageNumber, "favorites", this.semaphore ], action, delay);
}
}
class Journals {
constructor(semaphore) {
this.semaphore = semaphore;
}
static get hardLink() {
return FuraffinityRequests.getUrl() + "/journals/";
}
async getFiguresBetweenIds(username, fromId, toId, action, delay = 100) {
return fromId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getJournalsSectionsTillId, [ username, toId, null, this.semaphore ], action, delay) : toId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getJournalsSectionsSinceId, [ username, fromId, null, this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getJournalsSectionsBetweenIds, [ username, fromId, toId, null, null, this.semaphore ], action, delay);
}
async getFiguresBetweenIdsBetweenPages(username, fromId, toId, fromPageNumber, toPageNumber, action, delay = 100) {
return fromId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getJournalsSectionsTillId, [ username, toId, fromPageNumber, this.semaphore ], action, delay) : toId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getJournalsSectionsSinceId, [ username, fromId, toPageNumber, this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getJournalsSectionsBetweenIds, [ username, fromId, toId, fromPageNumber, toPageNumber, this.semaphore ], action, delay);
}
async getSectionsBetweenPages(username, fromPageNumber, toPageNumber, action, delay = 100) {
return fromPageNumber <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getJournalsSectionsTillPage, [ username, toPageNumber, this.semaphore ], action, delay, !0) : toPageNumber <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getJournalsSectionsSincePage, [ username, fromPageNumber, this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getJournalsSectionsBetweenPages, [ username, fromPageNumber, toPageNumber, this.semaphore ], action, delay, !0);
}
async getSections(username, pageNumber, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(GalleryRequests.getJournalsSections, [ username, pageNumber, this.semaphore ], action, delay);
}
async getPage(username, pageNumber, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(Page.getJournalsPage, [ username, pageNumber, this.semaphore ], action, delay);
}
}
class Search {
constructor(semaphore) {
this.semaphore = semaphore;
}
static get hardLink() {
return FuraffinityRequests.getUrl() + "/search/";
}
get newSearchOptions() {
return new SearchOptions;
}
get SearchOptions() {
return SearchOptions;
}
async getFiguresBetweenIds(fromId, toId, searchOptions, action, delay = 100) {
return fromId <= 0 ? await WaitAndCallAction.callFunctionAsync(SearchRequests.getSearchFiguresTillId, [ toId, null, searchOptions, this.semaphore ], action, delay) : toId <= 0 ? await WaitAndCallAction.callFunctionAsync(SearchRequests.getSearchFiguresSinceId, [ fromId, null, searchOptions, this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(SearchRequests.getSearchFiguresBetweenIds, [ fromId, toId, null, null, searchOptions, this.semaphore ], action, delay, !0);
}
async getFiguresBetweenIdsBetweenPages(fromId, toId, fromPageNumber, toPageNumber, searchOptions, action, delay = 100) {
return fromId <= 0 ? await WaitAndCallAction.callFunctionAsync(SearchRequests.getSearchFiguresTillId, [ toId, fromPageNumber, searchOptions, this.semaphore ], action, delay) : toId <= 0 ? await WaitAndCallAction.callFunctionAsync(SearchRequests.getSearchFiguresSinceId, [ fromId, toPageNumber, searchOptions, this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(SearchRequests.getSearchFiguresBetweenIds, [ fromId, toId, fromPageNumber, toPageNumber, searchOptions, this.semaphore ], action, delay, !0);
}
async getFiguresBetweenPages(fromPageNumber, toPageNumber, searchOptions, action, delay = 100) {
return fromPageNumber <= 0 ? await WaitAndCallAction.callFunctionAsync(SearchRequests.getSearchFiguresTillPage, [ toPageNumber, searchOptions, this.semaphore ], action, delay, !0) : toPageNumber <= 0 ? await WaitAndCallAction.callFunctionAsync(SearchRequests.getSearchFiguresSincePage, [ fromPageNumber, searchOptions, this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(SearchRequests.getSearchFiguresBetweenPages, [ fromPageNumber, toPageNumber, searchOptions, this.semaphore ], action, delay, !0);
}
async getFigures(pageNumber, searchOptions, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(SearchRequests.getSearchFigures, [ pageNumber, searchOptions, this.semaphore ], action, delay);
}
async getPage(pageNumber, searchOptions, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(Page.getSearchPage, [ pageNumber, searchOptions, this.semaphore ], action, delay);
}
}
class SearchOptions {
constructor() {
this.input = "", this.orderBy = SearchOptions.orderBy.relevancy, this.orderDirection = SearchOptions.orderDirection.descending,
this.range = SearchOptions.range.alltime, this.rangeFrom = null, this.rangeTo = null,
this.ratingGeneral = !0, this.ratingMature = !0, this.ratingAdult = !0, this.typeArt = !0,
this.typeMusic = !0, this.typeFlash = !0, this.typeStory = !0, this.typePhotos = !0,
this.typePoetry = !0, this.matching = SearchOptions.matching.all;
}
static get orderBy() {
return {
relevancy: "relevancy",
date: "date",
popularity: "popularity"
};
}
static get orderDirection() {
return {
ascending: "asc",
descending: "desc"
};
}
static get range() {
return {
"1day": "1day",
"3days": "3days",
"7days": "7days",
"30days": "30days",
"90days": "90days",
"1year": "1year",
"3years": "3years",
"5years": "5years",
alltime: "all",
manual: "manual"
};
}
static get matching() {
return {
all: "all",
any: "any",
extended: "extended"
};
}
}
class SearchRequests {
constructor(semaphore) {
this.semaphore = semaphore, this.Browse = new Browse(this.semaphore), this.Search = new Search(this.semaphore);
}
static async getBrowseFiguresTillId(toId, fromPage, browseOptions, semaphore) {
if (!toId) return Logger.logError("No toId given"), null;
let allFigures = [], running = !0, i = 1;
for (fromPage && fromPage >= 1 && (i = fromPage); running; ) {
const figures = await SearchRequests.getBrowseFigures(i, browseOptions, semaphore);
let currFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), null == currFigureId ? running = !1 : IdArray.containsId(figures, toId) ? (allFigures.push(IdArray.getTillId(figures, toId)),
running = !1) : (allFigures.push(figures), i++);
}
return 0 === allFigures.length ? null : allFigures;
}
static async getBrowseFiguresSinceId(fromId, toPage, browseOptions, semaphore) {
if (!fromId) return Logger.logError("No fromId given"), null;
let lastFigureId, running = !0, i = 1;
for (;running; ) {
if (toPage && toPage >= 1 && i == toPage) {
running = !1;
break;
}
const figures = await SearchRequests.getBrowseFigures(i, browseOptions, semaphore);
let currFigureId = lastFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), currFigureId == lastFigureId || IdArray.containsId(figures, fromId) ? running = !1 : i++;
}
let allFigures = [];
for (lastFigureId = null, running = !0; running; ) {
const figures = await SearchRequests.getBrowseFigures(i, browseOptions, semaphore);
let currFigureId = lastFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), currFigureId == lastFigureId ? running = !1 : (allFigures.push(IdArray.getSinceId(figures, fromId)),
i++);
}
return 0 === allFigures.length ? null : allFigures;
}
static async getBrowseFiguresBetweenIds(fromId, toId, fromPage, toPage, browseOptions, semaphore, percentId) {
if (!fromId) return Logger.logError("No fromId given"), null;
if (!toId) return Logger.logError("No toId given"), null;
let lastFigureId;
(!fromPage || fromPage <= 0 || !toPage || toPage <= 1) && (Logger.logWarning("No fromPage or toPage given. Percentages can not be calculated."),
percentId = null);
let running = !0, i = 1;
for (fromPage && fromPage >= 1 && (i = fromPage); running; ) {
const figures = await SearchRequests.getBrowseFigures(i, browseOptions, semaphore);
let currFigureId = lastFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), currFigureId == lastFigureId || IdArray.containsId(figures, fromId) ? running = !1 : i++;
}
let allFigures = [];
for (lastFigureId = null, running = !0; running; ) {
if (toPage && toPage >= 1 && i == toPage) {
running = !1;
break;
}
const figures = await SearchRequests.getBrowseFigures(i, browseOptions, semaphore);
let currFigureId = lastFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), currFigureId == lastFigureId ? running = !1 : IdArray.containsId(figures, toId) ? (allFigures.push(IdArray.getBetweenIds(figures, fromId, toId)),
running = !1) : (allFigures.push(figures), i++);
}
if (percentId) {
const progress = 1 / toPage * 100;
PercentHelper.setPercentValue(percentId, progress);
}
return 0 === allFigures.length ? null : allFigures;
}
static async getBrowseFiguresTillPage(toPageNumber, browseOptions, semaphore, percentId) {
if (!toPageNumber) return Logger.logError("No toPageNumber given"), null;
if (toPageNumber <= 0) return Logger.logError("toPageNumber must be greater than 0"),
null;
let allFigures = [], completedPages = 0;
for (let i = 1; i <= toPageNumber; i++) {
const figures = await SearchRequests.getBrowseFigures(i, browseOptions, semaphore);
if (figures && 0 !== figures.length && allFigures.push(figures), completedPages++,
percentId) {
const progress = completedPages / toPageNumber * 100;
PercentHelper.setPercentValue(percentId, progress);
}
}
return 0 === allFigures.length ? null : allFigures;
}
static async getBrowseFiguresSincePage(fromPageNumber, browseOptions, semaphore) {
if (!fromPageNumber) return Logger.logError("No fromPageNumber given"), null;
if (fromPageNumber <= 0) return Logger.logError("fromPageNumber must be greater than 0"),
null;
let allFigures = [], running = !0, i = fromPageNumber;
for (;running; ) {
const figures = await SearchRequests.getBrowseFigures(i, browseOptions, semaphore);
let currFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), null == currFigureId ? running = !1 : (allFigures.push(figures),
i++);
}
return 0 === allFigures.length ? null : allFigures;
}
static async getBrowseFiguresBetweenPages(fromPageNumber, toPageNumber, browseOptions, semaphore, percentId) {
if (!fromPageNumber) return Logger.logError("No fromPageNumber given"), null;
if (fromPageNumber <= 0) return Logger.logError("fromPageNumber must be greater than 0"),
null;
if (!toPageNumber) return Logger.logError("No toPageNumber given"), null;
if (toPageNumber <= 0) return Logger.logError("toPageNumber must be greater than 0"),
null;
let allFigures = [];
const direction = fromPageNumber < toPageNumber ? 1 : -1, totalPages = Math.abs(toPageNumber - fromPageNumber) + 1;
let completedPages = 0;
for (let i = fromPageNumber; i <= toPageNumber; i += direction) {
const figures = await SearchRequests.getBrowseFigures(i, browseOptions, semaphore);
if (figures && 0 !== figures.length && allFigures.push(figures), completedPages++,
percentId) {
const progress = completedPages / totalPages * 100;
PercentHelper.setPercentValue(percentId, progress);
}
}
return 0 === allFigures.length ? null : allFigures;
}
static async getBrowseFigures(pageNumber, browseOptions, semaphore) {
const galleryDoc = await Page.getBrowsePage(pageNumber, browseOptions, semaphore);
if (!galleryDoc || !(galleryDoc instanceof Document) || galleryDoc.getElementById("no-images")) return Logger.logMessage(`No images found at browse on page "${pageNumber}".`),
null;
const figures = galleryDoc.getElementsByTagName("figure");
return figures && 0 !== figures.length ? figures : (Logger.logMessage(`No figures found at browse on page "${pageNumber}".`),
null);
}
static async getSearchFiguresTillId(toId, fromPage, searchOptions, semaphore) {
if (!toId) return Logger.logError("No toId given"), null;
let allFigures = [], running = !0, i = 1;
for (fromPage && fromPage >= 1 && (i = fromPage); running; ) {
const figures = await SearchRequests.getSearchFigures(i, searchOptions, semaphore);
let currFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), null == currFigureId ? running = !1 : IdArray.containsId(figures, toId) ? (allFigures.push(IdArray.getTillId(figures, toId)),
running = !1) : (allFigures.push(figures), i++);
}
return 0 === allFigures.length ? null : allFigures;
}
static async getSearchFiguresSinceId(fromId, toPage, searchOptions, semaphore) {
if (!fromId) return Logger.logError("No fromId given"), null;
let lastFigureId, running = !0, i = 1;
for (;running; ) {
if (toPage && toPage >= 1 && i == toPage) {
running = !1;
break;
}
const figures = await SearchRequests.getSearchFigures(i, searchOptions, semaphore);
let currFigureId = lastFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), currFigureId == lastFigureId || IdArray.containsId(figures, fromId) ? running = !1 : i++;
}
let allFigures = [];
for (lastFigureId = null, running = !0; running; ) {
const figures = await SearchRequests.getSearchFigures(i, searchOptions, semaphore);
let currFigureId = lastFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), currFigureId == lastFigureId ? running = !1 : (allFigures.push(IdArray.getSinceId(figures, fromId)),
i++);
}
return 0 === allFigures.length ? null : allFigures;
}
static async getSearchFiguresBetweenIds(fromId, toId, fromPage, toPage, searchOptions, semaphore, percentId) {
if (!fromId) return Logger.logError("No fromId given"), null;
if (!toId) return Logger.logError("No toId given"), null;
let lastFigureId;
(!fromPage || fromPage <= 0 || !toPage || toPage <= 1) && (Logger.logWarning("No fromPage or toPage given. Percentages can not be calculated."),
percentId = null);
let running = !0, i = 1;
for (fromPage && fromPage >= 1 && (i = fromPage); running; ) {
const figures = await SearchRequests.getSearchFigures(i, searchOptions, semaphore);
let currFigureId = lastFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), currFigureId == lastFigureId || IdArray.containsId(figures, fromId) ? running = !1 : i++;
}
let allFigures = [];
for (lastFigureId = null, running = !0; running; ) {
if (toPage && toPage >= 1 && i == toPage) {
running = !1;
break;
}
const figures = await SearchRequests.getSearchFigures(i, searchOptions, semaphore);
let currFigureId = lastFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), currFigureId == lastFigureId ? running = !1 : IdArray.containsId(figures, toId) ? (allFigures.push(IdArray.getBetweenIds(figures, fromId, toId)),
running = !1) : (allFigures.push(figures), i++);
}
if (percentId) {
const progress = 1 / toPage * 100;
PercentHelper.setPercentValue(percentId, progress);
}
return 0 === allFigures.length ? null : allFigures;
}
static async getSearchFiguresTillPage(toPageNumber, searchOptions, semaphore, percentId) {
if (!toPageNumber) return Logger.logError("No toPageNumber given"), null;
if (toPageNumber <= 0) return Logger.logError("toPageNumber must be greater than 0"),
null;
let allFigures = [], completedPages = 0;
for (let i = 1; i <= toPageNumber; i++) {
const figures = await SearchRequests.getSearchFigures(i, searchOptions, semaphore);
if (figures && 0 !== figures.length && allFigures.push(figures), completedPages++,
percentId) {
const progress = completedPages / toPageNumber * 100;
PercentHelper.setPercentValue(percentId, progress);
}
}
return 0 === allFigures.length ? null : allFigures;
}
static async getSearchFiguresSincePage(fromPageNumber, searchOptions, semaphore) {
if (!fromPageNumber) return Logger.logError("No fromPageNumber given"), null;
if (fromPageNumber <= 0) return Logger.logError("fromPageNumber must be greater than 0"),
null;
let allFigures = [], running = !0, i = fromPageNumber;
for (;running; ) {
const figures = await SearchRequests.getSearchFigures(i, searchOptions, semaphore);
let currFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), null == currFigureId ? running = !1 : (allFigures.push(figures),
i++);
}
return 0 === allFigures.length ? null : allFigures;
}
static async getSearchFiguresBetweenPages(fromPageNumber, toPageNumber, searchOptions, semaphore, percentId) {
if (!fromPageNumber) return Logger.logError("No fromPageNumber given"), null;
if (fromPageNumber <= 0) return Logger.logError("fromPageNumber must be greater than 0"),
null;
if (!toPageNumber) return Logger.logError("No toPageNumber given"), null;
if (toPageNumber <= 0) return Logger.logError("toPageNumber must be greater than 0"),
null;
let allFigures = [];
const direction = fromPageNumber < toPageNumber ? 1 : -1, totalPages = Math.abs(toPageNumber - fromPageNumber) + 1;
let completedPages = 0;
for (let i = fromPageNumber; i <= toPageNumber; i += direction) {
const figures = await SearchRequests.getSearchFigures(i, searchOptions, semaphore);
if (figures && 0 !== figures.length && allFigures.push(figures), completedPages++,
percentId) {
const progress = completedPages / totalPages * 100;
PercentHelper.setPercentValue(percentId, progress);
}
}
return 0 === allFigures.length ? null : allFigures;
}
static async getSearchFigures(pageNumber, searchOptions, semaphore) {
const galleryDoc = await Page.getSearchPage(pageNumber, searchOptions, semaphore);
if (!galleryDoc || !(galleryDoc instanceof Document) || galleryDoc.getElementById("no-images")) return Logger.logMessage(`No images found at search on page "${pageNumber}".`),
null;
const figures = galleryDoc.getElementsByTagName("figure");
return figures && 0 !== figures.length ? figures : (Logger.logMessage(`No figures found at search on page "${pageNumber}".`),
null);
}
}
class Browse {
constructor(semaphore) {
this.semaphore = semaphore;
}
static get hardLink() {
return FuraffinityRequests.getUrl() + "/browse/";
}
get newBrowseOptions() {
return new BrowseOptions;
}
get BrowseOptions() {
return BrowseOptions;
}
async getFiguresBetweenIds(fromId, toId, browseOptions, action, delay = 100) {
return fromId <= 0 ? await WaitAndCallAction.callFunctionAsync(SearchRequests.getBrowseFiguresTillId, [ toId, null, browseOptions, this.semaphore ], action, delay) : toId <= 0 ? await WaitAndCallAction.callFunctionAsync(SearchRequests.getBrowseFiguresSinceId, [ fromId, null, browseOptions, this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(SearchRequests.getBrowseFiguresBetweenIds, [ fromId, toId, null, null, browseOptions, this.semaphore ], action, delay, !0);
}
async getFiguresBetweenIdsBetweenPages(fromId, toId, fromPageNumber, toPageNumber, browseOptions, action, delay = 100) {
return fromId <= 0 ? await WaitAndCallAction.callFunctionAsync(SearchRequests.getBrowseFiguresTillId, [ toId, fromPageNumber, browseOptions, this.semaphore ], action, delay) : toId <= 0 ? await WaitAndCallAction.callFunctionAsync(SearchRequests.getBrowseFiguresSinceId, [ fromId, toPageNumber, browseOptions, this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(SearchRequests.getBrowseFiguresBetweenIds, [ fromId, toId, fromPageNumber, toPageNumber, browseOptions, this.semaphore ], action, delay, !0);
}
async getFiguresBetweenPages(fromPageNumber, toPageNumber, browseOptions, action, delay = 100) {
return fromPageNumber <= 0 ? await WaitAndCallAction.callFunctionAsync(SearchRequests.getBrowseFiguresTillPage, [ toPageNumber, browseOptions, this.semaphore ], action, delay, !0) : toPageNumber <= 0 ? await WaitAndCallAction.callFunctionAsync(SearchRequests.getBrowseFiguresSincePage, [ fromPageNumber, browseOptions, this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(SearchRequests.getBrowseFiguresBetweenPages, [ fromPageNumber, toPageNumber, browseOptions, this.semaphore ], action, delay, !0);
}
async getFigures(pageNumber, browseOptions, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(SearchRequests.getBrowseFigures, [ pageNumber, browseOptions, this.semaphore ], action, delay);
}
async getPage(pageNumber, browseOptions, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(Page.getBrowsePage, [ pageNumber, browseOptions, this.semaphore ], action, delay);
}
}
class BrowseOptions {
constructor() {
this.category = BrowseOptions.category.all, this.type = BrowseOptions.type.all,
this.species = BrowseOptions.species.any, this.gender = BrowseOptions.gender.any,
this.results = BrowseOptions.results[72], this.ratingGeneral = !0, this.ratingMature = !0,
this.ratingAdult = !0;
}
static get category() {
return {
all: 1,
"artwork-digital": 2,
"artwork-traditional": 3,
"cel-shading": 4,
crafting: 5,
designs: 6,
flash: 7,
fursuiting: 8,
icons: 9,
mosaics: 10,
photography: 11,
"food-recipes": 32,
sculpting: 12,
story: 13,
poetry: 14,
prose: 15,
music: 16,
podcasts: 17,
skins: 18,
handhelds: 19,
resources: 20,
adoptables: 21,
auctions: 22,
contests: 23,
"current-events": 24,
desktops: 25,
stockart: 26,
screenshots: 27,
scraps: 28,
wallpaper: 29,
"ych-sale": 30,
other: 31
};
}
static get type() {
return {
all: 1,
abstract: 2,
"animal-related-non-anthro": 3,
anime: 4,
comics: 5,
doodle: 6,
fanart: 7,
fantasy: 8,
human: 9,
portraits: 10,
scenery: 11,
"still-life": 12,
tutorials: 13,
miscellaneous: 14,
"baby-fur": 101,
bondage: 102,
digimon: 103,
"fat-furs": 104,
"fetish-other": 105,
fursuit: 106,
gore: 119,
hyper: 107,
hypnosis: 121,
inflation: 108,
micro: 109,
muscle: 110,
"my-little-pony": 111,
paw: 112,
pokemon: 113,
pregnancy: 114,
sonic: 115,
transformation: 116,
"tf-tg": 120,
vore: 117,
"water-sports": 118,
"general-furry-art": 100,
techno: 201,
trance: 202,
house: 203,
"90s": 204,
"80s": 205,
"70s": 206,
"60s": 207,
"pre-60s": 208,
classical: 209,
"game-music": 210,
rock: 211,
pop: 212,
rap: 213,
industrial: 214,
"other-music": 200
};
}
static get species() {
return {
any: 1,
"airborne-vehicle": 10001,
alien: 5001,
amphibian: 1e3,
aquatic: 2e3,
avian: 3e3,
bear: 6002,
bovine: 6007,
canine: 6017,
cervine: 6018,
dog: 6010,
dragon: 4e3,
equine: 10009,
exotic: 5e3,
feline: 6030,
fox: 6075,
slime: 10007,
"hybrid-species": 10002,
inanimate: 10006,
insect: 8003,
"land-vehicle": 10003,
mammal: 6e3,
marsupial: 6042,
mustelid: 6051,
plant: 10008,
primate: 6058,
reptilian: 7e3,
robot: 10004,
rodent: 6067,
"sea-vehicle": 10005,
taur: 5025,
vulpine: 6015,
"original-species": 11014,
character: 11015,
aeromorph: 11001,
"angel-dragon": 11002,
avali: 11012,
chakat: 5003,
citra: 5005,
crux: 5006,
dracat: 5009,
dutch: 11003,
felkin: 11011,
ferrin: 11004,
jogauni: 11005,
langurhali: 5014,
nevrean: 11006,
protogen: 11007,
rexouium: 11016,
sergal: 5021,
synx: 11010,
wickerbeast: 11013,
yinglet: 11009,
zorgoia: 11008,
angel: 12001,
centaur: 12002,
cerberus: 12003,
"shape-shifter": 12038,
chimera: 12004,
chupacabra: 12005,
cockatrice: 12006,
daemon: 5007,
demon: 12007,
"displacer-beast": 12008,
dragonborn: 12009,
drow: 12010,
dwarf: 12011,
"eastern-dragon": 4001,
elf: 5011,
gargoyle: 5012,
goblin: 12012,
golem: 12013,
gryphon: 3007,
harpy: 12014,
hellhound: 12015,
hippogriff: 12016,
hobbit: 12017,
hydra: 4002,
imp: 12018,
incubus: 12019,
jackalope: 12020,
kirin: 12021,
kitsune: 12022,
kobold: 12023,
lamia: 12024,
manticore: 12025,
minotaur: 12026,
naga: 5016,
nephilim: 12027,
orc: 5018,
pegasus: 12028,
peryton: 12029,
phoenix: 3010,
sasquatch: 12030,
satyr: 5020,
sphinx: 12031,
succubus: 12032,
tiefling: 12033,
troll: 12034,
unicorn: 5023,
"water-dragon": 12035,
werewolf: 12036,
"western-dragon": 4004,
wyvern: 4005,
yokai: 12037,
alicorn: 13001,
argonian: 5002,
asari: 13002,
bangaa: 13003,
"bubble-dragon": 13004,
burmecian: 13005,
charr: 13006,
chiss: 13007,
chocobo: 5004,
deathclaw: 13008,
digimon: 5008,
draenei: 5010,
drell: 13009,
elcor: 13010,
ewok: 13011,
hanar: 13012,
hrothgar: 13013,
iksar: 5013,
kaiju: 5015,
kelpie: 13041,
kemonomimi: 13014,
khajiit: 13015,
koopa: 13016,
krogan: 13017,
lombax: 13018,
mimiga: 13019,
mobian: 13020,
moogle: 5017,
neopet: 13021,
"nu-mou": 13022,
pokemon: 5019,
"pony-mlp": 13023,
protoss: 13024,
quarian: 13025,
ronso: 13026,
salarian: 13027,
sangheili: 13028,
tauntaun: 13029,
tauren: 13030,
trandoshan: 13031,
transformer: 13032,
turian: 13033,
twilek: 13034,
viera: 13035,
wookiee: 13036,
xenomorph: 5024,
yautja: 13037,
yordle: 13038,
yoshi: 13039,
zerg: 13040,
aardvark: 14001,
aardwolf: 14002,
"african-wild-dog": 14003,
akita: 14004,
albatross: 14005,
crocodile: 7001,
alpaca: 14006,
anaconda: 14007,
anteater: 14008,
antelope: 6004,
arachnid: 8e3,
"arctic-fox": 14009,
armadillo: 14010,
axolotl: 14011,
baboon: 14012,
badger: 6045,
bat: 6001,
beaver: 6064,
bee: 14013,
binturong: 14014,
bison: 14015,
"blue-jay": 14016,
"border-collie": 14017,
"brown-bear": 14018,
buffalo: 14019,
"buffalo-bison": 14020,
"bull-terrier": 14021,
butterfly: 14022,
caiman: 14023,
camel: 6074,
capybara: 14024,
caribou: 14025,
caterpillar: 14026,
cephalopod: 2001,
chameleon: 14027,
cheetah: 6021,
chicken: 14028,
chimpanzee: 14029,
chinchilla: 14030,
chipmunk: 14031,
civet: 14032,
"clouded-leopard": 14033,
coatimundi: 14034,
cockatiel: 14035,
corgi: 14036,
corvid: 3001,
cougar: 6022,
cow: 6003,
coyote: 6008,
crab: 14037,
crane: 14038,
crayfish: 14039,
crow: 3002,
crustacean: 14040,
dalmatian: 14041,
deer: 14042,
dhole: 14043,
dingo: 6011,
dinosaur: 8001,
doberman: 6009,
dolphin: 2002,
donkey: 6019,
duck: 3003,
eagle: 3004,
eel: 14044,
elephant: 14045,
falcon: 3005,
fennec: 6072,
ferret: 6046,
finch: 14046,
fish: 2005,
flamingo: 14047,
fossa: 14048,
frog: 1001,
gazelle: 6005,
gecko: 7003,
genet: 14049,
"german-shepherd": 6012,
gibbon: 14050,
giraffe: 6031,
goat: 6006,
goose: 3006,
gorilla: 6054,
"gray-fox": 14051,
"great-dane": 14052,
"grizzly-bear": 14053,
"guinea-pig": 14054,
hamster: 14055,
hawk: 3008,
hedgehog: 6032,
heron: 14056,
hippopotamus: 6033,
honeybee: 14057,
horse: 6034,
housecat: 6020,
human: 6055,
humanoid: 14058,
hummingbird: 14059,
husky: 6014,
hyena: 6035,
iguana: 7004,
impala: 14060,
jackal: 6013,
jaguar: 6023,
kangaroo: 6038,
"kangaroo-mouse": 14061,
"kangaroo-rat": 14062,
kinkajou: 14063,
"kit-fox": 14064,
koala: 6039,
"kodiak-bear": 14065,
"komodo-dragon": 14066,
labrador: 14067,
lemur: 6056,
leopard: 6024,
liger: 14068,
linsang: 14069,
lion: 6025,
lizard: 7005,
llama: 6036,
lobster: 14070,
"longhair-cat": 14071,
lynx: 6026,
magpie: 14072,
"maine-coon": 14073,
malamute: 14074,
"mammal-feline": 14075,
"mammal-herd": 14076,
"mammal-marsupial": 14077,
"mammal-mustelid": 14078,
"mammal-other predator": 14079,
"mammal-prey": 14080,
"mammal-primate": 14081,
"mammal-rodent": 14082,
manatee: 14083,
mandrill: 14084,
"maned-wolf": 14085,
mantid: 8004,
marmoset: 14086,
marten: 14087,
meerkat: 6043,
mink: 6048,
mole: 14088,
mongoose: 6044,
"monitor-lizard": 14089,
monkey: 6057,
moose: 14090,
moth: 14091,
mouse: 6065,
"musk-deer": 14092,
"musk-ox": 14093,
newt: 1002,
ocelot: 6027,
octopus: 14094,
okapi: 14095,
olingo: 14096,
opossum: 6037,
orangutan: 14097,
orca: 14098,
oryx: 14099,
ostrich: 14100,
otter: 6047,
owl: 3009,
panda: 6052,
pangolin: 14101,
panther: 6028,
parakeet: 14102,
parrot: 14103,
peacock: 14104,
penguin: 14105,
"persian-cat": 14106,
pig: 6053,
pigeon: 14107,
pika: 14108,
"pine-marten": 14109,
platypus: 14110,
"polar-bear": 14111,
pony: 6073,
poodle: 14112,
porcupine: 14113,
porpoise: 2004,
procyonid: 14114,
puffin: 14115,
quoll: 6040,
rabbit: 6059,
raccoon: 6060,
rat: 6061,
ray: 14116,
"red-fox": 14117,
"red-panda": 6062,
reindeer: 14118,
reptillian: 14119,
rhinoceros: 6063,
robin: 14120,
rottweiler: 14121,
sabercats: 14122,
sabertooth: 14123,
salamander: 1003,
scorpion: 8005,
seagull: 14124,
seahorse: 14125,
seal: 6068,
"secretary-bird": 14126,
"serpent-dragon": 4003,
serval: 14127,
shark: 2006,
sheep: 14128,
"shiba-inu": 14129,
"shorthair-cat": 14130,
shrew: 14131,
siamese: 14132,
sifaka: 14133,
"silver-fox": 14134,
skunk: 6069,
sloth: 14135,
snail: 14136,
"snake-serpent": 7006,
"snow-leopard": 14137,
sparrow: 14138,
squid: 14139,
squirrel: 6070,
stoat: 14140,
stork: 14141,
"sugar-glider": 14142,
"sun-bear": 14143,
swan: 3011,
"swift-fox": 14144,
tanuki: 5022,
tapir: 14145,
"tasmanian-devil": 14146,
thylacine: 14147,
tiger: 6029,
toucan: 14148,
turtle: 7007,
vulture: 14149,
wallaby: 6041,
walrus: 14150,
wasp: 14151,
weasel: 6049,
whale: 2003,
wolf: 6016,
wolverine: 6050,
zebra: 6071
};
}
static get gender() {
return {
any: 0,
male: 2,
female: 3,
herm: 4,
intersex: 11,
"trans-male": 8,
"trans-female": 9,
"non-binary": 10,
multiple: 6,
other: 7,
"not-specified": 7
};
}
static get results() {
return {
24: 24,
48: 48,
72: 72,
96: 96,
128: 128
};
}
}
class Page {
static async getGalleryPage(username, folderId, pageNumber, galleryType, semaphore) {
if ("journals" == galleryType) return await Page.getJournalsPage(username, pageNumber, semaphore);
if ("browse" == galleryType) return await Page.getBrowsePage(pageNumber, null, semaphore);
if (!username) return Logger.logError("No username given"), null;
if (!pageNumber) return Logger.logError("No page number given"), null;
let url;
switch (pageNumber <= 0 && (Logger.logWarning("Page number is less 1. Using default 1 instead."),
pageNumber = 1), galleryType || (Logger.logWarning("No gallery type given. Using default 'Gallery' instead."),
galleryType = "gallery"), username.endsWith("/") || (username += "/"), galleryType) {
case "gallery":
url = Gallery.hardLink + username;
break;
case "scraps":
url = Scraps.hardLink + username;
break;
case "favorites":
url = Favorites.hardLink + username;
}
return folderId && (url += "folder/" + folderId + "/"), url ? await FuraffinityRequests.getHTML(url + pageNumber, semaphore) : null;
}
static async getJournalsPage(username, pageNumber, semaphore) {
if (!username) return Logger.logError("No username given"), null;
if (!pageNumber) return Logger.logError("No page number given"), null;
if (pageNumber <= 0) return Logger.logError("Page number must be greater than 0"),
null;
username.endsWith("/") || (username += "/");
const url = Journals.hardLink + username;
return url ? await FuraffinityRequests.getHTML(url + pageNumber, semaphore) : null;
}
static async getBrowsePage(pageNumber, browseOptions, semaphore) {
if (!pageNumber) return Logger.logError("No page number given"), null;
if (pageNumber <= 0) return Logger.logError("Page number must be greater than 0"),
null;
browseOptions || (browseOptions = new BrowseOptions);
const payload = {
cat: browseOptions.category,
atype: browseOptions.type,
species: browseOptions.species,
gender: browseOptions.gender,
perpage: browseOptions.results,
page: pageNumber,
rating_general: browseOptions.ratingGeneral ? "on" : "off",
rating_mature: browseOptions.ratingMature ? "on" : "off",
rating_adult: browseOptions.ratingAdult ? "on" : "off"
};
for (const key in payload) null != payload[key] && null != payload[key] && 0 != payload[key] && "off" != payload[key] || delete payload[key];
const payloadArray = Object.entries(payload), url = Browse.hardLink;
return url ? await FuraffinityRequests.postHTML(url, payloadArray, semaphore) : null;
}
static async getSearchPage(pageNumber, searchOptions, semaphore) {
if (!pageNumber) return Logger.logError("No page number given"), null;
if (pageNumber <= 0) return Logger.logError("Page number must be greater than 0"),
null;
searchOptions || (searchOptions = new SearchOptions);
const payload = {
page: pageNumber,
q: searchOptions.input,
"order-by": searchOptions.orderBy,
"order-direction": searchOptions.orderDirection,
range: searchOptions.range,
range_from: "",
range_to: "",
"rating-general": searchOptions.ratingGeneral ? 1 : 0,
"rating-mature": searchOptions.ratingMature ? 1 : 0,
"rating-adult": searchOptions.ratingAdult ? 1 : 0,
"type-art": searchOptions.typeArt ? 1 : 0,
"type-music": searchOptions.typeMusic ? 1 : 0,
"type-flash": searchOptions.typeFlash ? 1 : 0,
"type-story": searchOptions.typeStory ? 1 : 0,
"type-photos": searchOptions.typePhotos ? 1 : 0,
"type-poetry": searchOptions.typePoetry ? 1 : 0,
mode: searchOptions.matching
};
for (const key in payload) null != payload[key] && null != payload[key] && 0 != payload[key] && "off" != payload[key] || delete payload[key];
if (searchOptions.rangeFrom instanceof Date && searchOptions.rangeFrom) {
const formattedDate = `${searchOptions.rangeFrom.getFullYear()}-${(searchOptions.rangeFrom.getMonth() + 1).toString().padStart(2, "0")}-${searchOptions.rangeFrom.getDate().toString().padStart(2, "0")}`;
payload.range_from = formattedDate;
} else "string" == typeof searchOptions.rangeFrom && searchOptions.rangeFrom && (payload.range_from = searchOptions.rangeFrom);
if (searchOptions.rangeTo instanceof Date && searchOptions.rangeTo) {
const formattedDate = `${searchOptions.rangeTo.getFullYear()}-${(searchOptions.rangeTo.getMonth() + 1).toString().padStart(2, "0")}-${searchOptions.rangeTo.getDate().toString().padStart(2, "0")}`;
payload.range_to = formattedDate;
} else "string" == typeof searchOptions.rangeTo && searchOptions.rangeTo && (payload.range_to = searchOptions.rangeTo);
const payloadArray = Object.entries(payload), url = Search.hardLink;
return url ? await FuraffinityRequests.postHTML(url, payloadArray, semaphore) : null;
}
}
class Gallery {
constructor(semaphore) {
this.semaphore = semaphore;
}
static get hardLink() {
return FuraffinityRequests.getUrl() + "/gallery/";
}
async getFiguresBetweenIds(username, fromId, toId, action, delay = 100) {
return fromId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresTillId, [ username, null, toId, null, "gallery", this.semaphore ], action, delay) : toId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresSinceId, [ username, null, fromId, null, "gallery", this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresBetweenIds, [ username, null, fromId, toId, null, null, "gallery", this.semaphore ], action, delay, !0);
}
async getFiguresInFolderBetweenIds(username, folderId, fromId, toId, action, delay = 100) {
return fromId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresTillId, [ username, folderId, toId, null, "gallery", this.semaphore ], action, delay) : toId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresSinceId, [ username, folderId, fromId, null, "gallery", this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresBetweenIds, [ username, folderId, fromId, toId, null, null, "gallery", this.semaphore ], action, delay, !0);
}
async getFiguresBetweenIdsBetweenPages(username, fromId, toId, fromPageNumber, toPageNumber, action, delay = 100) {
return fromId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresTillId, [ username, null, toId, fromPageNumber, "gallery", this.semaphore ], action, delay) : toId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresSinceId, [ username, null, fromId, toPageNumber, "gallery", this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresBetweenIds, [ username, null, fromId, toId, fromPageNumber, toPageNumber, "gallery", this.semaphore ], action, delay, !0);
}
async getFiguresInFolderBetweenIdsBetweenPages(username, folderId, fromId, toId, fromPageNumber, toPageNumber, action, delay = 100) {
return fromId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresTillId, [ username, folderId, toId, fromPageNumber, "gallery", this.semaphore ], action, delay) : toId <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresSinceId, [ username, folderId, fromId, toPageNumber, "gallery", this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresBetweenIds, [ username, folderId, fromId, toId, fromPageNumber, toPageNumber, "gallery", this.semaphore ], action, delay, !0);
}
async getFiguresBetweenPages(username, fromPageNumber, toPageNumber, action, delay = 100) {
return fromPageNumber <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresTillPage, [ username, null, toPageNumber, "gallery", this.semaphore ], action, delay, !0) : toPageNumber <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresSincePage, [ username, null, fromPageNumber, "gallery", this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresBetweenPages, [ username, null, fromPageNumber, toPageNumber, "gallery", this.semaphore ], action, delay, !0);
}
async getFiguresInFolderBetweenPages(username, folderId, fromPageNumber, toPageNumber, action, delay = 100) {
return fromPageNumber <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresTillPage, [ username, folderId, toPageNumber, "gallery", this.semaphore ], action, delay, !0) : toPageNumber <= 0 ? await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresSincePage, [ username, folderId, fromPageNumber, "gallery", this.semaphore ], action, delay) : await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFiguresBetweenPages, [ username, folderId, fromPageNumber, toPageNumber, "gallery", this.semaphore ], action, delay, !0);
}
async getFigures(username, pageNumber, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFigures, [ username, null, pageNumber, "gallery", this.semaphore ], action, delay);
}
async getFiguresInFolder(username, folderId, pageNumber, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(GalleryRequests.getGalleryFigures, [ username, folderId, pageNumber, "gallery", this.semaphore ], action, delay);
}
async getPage(username, pageNumber, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(Page.getGalleryPage, [ username, null, pageNumber, "gallery", this.semaphore ], action, delay);
}
async getPageInFolder(username, folderId, pageNumber, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(Page.getGalleryPage, [ username, folderId, pageNumber, "gallery", this.semaphore ], action, delay);
}
}
class GalleryRequests {
constructor(semaphore) {
this.semaphore = semaphore, this.Gallery = new Gallery(semaphore), this.Scraps = new Scraps(semaphore),
this.Favorites = new Favorites(semaphore), this.Journals = new Journals(semaphore);
}
static async getGalleryFiguresTillId(username, folderId, toId, fromPage, galleryType, semaphore) {
if (!toId) return Logger.logError("No toId given"), null;
let allFigures = [], running = !0, i = 1;
for (fromPage && fromPage >= 1 && (i = fromPage); running; ) {
const figures = await GalleryRequests.getGalleryFigures(username, folderId, i, galleryType, semaphore);
let currFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), null == currFigureId ? running = !1 : IdArray.containsId(figures, toId) ? (allFigures.push(IdArray.getTillId(figures, toId)),
running = !1) : (allFigures.push(figures), i++);
}
return 0 === allFigures.length ? null : allFigures;
}
static async getGalleryFiguresSinceId(username, folderId, fromId, toPage, galleryType, semaphore) {
if (!fromId) return Logger.logError("No fromId given"), null;
let lastFigureId, running = !0, i = 1;
for (;running; ) {
if (toPage && toPage >= 1 && i == toPage) {
running = !1;
break;
}
const figures = await GalleryRequests.getGalleryFigures(username, folderId, i, galleryType, semaphore);
let currFigureId = lastFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), currFigureId == lastFigureId || IdArray.containsId(figures, fromId) ? running = !1 : i++;
}
let allFigures = [];
for (lastFigureId = null, running = !0; running; ) {
const figures = await GalleryRequests.getGalleryFigures(username, folderId, i, galleryType, semaphore);
let currFigureId = lastFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), currFigureId == lastFigureId ? running = !1 : (allFigures.push(IdArray.getSinceId(figures, fromId)),
i++);
}
return 0 === allFigures.length ? null : allFigures;
}
static async getGalleryFiguresBetweenIds(username, folderId, fromId, toId, fromPage, toPage, galleryType, semaphore, percentId) {
if (!fromId) return Logger.logError("No fromId given"), null;
if (!toId) return Logger.logError("No toId given"), null;
let lastFigureId;
(!fromPage || fromPage <= 0 || !toPage || toPage <= 1) && (Logger.logWarning("No fromPage or toPage given. Percentages can not be calculated."),
percentId = null);
let running = !0, i = 1;
for (fromPage && fromPage >= 1 && (i = fromPage); running; ) {
const figures = await GalleryRequests.getGalleryFigures(username, folderId, i, galleryType, semaphore);
let currFigureId = lastFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), currFigureId == lastFigureId || IdArray.containsId(figures, fromId) ? running = !1 : i++;
}
let allFigures = [];
for (lastFigureId = null, running = !0; running; ) {
if (toPage && toPage >= 1 && i == toPage) {
running = !1;
break;
}
const figures = await GalleryRequests.getGalleryFigures(username, folderId, i, galleryType, semaphore);
let currFigureId = lastFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), currFigureId == lastFigureId ? running = !1 : IdArray.containsId(figures, toId) ? (allFigures.push(IdArray.getBetweenIds(figures, fromId, toId)),
running = !1) : (allFigures.push(figures), i++);
}
if (percentId) {
const progress = 1 / toPage * 100;
PercentHelper.setPercentValue(percentId, progress);
}
return 0 === allFigures.length ? null : allFigures;
}
static async getGalleryFiguresTillPage(username, folderId, toPageNumber, galleryType, semaphore, percentId) {
if (!toPageNumber) return Logger.logError("No toPageNumber given"), null;
if (toPageNumber <= 0) return Logger.logError("toPageNumber must be greater than 0"),
null;
let allFigures = [], completedPages = 0;
for (let i = 1; i <= toPageNumber; i++) {
const figures = await GalleryRequests.getGalleryFigures(username, folderId, i, galleryType, semaphore);
if (figures && 0 !== figures.length && allFigures.push(figures), completedPages++,
percentId) {
const progress = completedPages / toPageNumber * 100;
PercentHelper.setPercentValue(percentId, progress);
}
}
return 0 === allFigures.length ? null : allFigures;
}
static async getGalleryFiguresSincePage(username, folderId, fromPageNumber, galleryType, semaphore) {
if (!fromPageNumber) return Logger.logError("No fromPageNumber given"), null;
if (fromPageNumber <= 0) return Logger.logError("fromPageNumber must be greater than 0"),
null;
let allFigures = [], running = !0, i = fromPageNumber;
for (;running; ) {
const figures = await GalleryRequests.getGalleryFigures(username, folderId, i, galleryType, semaphore);
let currFigureId;
figures && 0 !== figures.length && (currFigureId = figures[0].id), null == currFigureId ? running = !1 : (allFigures.push(figures),
i++);
}
return 0 === allFigures.length ? null : allFigures;
}
static async getGalleryFiguresBetweenPages(username, folderId, fromPageNumber, toPageNumber, galleryType, semaphore, percentId) {
if (!fromPageNumber) return Logger.logError("No fromPageNumber given"), null;
if (fromPageNumber <= 0) return Logger.logError("fromPageNumber must be greater than 0"),
null;
if (!toPageNumber) return Logger.logError("No toPageNumber given"), null;
if (toPageNumber <= 0) return Logger.logError("toPageNumber must be greater than 0"),
null;
let allFigures = [];
const direction = fromPageNumber < toPageNumber ? 1 : -1, totalPages = Math.abs(toPageNumber - fromPageNumber) + 1;
let completedPages = 0;
for (let i = fromPageNumber; i <= toPageNumber; i += direction) {
const figures = await GalleryRequests.getGalleryFigures(username, folderId, i, galleryType, semaphore);
if (figures && 0 !== figures.length && allFigures.push(figures), completedPages++,
percentId) {
const progress = completedPages / totalPages * 100;
PercentHelper.setPercentValue(percentId, progress);
}
}
return 0 === allFigures.length ? null : allFigures;
}
static async getGalleryFigures(username, folderId, pageNumber, galleryType, semaphore) {
const galleryDoc = await Page.getGalleryPage(username, folderId, pageNumber, galleryType, semaphore);
if (!galleryDoc || !(galleryDoc instanceof Document) || galleryDoc.getElementById("no-images")) return Logger.logMessage(`No images found at ${galleryType} of "${username}" on page "${pageNumber}".`),
null;
const figures = galleryDoc.getElementsByTagName("figure");
return figures && 0 !== figures.length ? figures : (Logger.logMessage(`No figures found at ${galleryType} of "${username}" on page "${pageNumber}".`),
null);
}
static async getJournalsSectionsTillId(username, toId, fromPage, semaphore) {
if (toId) return Logger.logError("No toId given"), null;
let allSections = [], running = !0, i = 1;
for (fromPage && fromPage >= 1 && (i = fromPage); running; ) {
const sections = await GalleryRequests.getJournalsSections(username, i, semaphore);
let currSectionId;
sections && 0 !== sections.length && (currSectionId = sections[0].id), null == currSectionId ? running = !1 : IdArray.containsId(sections, toId) ? (allSections.push(IdArray.getTillId(sections, toId)),
running = !1) : (allSections.push(sections), i++);
}
return 0 === allSections.length ? null : allSections;
}
static async getJournalsSectionsSinceId(username, fromId, toPage, semaphore) {
if (!fromId) return Logger.logError("No fromId given"), null;
let lastSectionId, running = !0, i = 1;
for (;running; ) {
if (toPage && toPage >= 1 && i == toPage) {
running = !1;
break;
}
const sections = await GalleryRequests.getJournalsSections(username, i, semaphore);
let currSectionId = lastSectionId;
sections && 0 !== sections.length && (currSectionId = sections[0].id), currSectionId == lastSectionId || IdArray.containsId(sections, fromId) ? running = !1 : i++;
}
let allSections = [];
for (lastSectionId = null, running = !0; running; ) {
const sections = await GalleryRequests.getJournalsSections(username, i, semaphore);
let currSectionId = lastSectionId;
sections && 0 !== sections.length && (currSectionId = sections[0].id), currSectionId == lastSectionId ? running = !1 : (allSections.push(IdArray.getSinceId(sections, fromId)),
i++);
}
return 0 === allSections.length ? null : allSections;
}
static async getJournalsSectionsBetweenIds(username, fromId, toId, fromPage, toPage, semaphore, percentId) {
if (!fromId) return Logger.logError("No fromId given"), null;
if (!toId) return Logger.logError("No toId given"), null;
let lastSectionId;
(!fromPage || fromPage <= 0 || !toPage || toPage <= 1) && (Logger.logWarning("No fromPage or toPage given. Percentages can not be calculated."),
percentId = null);
let running = !0, i = 1;
for (fromPage && fromPage >= 1 && (i = fromPage); running; ) {
const sections = await GalleryRequests.getJournalsSections(username, i, semaphore);
let currSectionId = lastSectionId;
sections && 0 !== sections.length && (currSectionId = sections[0].id), currSectionId == lastSectionId || IdArray.containsId(sections, fromId) ? running = !1 : i++;
}
let allSections = [];
lastSectionId = null, running = !0;
for (;running; ) {
if (toPage && toPage >= 1 && i == toPage) {
running = !1;
break;
}
const sections = await GalleryRequests.getJournalsSections(username, i, semaphore);
let currFigureId = lastSectionId;
sections && 0 !== sections.length && (currFigureId = sections[0].id), currFigureId == lastSectionId ? running = !1 : IdArray.containsId(sections, toId) ? (allSections.push(IdArray.getBetweenIds(sections, fromId, toId)),
running = !1) : (allSections.push(sections), i++);
}
if (percentId) {
const progress = 1 / toPage * 100;
PercentHelper.setPercentValue(percentId, progress);
}
return 0 === allSections.length ? null : allSections;
}
static async getJournalsSectionsTillPage(username, toPageNumber, semaphore, percentId) {
if (!toPageNumber) return Logger.logError("No toPageNumber given"), null;
if (toPageNumber <= 0) return Logger.logError("toPageNumber must be greater than 0"),
null;
let allSections = [], completedPages = 0;
for (let i = 1; i <= toPageNumber; i++) {
const sections = await GalleryRequests.getJournalsSections(username, i, semaphore);
if (sections && 0 !== sections.length && allSections.push(sections), completedPages++,
percentId) {
const progress = completedPages / toPageNumber * 100;
PercentHelper.setPercentValue(percentId, progress);
}
}
return 0 === allSections.length ? null : allSections;
}
static async getJournalsSectionsSincePage(username, fromPageNumber, semaphore) {
if (!fromPageNumber) return Logger.logError("No fromPageNumber given"), null;
if (fromPageNumber <= 0) return Logger.logError("fromPageNumber must be greater than 0"),
null;
let allSections = [], running = !0, i = fromPageNumber;
for (;running; ) {
const sections = await GalleryRequests.getJournalsSections(username, i, semaphore);
if (sections && 0 !== sections.length) {
null == sections[0].id ? running = !1 : (allSections.push(sections), i++);
}
}
return 0 === allSections.length ? null : allSections;
}
static async getJournalsSectionsBetweenPages(username, fromPageNumber, toPageNumber, semaphore, percentId) {
if (!fromPageNumber) return Logger.logError("No fromPageNumber given"), null;
if (fromPageNumber <= 0) return Logger.logError("fromPageNumber must be greater than 0"),
null;
if (!toPageNumber) return Logger.logError("No toPageNumber given"), null;
if (toPageNumber <= 0) return Logger.logError("toPageNumber must be greater than 0"),
null;
let allSections = [], direction = fromPageNumber < toPageNumber ? 1 : -1;
const totalPages = Math.abs(toPageNumber - fromPageNumber) + 1;
let completedPages = 0;
for (let i = fromPageNumber; i <= toPageNumber; i += direction) {
const sections = await GalleryRequests.getJournalsSections(username, i, semaphore);
sections && allSections.push(sections), completedPages++;
const progress = completedPages / totalPages * 100;
PercentHelper.setPercentValue(percentId, progress);
}
return 0 === allSections.length ? null : allSections;
}
static async getJournalsSections(username, pageNumber, semaphore) {
const galleryDoc = await Page.getJournalsPage(username, pageNumber, semaphore);
if (!galleryDoc) return Logger.logMessage(`No journals found at "${username}" on page "${pageNumber}".`),
null;
const columnPage = galleryDoc.getElementById("columnpage");
if (!columnPage) return Logger.logMessage(`No column page found at "${username}" on page "${pageNumber}".`),
null;
const sections = columnPage.getElementsByTagName("section");
return sections && 0 !== sections.length ? sections : (Logger.logMessage(`No journals found at "${username}" on page "${pageNumber}".`),
null);
}
}
class UserRequests {
constructor(semaphore) {
this.semaphore = semaphore, this.GalleryRequests = new GalleryRequests(semaphore),
this.SearchRequests = new SearchRequests(semaphore);
}
static get hardLinks() {
return {
user: FuraffinityRequests.getUrl() + "/user/",
watch: FuraffinityRequests.getUrl() + "/watch/",
unwatch: FuraffinityRequests.getUrl() + "/unwatch/",
block: FuraffinityRequests.getUrl() + "/block/",
unblock: FuraffinityRequests.getUrl() + "/unblock/"
};
}
async getUserPage(username, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getUserPageLocal, [ username, this.semaphore ], action, delay);
}
async watchUser(username, watchKey, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(watchUserLocal, [ username, watchKey, this.semaphore ], action, delay);
}
async unwatchUser(username, unwatchKey, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(unwatchUserLocal, [ username, unwatchKey, this.semaphore ], action, delay);
}
async blockUser(username, blockKey, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(blockUserLocal, [ username, blockKey, this.semaphore ], action, delay);
}
async unblockUser(username, unblockKey, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(unblockUserLocal, [ username, unblockKey, this.semaphore ], action, delay);
}
}
async function getUserPageLocal(username, semaphore) {
if (!username) return Logger.logWarning("No username given"), null;
UserRequests.hardLinks.user.endsWith("/") || (UserRequests.hardLinks.user += "/");
const url = UserRequests.hardLinks.user + username;
return url ? await FuraffinityRequests.getHTML(url, semaphore) : null;
}
async function watchUserLocal(username, watchKey, semaphore) {
if (!username) return Logger.logWarning("No username given"), null;
if (!watchKey) return Logger.logWarning("No watch key given"), null;
UserRequests.hardLinks.watch.endsWith("/") || (UserRequests.hardLinks.watch += "/");
const url = UserRequests.hardLinks.watch + username + "?key=" + watchKey;
return !!url && !!await FuraffinityRequests.getHTML(url, semaphore);
}
async function unwatchUserLocal(username, unwatchKey, semaphore) {
if (!username) return Logger.logWarning("No username given"), null;
if (!unwatchKey) return Logger.logWarning("No unwatch key given"), null;
UserRequests.hardLinks.unwatch.endsWith("/") || (UserRequests.hardLinks.unwatch += "/");
const url = UserRequests.hardLinks.unwatch + username + "?key=" + unwatchKey;
return !!url && !!await FuraffinityRequests.getHTML(url, semaphore);
}
async function blockUserLocal(username, blockKey, semaphore) {
if (!username) return Logger.logWarning("No username given"), null;
if (!blockKey) return Logger.logWarning("No block key given"), null;
UserRequests.hardLinks.block.endsWith("/") || (UserRequests.hardLinks.block += "/");
const url = UserRequests.hardLinks.block + username + "?key=" + blockKey;
return !!url && !!await FuraffinityRequests.getHTML(url, semaphore);
}
async function unblockUserLocal(username, unblockKey, semaphore) {
if (!username) return Logger.logWarning("No username given"), null;
if (!unblockKey) return Logger.logWarning("No unblock key given"), null;
UserRequests.hardLinks.unblock.endsWith("/") || (UserRequests.hardLinks.unblock += "/");
const url = UserRequests.hardLinks.unblock + username + "?key=" + unblockKey;
return !!url && !!await FuraffinityRequests.getHTML(url, semaphore);
}
class NewSubmissions {
constructor(semaphore) {
this.semaphore = semaphore;
}
static get hardLink() {
return FuraffinityRequests.getUrl() + "/msg/submissions/";
}
async getSubmissionsPage(firstSubmissionId, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getSubmissionsPageLocal, [ firstSubmissionId, this.semaphore ], action, delay);
}
async removeSubmissions(submissionIds, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(removeSubmissionsLocal, [ submissionIds, this.semaphore ], action, delay);
}
async nukeSubmissions(action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(nukeSubmissionsLocal, [ this.semaphore ], action, delay);
}
}
async function getSubmissionsPageLocal(firstSubmissionId, semaphore) {
return firstSubmissionId ? await FuraffinityRequests.getHTML(`${NewSubmissions.hardLink}new~${firstSubmissionId}@72/`, semaphore) : await FuraffinityRequests.getHTML(`${NewSubmissions.hardLink}new@72/`, semaphore);
}
async function removeSubmissionsLocal(submissionIds, semaphore) {
if (!submissionIds || 0 == submissionIds.length) return void Logger.logWarning("No submission ids to remove");
const payload = [];
for (const submissionId of submissionIds) payload.push({
key: "submissions[]",
value: submissionId
});
return payload.push({
key: "messagecenter-action",
value: Message.hardActions.remove
}), await FuraffinityRequests.postHTML(`${NewSubmissions.hardLink}new@72/`, payload, semaphore);
}
async function nukeSubmissionsLocal(semaphore) {
const payload = [];
return payload.push({
key: "messagecenter-action",
value: Message.hardActions.nuke
}), await FuraffinityRequests.postHTML(`${NewSubmissions.hardLink}new@72/`, payload, semaphore);
}
class Message {
constructor(semaphore) {
this.semaphore = semaphore, this.NewSubmissions = new NewSubmissions(semaphore);
}
static hardActions={
remove: "remove_checked",
nuke: "nuke_notifications"
};
}
class AccountInformation {
constructor(semaphore) {
this.semaphore = semaphore;
}
static get hardLinks() {
return {
settings: FuraffinityRequests.getUrl() + "/controls/settings/",
siteSettings: FuraffinityRequests.getUrl() + "/controls/site-settings/",
userSettings: FuraffinityRequests.getUrl() + "/controls/user-settings/"
};
}
async getSettingsPage(action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getSettingsPageLocal, [ this.semaphore ], action, delay);
}
async getSiteSettingsPage(action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getSiteSettingsPageLocal, [ this.semaphore ], action, delay);
}
async getUserSettingsPage(action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getUserSettingsPageLocal, [ this.semaphore ], action, delay);
}
}
async function getSettingsPageLocal(semaphore) {
return AccountInformation.hardLinks.settings.endsWith("/") || (AccountInformation.hardLinks.settings += "/"),
await FuraffinityRequests.getHTML(AccountInformation.hardLinks.settings, semaphore);
}
async function getSiteSettingsPageLocal(semaphore) {
return AccountInformation.hardLinks.siteSettings.endsWith("/") || (AccountInformation.hardLinks.siteSettings += "/"),
await FuraffinityRequests.getHTML(AccountInformation.hardLinks.siteSettings, semaphore);
}
async function getUserSettingsPageLocal(semaphore) {
return AccountInformation.hardLinks.userSettings.endsWith("/") || (AccountInformation.hardLinks.userSettings += "/"),
await FuraffinityRequests.getHTML(AccountInformation.hardLinks.userSettings, semaphore);
}
class UserProfile {
constructor(semaphore) {
this.semaphore = semaphore;
}
static get hardLinks() {
return {
profile: FuraffinityRequests.getUrl() + "/controls/profile/",
profilebanner: FuraffinityRequests.getUrl() + "/controls/profilebanner/",
contacts: FuraffinityRequests.getUrl() + "/controls/contacts/",
avatar: FuraffinityRequests.getUrl() + "/controls/avatar/"
};
}
async getProfilePage(action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getProfilePageLocal, [ this.semaphore ], action, delay);
}
async getProfilebannerPage(action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getProfilebannerPageLocal, [ this.semaphore ], action, delay);
}
async getContactsPage(action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getContactsPageLocal, [ this.semaphore ], action, delay);
}
async getAvatarPage(action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getAvatarPageLocal, [ this.semaphore ], action, delay);
}
}
async function getProfilePageLocal(semaphore) {
return UserProfile.hardLinks.profile.endsWith("/") || (UserProfile.hardLinks.profile += "/"),
await FuraffinityRequests.getHTML(UserProfile.hardLinks.profile, semaphore);
}
async function getProfilebannerPageLocal(semaphore) {
return UserProfile.hardLinks.profilebanner.endsWith("/") || (UserProfile.hardLinks.profilebanner += "/"),
await FuraffinityRequests.getHTML(UserProfile.hardLinks.profilebanner, semaphore);
}
async function getContactsPageLocal(semaphore) {
return UserProfile.hardLinks.contacts.endsWith("/") || (UserProfile.hardLinks.contacts += "/"),
await FuraffinityRequests.getHTML(UserProfile.hardLinks.contacts, semaphore);
}
async function getAvatarPageLocal(semaphore) {
return UserProfile.hardLinks.avatar.endsWith("/") || (UserProfile.hardLinks.avatar += "/"),
await FuraffinityRequests.getHTML(UserProfile.hardLinks.avatar, semaphore);
}
class ManageContent {
constructor(semaphore) {
this.semaphore = semaphore;
}
static get hardLinks() {
return {
submissions: FuraffinityRequests.getUrl() + "/controls/submissions/",
folders: FuraffinityRequests.getUrl() + "/controls/folders/submissions/",
journals: FuraffinityRequests.getUrl() + "/controls/journal/",
favorites: FuraffinityRequests.getUrl() + "/controls/favorites/",
buddylist: FuraffinityRequests.getUrl() + "/controls/buddylist/",
shouts: FuraffinityRequests.getUrl() + "/controls/shouts/",
badges: FuraffinityRequests.getUrl() + "/controls/badges/"
};
}
async getFoldersPages(action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getContentFoldersLocal, [ this.semaphore ], action, delay);
}
async getAllWatchesPages(action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getContentAllWatchesPagesLocal, [ this.semaphore ], action, delay);
}
async getWatchesPage(pageNumber, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getWatchesPageLocal, [ pageNumber, this.semaphore ], action, delay);
}
}
async function getContentFoldersLocal(semaphore) {
return ManageContent.hardLinks.folders.endsWith("/") || (ManageContent.hardLinks.folders += "/"),
await FuraffinityRequests.getHTML(ManageContent.hardLinks.folders, semaphore);
}
async function getContentAllWatchesPagesLocal(semaphore) {
ManageContent.hardLinks.buddylist.endsWith("/") || (ManageContent.hardLinks.buddylist += "/");
let usersDoc = await FuraffinityRequests.getHTML(ManageContent.hardLinks.buddylist + "x", semaphore);
const pages = usersDoc.getElementById("columnpage").querySelector('div[class="section-body"').querySelectorAll(":scope > a");
let userPageDocs = [];
for (let i = 1; i <= pages.length; i++) usersDoc = await getWatchesPageLocal(i, semaphore),
usersDoc && userPageDocs.push(usersDoc);
return 0 == userPageDocs.length ? null : userPageDocs;
}
async function getWatchesPageLocal(pageNumber, semaphore) {
return pageNumber ? (pageNumber <= 0 && (Logger.logWarning("Page number is less 1. Using default 1 instead."),
pageNumber = 1), ManageContent.hardLinks.buddylist.endsWith("/") || (ManageContent.hardLinks.buddylist += "/"),
await FuraffinityRequests.getHTML(ManageContent.hardLinks.buddylist + pageNumber, semaphore)) : (Logger.logError("No page number given"),
null);
}
class Security {
constructor(semaphore) {
this.semaphore = semaphore;
}
static get hardLinks() {
return {
sessions: FuraffinityRequests.getUrl() + "/controls/sessions/logins/",
logs: FuraffinityRequests.getUrl() + "/controls/logs/",
labels: FuraffinityRequests.getUrl() + "/controls/labels/"
};
}
async getSessionsPage(action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getSecuritySessionsPageLocal, [ this.semaphore ], action, delay);
}
async getLogsPage(action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getSecurityLogsPageLocal, [ this.semaphore ], action, delay);
}
async getLabelsPage(action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getSecurityLabelsPageLocal, [ this.semaphore ], action, delay);
}
}
async function getSecuritySessionsPageLocal(semaphore) {
return Security.hardLinks.sessions.endsWith("/") || (Security.hardLinks.sessions += "/"),
await FuraffinityRequests.getHTML(Security.hardLinks.sessions, semaphore);
}
async function getSecurityLogsPageLocal(semaphore) {
return Security.hardLinks.logs.endsWith("/") || (Security.hardLinks.logs += "/"),
await FuraffinityRequests.getHTML(Security.hardLinks.logs, semaphore);
}
async function getSecurityLabelsPageLocal(semaphore) {
return Security.hardLinks.labels.endsWith("/") || (Security.hardLinks.labels += "/"),
await FuraffinityRequests.getHTML(Security.hardLinks.labels, semaphore);
}
class PersonalUserRequests {
constructor(semaphore) {
this.semaphore = semaphore, this.MessageRequests = new Message(semaphore), this.AccountInformation = new AccountInformation(semaphore),
this.UserProfile = new UserProfile(semaphore), this.ManageContent = new ManageContent(semaphore),
this.Security = new Security(semaphore);
}
}
class SubmissionRequests {
constructor(semaphore) {
this.semaphore = semaphore;
}
static get hardLinks() {
return {
view: FuraffinityRequests.getUrl() + "/view/",
fav: FuraffinityRequests.getUrl() + "/fav/",
unfav: FuraffinityRequests.getUrl() + "/unfav/",
journal: FuraffinityRequests.getUrl() + "/journal/"
};
}
async getSubmissionPage(submissionId, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getSubmissionPageLocal, [ submissionId, this.semaphore ], action, delay);
}
async favSubmission(submissionId, favKey, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(favSubmissionLocal, [ submissionId, favKey, this.semaphore ], action, delay);
}
async unfavSubmission(submissionId, unfavKey, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(unfavSubmissionLocal, [ submissionId, unfavKey, this.semaphore ], action, delay);
}
async getJournalPage(journalId, action, delay = 100) {
return await WaitAndCallAction.callFunctionAsync(getJournalPageLocal, [ journalId, this.semaphore ], action, delay);
}
}
async function getSubmissionPageLocal(submissionId, semaphore) {
if (!submissionId) return Logger.logError("No submissionId given"), null;
SubmissionRequests.hardLinks.view.endsWith("/") || (SubmissionRequests.hardLinks.view += "/");
const url = SubmissionRequests.hardLinks.view + submissionId;
return url ? await FuraffinityRequests.getHTML(url, semaphore) : null;
}
async function favSubmissionLocal(submissionId, favKey, semaphore) {
if (!submissionId) return void Logger.logError("No submissionId given");
if (!favKey) return void Logger.logError("No favKey given");
SubmissionRequests.hardLinks.fav.endsWith("/") || (SubmissionRequests.hardLinks.fav += "/");
const url = SubmissionRequests.hardLinks.fav + submissionId + "?key=" + favKey;
if (url) {
const resultDoc = await FuraffinityRequests.getHTML(url, semaphore);
try {
const standardpage = resultDoc.getElementById("standardpage");
if (standardpage) {
const blocked = standardpage.querySelector('div[class="redirect-message"]');
if (blocked && blocked.textContent.includes("blocked")) return;
}
return getFavKeyLocal(resultDoc);
} catch {}
}
}
async function unfavSubmissionLocal(submissionId, unfavKey, semaphore) {
if (!submissionId) return void Logger.logError("No submissionId given");
if (!unfavKey) return void Logger.logError("No unfavKey given");
SubmissionRequests.hardLinks.unfav.endsWith("/") || (SubmissionRequests.hardLinks.unfav += "/");
const url = SubmissionRequests.hardLinks.unfav + submissionId + "?key=" + unfavKey;
if (url) {
const resultDoc = await FuraffinityRequests.getHTML(url, semaphore);
if (resultDoc) {
return getFavKeyLocal(resultDoc);
}
}
}
async function getJournalPageLocal(journalId, semaphore) {
if (!journalId) return Logger.logError("No journalId given"), null;
SubmissionRequests.hardLinks.journal.endsWith("/") || (SubmissionRequests.hardLinks.journal += "/");
const url = SubmissionRequests.hardLinks.journal + journalId;
return url ? await FuraffinityRequests.getHTML(url, semaphore) : null;
}
function getFavKeyLocal(doc) {
const buttons = doc.getElementById("columnpage").querySelector('div[class*="favorite-nav"').querySelectorAll('a[class*="button"][href]');
let favButton;
for (const button of Array.from(buttons)) button.textContent.toLowerCase().includes("fav") && (favButton = button);
if (favButton) {
return favButton.getAttribute("href").split("?key=")[1];
}
}
class FuraffinityRequests {
constructor(maxAmountRequests = 2) {
this._semaphore = new Semaphore(maxAmountRequests), this.UserRequests = new UserRequests(this._semaphore),
this.PersonalUserRequests = new PersonalUserRequests(this._semaphore), this.SubmissionRequests = new SubmissionRequests(this._semaphore);
}
set maxAmountRequests(value) {
this._semaphore.maxConcurrency != value && (this._semaphore.maxConcurrency = value);
}
get maxAmountRequests() {
return this._semaphore.maxConcurrency;
}
static set useHttps(value) {
FuraffinityRequests._useHttps != value && (FuraffinityRequests._useHttps = value,
FuraffinityRequests._httpsString = value ? "https://" : "http://");
}
static get useHttps() {
return FuraffinityRequests._useHttps;
}
static logLevel=1;
static domain="www.furaffinity.net";
static _httpsString="https://";
static _useHttps=!0;
static getUrl() {
return FuraffinityRequests._httpsString + FuraffinityRequests.domain;
}
static async getHTML(url, semaphore, action, delay = 100) {
const waitAndCallAction = new WaitAndCallAction(action, null, delay);
waitAndCallAction.start();
const html = await async function(url, semaphore) {
Logger.logMessage(`Requesting '${url}'`);
const semaphoreActive = semaphore && semaphore.maxConcurrency > 0;
semaphoreActive && await semaphore.acquire();
try {
const response = await fetch(url), html = await response.text(), parser = new DOMParser;
return parser.parseFromString(html, "text/html");
} catch (error) {
Logger.logError(error);
} finally {
semaphoreActive && semaphore.release();
}
}(url, semaphore);
return waitAndCallAction.stop(), html;
}
static async postHTML(url, payload, semaphore, action, delay = 100) {
const waitAndCallAction = new WaitAndCallAction(action, null, delay);
waitAndCallAction.start();
const html = await async function(url, payload, semaphore) {
const semaphoreActive = semaphore && semaphore.maxConcurrency > 0;
semaphoreActive && await semaphore.acquire();
try {
const response = await fetch(url, {
method: "POST",
body: new URLSearchParams(payload).toString(),
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
});
if (!response.ok) return void Logger.logError(`HTTP error! Status: ${response.status}`);
const responseData = await response.text();
try {
const parser = new DOMParser;
return parser.parseFromString(responseData, "text/html");
} catch {
return responseData;
}
} catch (error) {
Logger.logError(error);
} finally {
semaphoreActive && semaphore.release();
}
}(url, payload, semaphore);
return waitAndCallAction.stop(), html;
}
}
Object.defineProperty(window, "FARequestHelper", {
get: () => FuraffinityRequests
});
})();