Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeZeDev committed Nov 24, 2024
1 parent c7aae46 commit c344fb7
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 126 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ cache
/redist/*.zip
/test/*.log
junit.xml
.idea/
.idea/
.vs
147 changes: 110 additions & 37 deletions src/web/mjs/connectors/Cuutruyen.mjs
Original file line number Diff line number Diff line change
@@ -1,62 +1,135 @@
import Connector from '../engine/Connector.mjs';
import Manga from '../engine/Manga.mjs';

export default class Cuutruyen extends Connector {

export default class CuuTruyen extends Connector {
constructor() {
super();
super.id = 'cuutruyen';
super.label = 'Cuutruyen';
this.tags = [ 'manga', 'vietnamese' ];
super.label = 'Cứu Truyện';
this.tags = ['manga', 'vietnamese'];
this.url = 'https://cuutruyen.net';
this.api = 'https://kakarot.cuutruyen.net';
}

async _getMangaFromURI(uri) {
const mangaid = uri.href.match(/\/mangas\/([0-9]+)/)[1];
const req = new URL('/api/v1/mangas/'+mangaid, this.api);
const mangaid = uri.href.match(/\/mangas\/([0-9]+)/)[1];
const req = new URL(`/api/v2/mangas/${mangaid}`, this.url);
const request = new Request(req, this.requestOptions);
const data = await this.fetchJSON(request);
return new Manga(this, mangaid, data.data.attributes.name.trim());
const { data: { name } } = await this.fetchJSON(request);
return new Manga(this, mangaid, name.trim());
}

async _getMangas() {
let mangaList = [];
for (let page = 1, run = true; run; page++) {
const mangas = await this._getMangasFromPage(page);
mangas.length > 0 ? mangaList.push(...mangas) : run = false;
const uri = new URL('/api/v2/mangas/recently_updated?page=1&per_page=30', this.url);
const request = new Request(uri, this.requestOptions);
const data = await this.fetchJSON(request);
const pages = data._metadata.total_pages;

const mangaList = this._getMangasFromPage(data);

for (let page = 2; page <= pages; page++) {
const uri = new URL(`/api/v2/mangas/recently_updated?page=${page}&per_page=30`, this.url);
const request = new Request(uri, this.requestOptions);
const data = await this.fetchJSON(request);
const mangas = this._getMangasFromPage(data);
mangaList.push(...mangas);
}
return mangaList;
}
async _getMangasFromPage(page) {
const uri = new URL('/api/v1/mangas?page[size]=50&page[number]='+page, this.api);
const request = new Request(uri, this.requestOptions);
const data = await this.fetchJSON(request);
return data.data.map(element => {
return {
id: element.id,
title: element.attributes.name.trim()
};
});

_getMangasFromPage(data) {
return data.data.map((c) => ({
id: c.id,
title: c.name.trim(),
}));
}

async _getChapters(manga) {
const uri = new URL('/api/v1/chapter_listings/'+manga.id, this.api);
const uri = new URL(`/api/v2/mangas/${manga.id}/chapters`, this.url);
const request = new Request(uri, this.requestOptions);
const data = await this.fetchJSON(request);
const chapters = JSON.parse(data.data.attributes.chapters);
return chapters.map(element => {
return {
id: element.id,
title: 'Chapter '+ element.number + ' '+ element.name.trim()
};
});
const { data } = await this.fetchJSON(request);
return data
.filter((chapter) => chapter.status === 'processed')
.map((chapter) => {
let title = `Chapter ${chapter.number}`;

if (chapter.name) {
title += `: ${chapter.name}`;
}

return { id: chapter.id, title };
});
}

async _getPages(chapter) {
const uri = new URL('/api/v1/readings/'+chapter.id, this.api);
const uri = new URL('/api/v2/chapters/' + chapter.id, this.url);
const request = new Request(uri, this.requestOptions);
const data = await this.fetchJSON(request);
const pages = JSON.parse(data.data.attributes.pages);
return pages.map(image => this.getAbsolutePath(image.imageUrl, request.url));
const { data: { pages } } = await this.fetchJSON(request);

if (pages.some((image) => image.status !== 'processed')) {
throw new Error('This chapter is still processing, please try again later.');
}

return pages.map((image) => {
return this.createConnectorURI({
url: image.image_url,
drmData: image.drm_data,
});
});
}

async _handleConnectorURI(payload) {
const response = await fetch(payload.url, {
cache: 'no-cache',
referrer: `${this.url}/`,
headers: {
'accept': 'image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5',
},
});

if (!payload.drmData) {
return this._blobToBuffer(await response.blob());
}

const decryptedDrmData = this.decodeXorCipher(atob(payload.drmData), '3141592653589793');

if (!decryptedDrmData.startsWith('#v4|')) {
throw new Error(`Invalid DRM data (does not start with magic bytes): ${decryptedDrmData}`);
}

}
const image = await createImageBitmap(await response.blob());
const canvas = document.createElement('canvas');

canvas.width = image.width;
canvas.height = image.height;

const ctx = canvas.getContext('2d');
let sy = 0;

for (const t of decryptedDrmData.split('|').slice(1)) {
const [dy, height] = t.split('-', 2).map(Number);

ctx.drawImage(image, 0, sy, image.width, height, 0, dy, image.width, height);
sy += height;
}

return this._blobToBuffer(await this._canvasToBlob(canvas));
}

_canvasToBlob(canvas) {
return new Promise(resolve => {
canvas.toBlob(data => {
resolve(data);
}, Engine.Settings.recompressionFormat.value, parseFloat(Engine.Settings.recompressionQuality.value) / 100);
});
}

decodeXorCipher(data, key) {
let output = "";

for (let i = 0; i < data.length; i++) {
output += String.fromCharCode(data.charCodeAt(i) ^ key.charCodeAt(i % key.length));
}

return output;
}
}
Loading

0 comments on commit c344fb7

Please sign in to comment.