source/mangadex/mangadex.js
2026-01-09 20:44:54 +00:00

163 lines
5.7 KiB
JavaScript

async function searchContent(keyword, page=0) {
const results = [];
try {
const offset = page * 100;
const response = await fetch(`https://api.mangadex.org/manga?title=${encodeURIComponent(keyword)}&limit=100&offset=${offset}&contentRating[]=safe&contentRating[]=suggestive&contentRating[]=erotica&includes[]=cover_art&order[followedCount]=desc&order[relevance]=desc`);
const data = await response.json();
if (data.result === 'ok' && data.data) {
for (const manga of data.data) {
const id = manga.id;
const attributes = manga.attributes;
let title = attributes.title.en || attributes.title['en'];
if (!title) {
const altTitles = attributes.altTitles || [];
for (const alt of altTitles) {
if (alt.en) {
title = alt.en;
break;
}
}
}
if (!title) {
title = Object.values(attributes.title)[0] || 'Unknown Title';
}
let imageURL = '';
const relationships = manga.relationships || [];
const coverArt = relationships.find(rel => rel.type === 'cover_art');
if (coverArt && coverArt.attributes && coverArt.attributes.fileName) {
imageURL = `https://mangadex.org/covers/${id}/${coverArt.attributes.fileName}`;
}
results.push({
id: id,
imageURL: imageURL,
title: title
});
}
}
return results;
} catch (err) {
console.error(err);
return [];
}
}
async function getContentData(ID) {
try {
const response = await fetch(`https://api.mangadex.org/manga/${ID}?includes[]=artist&includes[]=author&includes[]=cover_art`);
const data = await response.json();
if (data.result === 'ok' && data.data) {
const attributes = data.data.attributes;
const description = attributes.description?.en || attributes.description?.['en'] || Object.values(attributes.description || {})[0] || '';
const tags = (attributes.tags || []).map(tag => tag.attributes?.name?.en || tag.attributes?.name?.['en'] || Object.values(tag.attributes?.name || {})[0] || '').filter(Boolean);
return {
description: description,
tags: tags
};
}
return {
description: "",
tags: []
};
} catch (err) {
console.error(err);
return {
description: "Error",
tags: []
};
}
}
async function getChapters(url) {
const results = [];
try {
const limit = 100;
let offset = 0;
let total = 0;
const allChapters = [];
do {
const response = await fetch(`https://api.mangadex.org/manga/${url}/feed?limit=${limit}&offset=${offset}&includes[]=scanlation_group&includes[]=user&contentRating[]=safe&contentRating[]=suggestive&contentRating[]=erotica&contentRating[]=pornographic&excludeExternalUrl=blinktoon.com&order[chapter]=asc&includeUnavailable=0`);
const data = await response.json();
if (data.result === 'ok' && data.data) {
allChapters.push(...data.data);
total = data.total;
offset += limit;
} else {
break;
}
} while (offset < total && allChapters.length < total);
const chapters = {};
for (const ch of allChapters) {
const lang = ch.attributes.translatedLanguage;
if (!chapters[lang]) {
chapters[lang] = [];
}
const chapterNum = ch.attributes.chapter;
const chapterFloat = parseFloat(chapterNum) || 0;
const scanlationGroupRel = ch.relationships.find(rel => rel.type === 'scanlation_group');
const scanlationGroup = scanlationGroupRel ? scanlationGroupRel.attributes.name : '';
const title = ch.attributes.title || `Chapter ${chapterNum}`;
chapters[lang].push({
id: ch.id,
title: title + ` - Language: ${lang}`,
chapter: chapterFloat,
scanlation_group: scanlationGroup,
language: lang
});
}
for (const lang in chapters) {
chapters[lang].sort((a, b) => a.chapter - b.chapter);
}
const results = {};
for (const lang in chapters) {
results[lang] = chapters[lang].map(ch => [
ch.chapter.toString(),
[{
id: ch.id,
title: ch.title,
chapter: ch.chapter,
scanlation_group: ch.scanlation_group
}]
]);
}
return results;
} catch (err) {
console.error(err);
return { en: [] };
}
}
async function getChapterImages(chapterId) {
try {
const apiEndpoint = `https://api.mangadex.org/at-home/server/${chapterId}`;
const apiResponse = await fetch(apiEndpoint);
const serverData = await apiResponse.json();
const { baseUrl: imageBaseUrl, chapter: { hash: chapterHash, data: imageFiles } } = serverData;
console.log(serverData);
return imageFiles.map(fileName => `${imageBaseUrl}/data/${chapterHash}/${fileName}`);
} catch (error) {
console.log(error.message);
return [];
}
}