diff --git a/src/web/img/connectors/mangagalaxy b/src/web/img/connectors/mangagalaxy new file mode 100644 index 00000000000..fbad6314894 Binary files /dev/null and b/src/web/img/connectors/mangagalaxy differ diff --git a/src/web/img/connectors/vortexscans b/src/web/img/connectors/vortexscans index fcf3f4ca07b..24ce2053a5f 100644 Binary files a/src/web/img/connectors/vortexscans and b/src/web/img/connectors/vortexscans differ diff --git a/src/web/mjs/connectors/MangaGalaxy.mjs b/src/web/mjs/connectors/MangaGalaxy.mjs new file mode 100644 index 00000000000..57bf02d3a96 --- /dev/null +++ b/src/web/mjs/connectors/MangaGalaxy.mjs @@ -0,0 +1,14 @@ +import Iken from './templates/Iken.mjs'; + +export default class MangaGalaxy extends Iken { + constructor() { + super(); + super.id = 'mangagalaxy'; + super.label = 'MangaGalaxy'; + this.tags = [ 'manga', 'english', 'scanlation' ]; + this.url = 'https://mangagalaxy.net'; + this.links = { + login: 'https://mangagalaxy.net/auth/signin', + }; + } +} \ No newline at end of file diff --git a/src/web/mjs/connectors/VortexScans.mjs b/src/web/mjs/connectors/VortexScans.mjs index 1e2bad7bc3c..5dfc8b63f9f 100644 --- a/src/web/mjs/connectors/VortexScans.mjs +++ b/src/web/mjs/connectors/VortexScans.mjs @@ -1,20 +1,14 @@ -import FoolSlide from './templates/FoolSlide.mjs'; +import Iken from './templates/Iken.mjs'; -/** - * - */ -export default class VortexScans extends FoolSlide { - - /** - * - */ +export default class VortexScans extends Iken { constructor() { super(); super.id = 'vortexscans'; super.label = 'VortexScans'; - this.tags = [ 'manga', 'high-quality', 'english', 'scanlation' ]; - this.url = 'https://reader.vortex-scans.com'; - //this.path = '/directory/'; - this.language = 'english'; + this.tags = [ 'manga', 'english', 'scanlation' ]; + this.url = 'https://vortexscans.org'; + this.links = { + login: 'https://vortexscans.org/auth/signin', + }; } } \ No newline at end of file diff --git a/src/web/mjs/connectors/templates/Iken.mjs b/src/web/mjs/connectors/templates/Iken.mjs new file mode 100644 index 00000000000..3a8c94af944 --- /dev/null +++ b/src/web/mjs/connectors/templates/Iken.mjs @@ -0,0 +1,102 @@ +import Connector from '../../engine/Connector.mjs'; +import Manga from '../../engine/Manga.mjs'; + +export default class Iken extends Connector { + constructor() { + super(); + super.id = undefined; + super.label = undefined; + this.tags = []; + this.url = undefined; + this.apiPath = '/api'; + + this.queryPages = 'main section img[src]:not([src=""])'; + } + + async _getMangas() { + const mangaList = []; + + for (let page = 1, run = true; run; page++) { + const list = await this._getMangasFromPage(page); + list.length > 0 ? mangaList.push(...list) : run = false; + } + return mangaList; + } + + async _getMangasFromPage(page) { + const request = new Request(new URL(`${this.apiPath}/query?page=${page}&perPage=1000`, this.url), this.requestOptions); + const { posts } = await this.fetchJSON(request); + + return posts.map(manga => { + // need an example of a novel page to add support + if (manga.isNovel) throw new Error('Novels are not supported'); + + return { + id: manga.id, + title: manga.postTitle + }; + }); + } + + async _getChapters(manga) { + const chapterList = []; + + for (let page = 0, run = true; run; page++) { + const list = await this._getChaptersFromPage(manga.id, page); + list.length > 0 ? chapterList.push(...list) : run = false; + } + return chapterList; + } + + async _getChaptersFromPage(mangaId, page) { + const request = new Request(new URL(`${this.apiPath}/chapters?postId=${mangaId}&skip=${page * 1000}&take=1000&order=desc&userid=`, this.url), this.requestOptions); + const { post } = await this.fetchJSON(request); + + return post.chapters.map(chapter => { + return { + id: JSON.stringify({ + series: chapter.mangaPost.slug, + chapter: chapter.slug, + paywalled: chapter.isLocked, + accessible: chapter.isAccessible + }), + title: `Chapter ${chapter.number} ${chapter.title || ''}`.trim() + }; + }); + } + + async _getPages(chapter) { + const id = JSON.parse(chapter.id); + + // chapter is paywalled + if (id.paywalled) throw new Error('Chapter is paywalled. Please login.'); + + // chapter is not accessible for some reason + if (!id.accessible) throw new Error('The chapter is marked as not accessible.'); + + const request = new Request(new URL(`/series/${id.series}/${id.chapter}`, this.url), this.requestOptions); + const script = ` + new Promise((resolve, reject) => { + setTimeout(() => { + try { + const images = [...document.querySelectorAll('${this.queryPages}')]; + resolve(images.map(image => image.src)); + } catch (error) { + reject(error); + } + }, 1000); + }); + `; + return await Engine.Request.fetchUI(request, script); + } + + async _getMangaFromURI(uri) { + const slug = uri.pathname.split('/')[2]; + const request = new Request(new URL(`${this.apiPath}/post?postSlug=${slug}`, this.url), this.requestOptions); + const { post } = await this.fetchJSON(request); + return new Manga({ + id: post.id, + title: post.postTitle + }); + } +} \ No newline at end of file