feat(userscript): add kagane.to site adapter
This commit is contained in:
@@ -292,7 +292,86 @@
|
||||
},
|
||||
};
|
||||
|
||||
const ADAPTERS = [asura, demonic, comix];
|
||||
const kagane = {
|
||||
site: "kagane",
|
||||
matches: (loc) => /(^|\.)kagane\.to$/.test(loc.hostname),
|
||||
detect(loc) {
|
||||
const path = loc.pathname;
|
||||
const UUID = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
|
||||
// /series/<uuid>/reader/<bookUuid> — no chapter number anywhere in the
|
||||
// URL, so it comes out of og:title instead.
|
||||
let m = path.match(new RegExp("^/series/(" + UUID + ")/reader/" + UUID));
|
||||
if (m) {
|
||||
const num = chapterNumFromTitle(meta("og:title"));
|
||||
return {
|
||||
type: "chapter",
|
||||
site: this.site,
|
||||
seriesId: m[1],
|
||||
title: cleanTitle(meta("og:title")),
|
||||
cover: meta("og:image") || "",
|
||||
seriesUrl: loc.origin + "/series/" + m[1],
|
||||
chapterLabel: num === null ? null : "Chapter " + num,
|
||||
chapterNum: num,
|
||||
chapterUrl: loc.href,
|
||||
};
|
||||
}
|
||||
// /series/<uuid>
|
||||
m = path.match(new RegExp("^/series/(" + UUID + ")/?$"));
|
||||
if (m) {
|
||||
return {
|
||||
type: "series",
|
||||
site: this.site,
|
||||
seriesId: m[1],
|
||||
title: cleanTitle(meta("og:title")),
|
||||
cover: meta("og:image") || "",
|
||||
seriesUrl: loc.origin + "/series/" + m[1],
|
||||
chapterLabel: null,
|
||||
chapterNum: null,
|
||||
chapterUrl: null,
|
||||
};
|
||||
}
|
||||
return { type: "other" };
|
||||
|
||||
// Reader og:title is "<Title> - Chapter <n> - <episode name>".
|
||||
function chapterNumFromTitle(t) {
|
||||
const m = t && t.match(/\s-\sChapter\s([\d.]+)\s/);
|
||||
if (!m) return null;
|
||||
const num = parseFloat(m[1]);
|
||||
return isNaN(num) ? null : num;
|
||||
}
|
||||
|
||||
function cleanTitle(t) {
|
||||
if (!t) return "";
|
||||
return t.replace(/\s-\sChapter\s[\d.]+\s-\s.*$/i, "").trim();
|
||||
}
|
||||
},
|
||||
// Reader hrefs are uuids with no number in them, so no maximum can be taken
|
||||
// from anchors at all. latestChapterFromApi replaces this path entirely.
|
||||
latestChapterFromAnchors() {
|
||||
return null;
|
||||
},
|
||||
// Same-origin only: the request needs the Cloudflare clearance cookie that
|
||||
// this browser already holds for kagane.to. Called cross-origin it would be
|
||||
// challenged and return nothing.
|
||||
async latestChapterFromApi(seriesId) {
|
||||
try {
|
||||
const res = await fetch("/api/v2/series/" + seriesId);
|
||||
if (!res.ok) return null;
|
||||
const data = await res.json();
|
||||
let best = null;
|
||||
for (const b of (data && data.series_books) || []) {
|
||||
const num = parseFloat(b.chapter_no);
|
||||
if (isNaN(num)) continue;
|
||||
if (!best || num > best.num) best = { num, label: "Chapter " + b.chapter_no };
|
||||
}
|
||||
return best;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const ADAPTERS = [asura, demonic, comix, kagane];
|
||||
|
||||
function detect() {
|
||||
const loc = window.location;
|
||||
@@ -1694,7 +1773,7 @@
|
||||
// Exposes pure logic only — see userscript/test/logic.test.js.
|
||||
// ============================================================
|
||||
if (typeof window === "undefined" && typeof module === "object" && module.exports) {
|
||||
module.exports = { stripBuildHash, comixSeriesId, asura, demonic, comix, anchorsFromHTML, statusOf };
|
||||
module.exports = { stripBuildHash, comixSeriesId, asura, demonic, comix, kagane, anchorsFromHTML, statusOf };
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
|
||||
Reference in New Issue
Block a user