concurrent requests are limited now.
This commit is contained in:
NBA2K1
2025-02-01 07:01:43 +01:00
parent f09b870214
commit ccbe6982db
2 changed files with 74 additions and 14 deletions

View File

@@ -7,7 +7,7 @@ const mangayomiSources = [{
"typeSource": "single", "typeSource": "single",
"itemType": 1, "itemType": 1,
"isNsfw": false, "isNsfw": false,
"version": "0.3.3", "version": "0.3.4",
"dateFormat": "", "dateFormat": "",
"dateFormatLocale": "", "dateFormatLocale": "",
"pkgPath": "anime/src/de/aniworld.js" "pkgPath": "anime/src/de/aniworld.js"
@@ -76,9 +76,39 @@ class DefaultExtension extends MProvider {
.replace(/>/g, '>') .replace(/>/g, '>')
.replace(/<br>/g, '\n') .replace(/<br>/g, '\n')
.replace(/<br\s*\/?>/g, '\n') .replace(/<br\s*\/?>/g, '\n')
.replace(/&#039;/g, "'")
.replace(/&quot;/g, '"') .replace(/&quot;/g, '"')
.replace(/<a\s+href="([^"]*)".*?>.*?<\/a>/g, '$1'); .replace(/<a\s+href="([^"]*)".*?>.*?<\/a>/g, '$1');
} }
/**
* Custom asyncPool implementation.
* @param {number} poolLimit - Maximum number of concurrent promises.
* @param {Array} array - Array of items to process.
* @param {function} iteratorFn - Function that returns a promise for each item.
* @returns {Promise<Array>} - Promise resolving to an array of results.
*/
async asyncPool(poolLimit, array, iteratorFn) {
const ret = []; // Array to store all promises
const executing = []; // Array to store currently executing promises
for (const item of array) {
const p = Promise.resolve().then(() => iteratorFn(item));
ret.push(p);
// When poolLimit is reached, wait for the fastest promise to complete
if (poolLimit <= array.length) {
const e = p.then(() => {
// Remove the promise from executing array once it resolves
executing.splice(executing.indexOf(e), 1);
});
executing.push(e);
if (executing.length >= poolLimit) {
await Promise.race(executing);
}
}
}
return Promise.all(ret);
}
async getDetail(url) { async getDetail(url) {
const baseUrl = this.source.baseUrl; const baseUrl = this.source.baseUrl;
const res = await this.client.get(baseUrl + url); const res = await this.client.get(baseUrl + url);
@@ -95,18 +125,18 @@ class DefaultExtension extends MProvider {
author = produzent[0].select("li").map(e => e.text).join(", "); author = produzent[0].select("li").map(e => e.text).join(", ");
} }
const seasonsElements = document.select("#stream > ul:nth-child(1) > li > a"); const seasonsElements = document.select("#stream > ul:nth-child(1) > li > a");
const promises = seasonsElements.map(element => this.parseEpisodesFromSeries(element)); // Use asyncPool to limit concurrency while processing seasons
const episodes = (await Promise.allSettled(promises)) const episodesArrays = await this.asyncPool(2, seasonsElements, element => this.parseEpisodesFromSeries(element));
.filter(p => p.status === 'fulfilled') // Flatten the resulting arrays and reverse the order
.flatMap(p => p.value); const episodes = episodesArrays.flat().reverse();
episodes.reverse();
return { name, imageUrl, description, author, status: 5, genre, episodes }; return { name, imageUrl, description, author, status: 5, genre, episodes };
} }
async parseEpisodesFromSeries(element) { async parseEpisodesFromSeries(element) {
const seasonId = element.getHref; const seasonId = element.getHref;
const res = await this.client.get(this.source.baseUrl + seasonId); const res = await this.client.get(this.source.baseUrl + seasonId);
const episodeElements = new Document(res.body).select("table.seasonEpisodesList tbody tr"); const episodeElements = new Document(res.body).select("table.seasonEpisodesList tbody tr");
return Promise.all(episodeElements.map(e => this.episodeFromElement(e))); // Use asyncPool to limit concurrency while processing episodes of a season
return await this.asyncPool(13, episodeElements, e => this.episodeFromElement(e));
} }
async episodeFromElement(element) { async episodeFromElement(element) {
const titleAnchor = element.selectFirst("td.seasonEpisodeTitle a"); const titleAnchor = element.selectFirst("td.seasonEpisodeTitle a");

View File

@@ -7,7 +7,7 @@ const mangayomiSources = [{
"typeSource": "single", "typeSource": "single",
"itemType": 1, "itemType": 1,
"isNsfw": false, "isNsfw": false,
"version": "0.0.5", "version": "0.0.6",
"dateFormat": "", "dateFormat": "",
"dateFormatLocale": "", "dateFormatLocale": "",
"pkgPath": "anime/src/de/serienstream.js" "pkgPath": "anime/src/de/serienstream.js"
@@ -76,9 +76,39 @@ class DefaultExtension extends MProvider {
.replace(/&gt;/g, '>') .replace(/&gt;/g, '>')
.replace(/<br>/g, '\n') .replace(/<br>/g, '\n')
.replace(/<br\s*\/?>/g, '\n') .replace(/<br\s*\/?>/g, '\n')
.replace(/&#039;/g, "'")
.replace(/&quot;/g, '"') .replace(/&quot;/g, '"')
.replace(/<a\s+href="([^"]*)".*?>.*?<\/a>/g, '$1'); .replace(/<a\s+href="([^"]*)".*?>.*?<\/a>/g, '$1');
} }
/**
* Custom asyncPool implementation.
* @param {number} poolLimit - Maximum number of concurrent promises.
* @param {Array} array - Array of items to process.
* @param {function} iteratorFn - Function that returns a promise for each item.
* @returns {Promise<Array>} - Promise resolving to an array of results.
*/
async asyncPool(poolLimit, array, iteratorFn) {
const ret = []; // Array to store all promises
const executing = []; // Array to store currently executing promises
for (const item of array) {
const p = Promise.resolve().then(() => iteratorFn(item));
ret.push(p);
// When poolLimit is reached, wait for the fastest promise to complete
if (poolLimit <= array.length) {
const e = p.then(() => {
// Remove the promise from executing array once it resolves
executing.splice(executing.indexOf(e), 1);
});
executing.push(e);
if (executing.length >= poolLimit) {
await Promise.race(executing);
}
}
}
return Promise.all(ret);
}
async getDetail(url) { async getDetail(url) {
const baseUrl = this.source.baseUrl; const baseUrl = this.source.baseUrl;
const res = await this.client.get(baseUrl + url); const res = await this.client.get(baseUrl + url);
@@ -95,18 +125,18 @@ class DefaultExtension extends MProvider {
author = produzent[0].select("li").map(e => e.text).join(", "); author = produzent[0].select("li").map(e => e.text).join(", ");
} }
const seasonsElements = document.select("#stream > ul:nth-child(1) > li > a"); const seasonsElements = document.select("#stream > ul:nth-child(1) > li > a");
const promises = seasonsElements.map(element => this.parseEpisodesFromSeries(element)); // Use asyncPool to limit concurrency while processing seasons
const episodes = (await Promise.allSettled(promises)) const episodesArrays = await this.asyncPool(2, seasonsElements, element => this.parseEpisodesFromSeries(element));
.filter(p => p.status === 'fulfilled') // Flatten the resulting arrays and reverse the order
.flatMap(p => p.value); const episodes = episodesArrays.flat().reverse();
episodes.reverse();
return { name, imageUrl, description, author, status: 5, genre, episodes }; return { name, imageUrl, description, author, status: 5, genre, episodes };
} }
async parseEpisodesFromSeries(element) { async parseEpisodesFromSeries(element) {
const seasonId = element.getHref; const seasonId = element.getHref;
const res = await this.client.get(this.source.baseUrl + seasonId); const res = await this.client.get(this.source.baseUrl + seasonId);
const episodeElements = new Document(res.body).select("table.seasonEpisodesList tbody tr"); const episodeElements = new Document(res.body).select("table.seasonEpisodesList tbody tr");
return Promise.all(episodeElements.map(e => this.episodeFromElement(e))); // Use asyncPool to limit concurrency while processing episodes of a season
return await this.asyncPool(13, episodeElements, e => this.episodeFromElement(e));
} }
async episodeFromElement(element) { async episodeFromElement(element) {
const titleAnchor = element.selectFirst("td.seasonEpisodeTitle a"); const titleAnchor = element.selectFirst("td.seasonEpisodeTitle a");