mangadex update fixes

This commit is contained in:
Daniel Bulant 2022-01-10 16:20:31 +01:00
parent a5c1c24e99
commit e2df1b923d
14 changed files with 182 additions and 88 deletions

View file

@ -14,5 +14,5 @@ module.exports = {
"svx",
"md"
],
"started": "2021-05-20T14:57:51.302Z"
"started": "2022-01-10T14:33:28.708Z"
}

View file

@ -1,11 +1,11 @@
/**
* @roxi/routify 2.18.1
* File generated Thu May 20 2021 18:09:03 GMT+0200 (GMT+02:00)
* @roxi/routify 2.18.4
* File generated Mon Jan 10 2022 15:33:28 GMT+0100 (Central European Standard Time)
*/
export const __version = "2.18.1"
export const __timestamp = "2021-05-20T16:09:03.946Z"
export const __version = "2.18.4"
export const __timestamp = "2022-01-10T14:33:28.723Z"
//buildRoutes
import { buildClientTree } from "@roxi/routify/runtime/buildRoutes"
@ -24,7 +24,7 @@ export const _tree = {
"ownMeta": {
"preload": "proximity"
},
"absolutePath": "/home/dan/Documents/node_projects/mangades/src/pages/_layout.svelte",
"absolutePath": "/home/dan/projects/node/Mangades/src/pages/_layout.svelte",
"children": [
{
"isFile": true,
@ -34,7 +34,7 @@ export const _tree = {
"name": "_fallback",
"ext": "svelte",
"badExt": false,
"absolutePath": "/home/dan/Documents/node_projects/mangades/src/pages/_fallback.svelte",
"absolutePath": "/home/dan/projects/node/Mangades/src/pages/_fallback.svelte",
"importPath": "../src/pages/_fallback.svelte",
"isLayout": false,
"isReset": false,
@ -59,8 +59,85 @@ export const _tree = {
"name": "_layout",
"ext": "svelte",
"badExt": false,
"absolutePath": "/home/dan/Documents/node_projects/mangades/src/pages/[manga]/_layout.svelte",
"absolutePath": "/home/dan/projects/node/Mangades/src/pages/[manga]/_layout.svelte",
"children": [
{
"isFile": true,
"isDir": true,
"file": "_layout.svelte",
"filepath": "/[manga]/[chapter]/_layout.svelte",
"name": "_layout",
"ext": "svelte",
"badExt": false,
"absolutePath": "/home/dan/projects/node/Mangades/src/pages/[manga]/[chapter]/_layout.svelte",
"children": [
{
"isFile": true,
"isDir": false,
"file": "[page].svelte",
"filepath": "/[manga]/[chapter]/[page].svelte",
"name": "[page]",
"ext": "svelte",
"badExt": false,
"absolutePath": "/home/dan/projects/node/Mangades/src/pages/[manga]/[chapter]/[page].svelte",
"importPath": "../src/pages/[manga]/[chapter]/[page].svelte",
"isLayout": false,
"isReset": false,
"isIndex": false,
"isFallback": false,
"isPage": true,
"ownMeta": {},
"meta": {
"recursive": true,
"preload": "proximity",
"prerender": true
},
"path": "/:manga/:chapter/:page",
"id": "__manga__chapter__page",
"component": () => import('../src/pages/[manga]/[chapter]/[page].svelte').then(m => m.default)
},
{
"isFile": true,
"isDir": false,
"file": "index.svelte",
"filepath": "/[manga]/[chapter]/index.svelte",
"name": "index",
"ext": "svelte",
"badExt": false,
"absolutePath": "/home/dan/projects/node/Mangades/src/pages/[manga]/[chapter]/index.svelte",
"importPath": "../src/pages/[manga]/[chapter]/index.svelte",
"isLayout": false,
"isReset": false,
"isIndex": true,
"isFallback": false,
"isPage": true,
"ownMeta": {},
"meta": {
"recursive": true,
"preload": "proximity",
"prerender": true
},
"path": "/:manga/:chapter/index",
"id": "__manga__chapter_index",
"component": () => import('../src/pages/[manga]/[chapter]/index.svelte').then(m => m.default)
}
],
"isLayout": true,
"isReset": false,
"isIndex": false,
"isFallback": false,
"isPage": false,
"importPath": "../src/pages/[manga]/[chapter]/_layout.svelte",
"ownMeta": {},
"meta": {
"recursive": true,
"preload": "proximity",
"prerender": true
},
"path": "/:manga/:chapter",
"id": "__manga__chapter__layout",
"component": () => import('../src/pages/[manga]/[chapter]/_layout.svelte').then(m => m.default)
},
{
"isFile": true,
"isDir": false,
@ -69,7 +146,7 @@ export const _tree = {
"name": "index",
"ext": "svelte",
"badExt": false,
"absolutePath": "/home/dan/Documents/node_projects/mangades/src/pages/[manga]/index.svelte",
"absolutePath": "/home/dan/projects/node/Mangades/src/pages/[manga]/index.svelte",
"importPath": "../src/pages/[manga]/index.svelte",
"isLayout": false,
"isReset": false,
@ -111,7 +188,7 @@ export const _tree = {
"name": "index",
"ext": "svelte",
"badExt": false,
"absolutePath": "/home/dan/Documents/node_projects/mangades/src/pages/index.svelte",
"absolutePath": "/home/dan/projects/node/Mangades/src/pages/index.svelte",
"importPath": "../src/pages/index.svelte",
"isLayout": false,
"isReset": false,

View file

@ -24,27 +24,27 @@
"routify": "routify"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^19.0.0",
"@rollup/plugin-node-resolve": "^13.0.0",
"@roxi/routify": "^2.18.1",
"@types/streamsaver": "^2.0.0",
"@rollup/plugin-commonjs": "^19.0.2",
"@rollup/plugin-node-resolve": "13.0.0",
"@roxi/routify": "^2.18.4",
"@types/streamsaver": "^2.0.1",
"cross-env": "^7.0.3",
"fs-extra": "^10.0.0",
"nollup": "^0.16.4",
"nollup": "^0.16.5",
"npm-run-all": "^4.1.5",
"postcss": "^8.2.14",
"postcss-import": "^14.0.1",
"rollup": "^2.47.0",
"postcss": "^8.4.5",
"postcss-import": "^14.0.2",
"rollup": "^2.63.0",
"rollup-plugin-hot": "^0.1.1",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-livereload": "^2.0.5",
"rollup-plugin-svelte": "^7.1.0",
"rollup-plugin-svelte-hot": "^1.0.0-7",
"rollup-plugin-svelte-hot": "^1.0.0-8",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-workbox": "^5.2.1",
"spank": "^1.7.0",
"spank": "^1.9.0",
"spassr": "^2.6.0",
"svelte": "^3.38.2",
"svelte-preprocess": "^4.7.3",
"svelte": "^3.45.0",
"svelte-preprocess": "^4.10.1",
"tossr": "^1.4.2"
},
"routify": {

View file

@ -53,8 +53,7 @@ export default {
hot: isNollup,
preprocess: [
autoPreprocess({
postcss: { plugins: [postcssImport()] },
defaults: { style: 'postcss' }
postcss: { plugins: [postcssImport()] }
})
]
}),

View file

@ -26,13 +26,13 @@
</script>
<tr on:mouseenter={mouseenter} on:mousedown={click} class:selected={selected} style="background-image: linear-gradient(to right, rgba(0, 255, 0, 0.247) {progress * 100}%, transparent {progress * 100}%)">
<td class="no-wrap">{chapter.data.attributes.volume ? "Vol " + chapter.data.attributes.volume : ""}</td>
<td class="no-wrap">{chapter.data.attributes.chapter ? "Chapter " + chapter.data.attributes.chapter : ""}</td>
<td>{chapter.data.attributes.title}</td>
<td class="action no-wrap"><a href={$url("./" + chapter.data.id)} on:click|stopPropagation={() => !disabledDownload && dispatch("view")}>View</a></td>
<td class="no-wrap">{chapter.attributes.volume ? "Vol " + chapter.attributes.volume : ""}</td>
<td class="no-wrap">{chapter.attributes.chapter ? "Chapter " + chapter.attributes.chapter : ""}</td>
<td>{chapter.attributes.title}</td>
<td class="action no-wrap"><a href={$url("./" + chapter.id)} on:click|stopPropagation={() => !disabledDownload && dispatch("view")}>View</a></td>
</tr>
<style>
<style lang="postcss">
tr {
border: 1px solid black;
position: relative;

View file

@ -13,6 +13,7 @@
$: manga = scoped.manga;
var atHome = scoped.atHome;
$: atHome = scoped.atHome;
console.log("athome", atHome);
var title = manga.title.en || manga.title.jp || Object.values(manga.title)[0];
$: title = manga.title.en || manga.title.jp || Object.values(manga.title)[0];
@ -63,7 +64,7 @@
function next() {
if(!image.complete) return;
if(page > (chapter.data.attributes[quality].length - 2)) return;
if(page > (atHome.chapter[quality].length - 2)) return;
$goto("./" + (parseInt(page) + 1));
document.scrollingElement.scrollTo({
top: 0
@ -180,26 +181,26 @@
<svelte:window on:keydown={keydown} on:keyup={keyup} on:resize={isZooming} />
<svelte:head>
<title>{title} Chapter {chapter.data.attributes.chapter} Page {page}</title>
<meta name="description" value="Read page {page} of chapter {chapter.data.attributes.chapter} of {title} online. Free of charge and ads." />
<title>{title} Chapter {chapter.attributes.chapter} Page {page}</title>
<meta name="description" value="Read page {page} of chapter {chapter.attributes.chapter} of {title} online. Free of charge and ads." />
</svelte:head>
<div class="top">
<a class="back" href={$url("../..")}>Back to chapter list</a>
</div>
<img draggable={false} bind:this={image} style="height: {actualHeight}px" on:load={loaded} on:touchstart={handleTouchStart} on:touchmove={handleTouchMove} on:mousedown={mouseclick} on:mouseup={preventDefault} src={`${atHome}/${quality}/${chapter.data.attributes.hash}/${chapter.data.attributes[quality][page - 1]}`} alt="Page {page} in chapter {chapter.data.attributes.chapter} of {manga.title.en}">
<img draggable={false} bind:this={image} style="height: {actualHeight}px" on:load={loaded} on:touchstart={handleTouchStart} on:touchmove={handleTouchMove} on:mousedown={mouseclick} on:mouseup={preventDefault} src={`${atHome.baseUrl}/${quality}/${atHome.chapter.hash}/${atHome.chapter[quality][page - 1]}`} alt="Page {page} in chapter {chapter.attributes.chapter} of {manga.title.en}">
<div class="bottom">
{#if page > 1}
<a href={$url("./" + (page - 1))} class="prev">Previous</a>
{/if}
{#if page < chapter.data.attributes[quality].length - 1}
{#if page < atHome.chapter[quality].length - 1}
<a href={$url("./" + (parseInt(page) + 1))} class="next">Next</a>
{/if}
</div>
<style>
<style lang="postcss">
img {
width: calc(100vw - 16px);
height: calc(100vh - 17px);

View file

@ -12,8 +12,8 @@
async function getChapter(id) {
if(chapterData && chapterData.id === id) return chapterData;
const data = await request("chapter/" + id);
console.log(data);
return data;
console.log(data.data);
return data.data;
}
var chapterData = getChapter(chapter);
@ -21,8 +21,9 @@
async function getAtHome(id) {
if(chapterData && chapterData.id === id) return atHome;
const { baseUrl } = await request("at-home/server/" + id);
return baseUrl;
const data = await request("at-home/server/" + id);
console.log(data);
return data;
}
var atHome = getAtHome(chapter);

View file

@ -20,7 +20,8 @@
async function getMangaChapters(id) {
const data = await request("manga/" + id + "/feed?limit=500&translatedLanguage[]=en");
data.results.sort((a, b) => a.data.attributes.chapter - b.data.attributes.chapter);
console.log(data);
data.data.sort((a, b) => a.attributes.chapter - b.attributes.chapter);
return data;
}
@ -61,9 +62,9 @@
console.log(chapter, link, finished);
if(chapter === -1 || link === -1) return;
var cs = await chapters;
var related = cs.results.filter(t => processing.opts.chapters.find(c => t.data.id === c.id));
var related = cs.data.filter(t => processing.opts.chapters.find(c => t.id === c.id));
var done = processing.opts.chapters.filter(t => parseFloat(t.number) < parseFloat(processing.opts.chapters[chapter].number));
var linkCount = related.map(t => t.data.attributes[quality].length).reduce((a, b) => a + b);
var linkCount = related.map(t => t.attributes.pages).reduce((a, b) => a + b);
console.log(related, done, done.reduce((a, b) => (a.links || []).length + (b.links || []).length, 0), link + 1, linkCount);
progress = (done.reduce((a, b) => (a.links || []).length + (b.links || []).length, 0) + link + 1) / linkCount;
progressMap.set(processing.opts.chapters[chapter].id, link + 1);
@ -81,28 +82,24 @@
epub: EpubGenerator,
cbz: CBZGenerator
}
const quality = "data";
async function downloadSingle(chapter) {
const file = streamSaver.createWriteStream(`${manga.title.en} ${chapter.data.attributes.chapter}.${format}`, {
const file = streamSaver.createWriteStream(`${manga.title.en} ${chapter.attributes.chapter}.${format}`, {
writableStrategy: undefined, // (optional)
readableStrategy: undefined, // (optional)
});
const generator = new generators[format]({
file,
id: chapter.data.id,
language: chapter.data.attributes.translatedLanguage,
quality,
updatedAt: chapter.data.attributes.updatedAt,
id: chapter.id,
language: chapter.attributes.translatedLanguage,
updatedAt: chapter.attributes.updatedAt,
title: manga.title.en,
author: "Unknown",
chapters: [{
hash: chapter.data.attributes.hash,
id: chapter.data.id,
links: chapter.data.attributes[quality],
number: chapter.data.attributes.chapter,
volume: chapter.data.attributes.volume
id: chapter.id,
number: chapter.attributes.chapter,
volume: chapter.attributes.volume
}]
});
@ -127,7 +124,7 @@
}
}
function downloadMulti() {
selected.sort((a, b) => a.data.attributes.chapter - b.data.attributes.chapter);
selected.sort((a, b) => a.attributes.chapter - b.attributes.chapter);
if(!selected.length) return;
if(selected.length === 1) {
downloadSingle(selected.shift());
@ -140,18 +137,15 @@
});
const generator = new generators[format]({
file,
quality,
id: window.location.toString(),
language: selected[0].data.attributes.translatedLanguage,
language: selected[0].attributes.translatedLanguage,
updatedAt: new Date,
title: manga.title.en,
author: "Unknown",
chapters: selected.map(chapter => ({
hash: chapter.data.attributes.hash,
id: chapter.data.id,
links: chapter.data.attributes[quality],
number: chapter.data.attributes.chapter,
volume: chapter.data.attributes.volume
id: chapter.id,
number: chapter.attributes.chapter,
volume: chapter.attributes.volume
}))
});
@ -252,13 +246,13 @@
{#await chapters}
Loading chapters...
{:then chapters}
{#if chapters.results.length === 0}
{#if chapters.data.length === 0}
<p>No chapters found.</p>
{/if}
<table>
<tbody>
{#each chapters.results as chapter, i}
<Chapter progress={(progressMap.get(chapter.data.id) || 0) / chapter.data.attributes[quality].length} {chapter} disabledDownload={!!progress} selected={selected.includes(chapter)} on:select={() => select(chapter)} on:download={() => downloadSingle(chapter)} />
{#each chapters.data as chapter, i}
<Chapter progress={(progressMap.get(chapter.id) || 0) / chapter.attributes.pages} {chapter} disabledDownload={!!progress} selected={selected.includes(chapter)} on:select={() => select(chapter)} on:download={() => downloadSingle(chapter)} />
{/each}
</tbody>
</table>
@ -268,7 +262,7 @@
<br>
</main>
<style>
<style lang="postcss">
.flex {
display: flex;
justify-content: space-between;

View file

@ -2,7 +2,7 @@
import { url } from '@roxi/routify'
</script>
<style>
<style lang="postcss">
.huge {
font-size: 12rem;
}

View file

@ -15,7 +15,7 @@
</div>
{/if}
<style>
<style lang="postcss">
.flow {
position: fixed;
bottom: 0;

View file

@ -142,7 +142,7 @@
</p>
</main>
<style>
<style lang="postcss">
.filters {
display: flex;
justify-content: space-between;

View file

@ -33,18 +33,24 @@ export class BaseGenerator {
*/
constructor(opts) {
this.opts = opts;
this.opts.quality = "data";
}
async generate() {}
/**
* @param {string | Chapter | any} chapter
* @returns {Promise<string>}
* @returns {Promise<{ urls: string[], hashes: string[], hash: string[] }>}
*/
async getBaseURL(chapter) {
if(typeof chapter === "object") chapter = chapter.data.id;
const { baseUrl } = await request("at-home/server/" + chapter);
return baseUrl;
async getURLs(chapter) {
if(typeof chapter === "object") chapter = chapter.id;
const data = await request("at-home/server/" + chapter);
console.log(data, this.opts);
return {
urls: data.chapter[this.opts.quality].map(t => `${data.baseUrl}/${this.opts.quality}/${data.chapter.hash}/${t}`),
hashes: data.chapter[this.opts.quality],
hash: data.chapter.hash
}
}
/**
@ -55,14 +61,14 @@ export class BaseGenerator {
async fetchImage(url, chapter) {
var res;
try {
res = await fetch(chapter.baseUrl + "/" + url);
res = await fetch(url);
} catch(e) {
console.error(e);
res = await fetch(proxy + chapter.baseUrl + "/" + url);
res = await fetch(proxy + url);
}
if(Math.floor(res.status / 100) !== 2) {
for(var i = 0; i < RETRY_LIMIT; i++) {
chapter.baseUrl = await this.getBaseURL(chapter);
chapter.baseUrl = await this.getURLs(chapter);
res = await fetch(chapter.baseUrl + "/" + url);
if(Math.floor(res.status / 100) === 2) return res;
}

View file

@ -25,14 +25,19 @@ export class CBZGenerator extends BaseGenerator {
const chapterCountLength = this.opts.chapters.reduce((a, b) => Math.max(a.number, b.number), 0).toString().length;
for(const chapterI in this.opts.chapters) {
const chapter = this.opts.chapters[chapterI];
if(!chapter.baseUrl) chapter.baseUrl = await this.getBaseURL(chapter.id);
if(!chapter.links) {
let data = await this.getURLs(chapter);
chapter.links = data.urls;
chapter.hashes = data.hashes;
chapter.hash = data.hash;
}
const imageCountLength = chapter.links.length.toString().length;
for(const i in chapter.links) {
let url = chapter.links[i];
let hash = chapter.hashes[i];
this.callback(chapterI, i, false);
const hash = chapter.links[i];
const URL = `${this.opts.quality}/${chapter.hash}/${hash}`;
const start = performance.now();
const res = await this.fetchImage(URL, chapter);
const res = await this.fetchImage(url, chapter);
const chapterText = chapter.number.toString().padStart(chapterCountLength, "0");
const image = new ZipPassThrough(`${this.opts.title} ${chapterText}/${this.opts.title} ${chapterText} page ${i.toString().padStart(imageCountLength, "0")}.${hash.substr(hash.lastIndexOf(".") + 1)}`);
this.zip.add(image);
@ -43,7 +48,7 @@ export class CBZGenerator extends BaseGenerator {
cached: res.headers.get("X-Cache") === "HIT",
duration: end,
success: Math.floor(res.status / 100) === 2,
url: `${chapter.baseUrl}/${URL}`
url
});
image.push(data, true);
this.callback(chapterI, i, true);

View file

@ -25,7 +25,19 @@ export class EpubGenerator extends BaseGenerator {
}
};
this.hashes = this.opts.chapters.map(t => t.links).flat();
this.hashes = [];
for(const chapterI in this.opts.chapters) {
const chapter = this.opts.chapters[chapterI];
if(!chapter.links) {
let data = await this.getURLs(chapter);
chapter.links = data.urls;
chapter.hashes = data.hashes;
chapter.hash = data.hash;
this.hashes.push(...chapter.hashes);
}
}
this.mimetype();
this.container();
@ -36,13 +48,12 @@ export class EpubGenerator extends BaseGenerator {
for(const chapterI in this.opts.chapters) {
const chapter = this.opts.chapters[chapterI];
if(!chapter.baseUrl) chapter.baseUrl = await this.getBaseURL(chapter.id);
for(const i in chapter.links) {
let url = chapter.links[i];
let hash = chapter.hashes[i];
this.callback(chapterI, i, false);
const hash = chapter.links[i];
const URL = `${this.opts.quality}/${chapter.hash}/${hash}`;
const start = performance.now();
const res = await this.fetchImage(URL, chapter);
const res = await this.fetchImage(url, chapter);
const image = new ZipPassThrough("OEBPS/" + hash);
this.zip.add(image);
const data = new Uint8Array(await res.arrayBuffer());
@ -52,7 +63,7 @@ export class EpubGenerator extends BaseGenerator {
cached: res.headers.get("X-Cache") === "HIT",
duration: end,
success: Math.floor(res.status / 100) === 2,
url: `${chapter.baseUrl}/${URL}`
url: url
});
image.push(data, true);
const textContent = new ZipPassThrough("OEBPS/" + i + ".xhtml");