feat(userscript): add kagane.to site adapter
This commit is contained in:
@@ -57,6 +57,7 @@ const {
|
||||
asura,
|
||||
demonic,
|
||||
comix,
|
||||
kagane,
|
||||
anchorsFromHTML,
|
||||
statusOf,
|
||||
} = require("../manga-bookmark.user.js");
|
||||
@@ -274,6 +275,90 @@ test("asura and demonic ignore the seriesId argument", () => {
|
||||
});
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// kagane — reader URLs carry uuids and no chapter number, so the number has to
|
||||
// come out of og:title. When that fails, chapterNum is null and the existing
|
||||
// progress logic records the current chapter rather than guessing.
|
||||
// ============================================================
|
||||
|
||||
const KAGANE_SERIES = "019f84bc-9ba0-7ed9-86f5-8b905ec7c28b";
|
||||
const KAGANE_BOOK = "019fa2e0-6dbd-73ca-b40b-fe06ab75eb0e";
|
||||
|
||||
test("kagane detects a series page", () => {
|
||||
metaTags = {
|
||||
"og:title": "Infinite Decryption: The Strongest Level 0",
|
||||
"og:image": "https://kagane.to/api/v2/image/abc/compressed",
|
||||
};
|
||||
const p = kagane.detect(loc("https://kagane.to/series/" + KAGANE_SERIES));
|
||||
assert.equal(p.type, "series");
|
||||
assert.equal(p.site, "kagane");
|
||||
assert.equal(p.seriesId, KAGANE_SERIES);
|
||||
assert.equal(p.title, "Infinite Decryption: The Strongest Level 0");
|
||||
assert.equal(p.cover, "https://kagane.to/api/v2/image/abc/compressed");
|
||||
assert.equal(p.seriesUrl, "https://kagane.to/series/" + KAGANE_SERIES);
|
||||
});
|
||||
|
||||
test("kagane reads the chapter number out of og:title", () => {
|
||||
metaTags = {
|
||||
"og:title": "Infinite Decryption: The Strongest Level 0 - Chapter 41 - Episode 41",
|
||||
"og:image": "https://kagane.to/api/v2/image/abc/compressed",
|
||||
};
|
||||
const p = kagane.detect(
|
||||
loc("https://kagane.to/series/" + KAGANE_SERIES + "/reader/" + KAGANE_BOOK)
|
||||
);
|
||||
assert.equal(p.type, "chapter");
|
||||
assert.equal(p.seriesId, KAGANE_SERIES);
|
||||
assert.equal(p.title, "Infinite Decryption: The Strongest Level 0");
|
||||
assert.equal(p.chapterNum, 41);
|
||||
assert.equal(p.chapterLabel, "Chapter 41");
|
||||
assert.equal(p.seriesUrl, "https://kagane.to/series/" + KAGANE_SERIES);
|
||||
});
|
||||
|
||||
test("kagane yields a null chapterNum when og:title has no chapter", () => {
|
||||
metaTags = { "og:title": "Infinite Decryption: The Strongest Level 0" };
|
||||
const p = kagane.detect(
|
||||
loc("https://kagane.to/series/" + KAGANE_SERIES + "/reader/" + KAGANE_BOOK)
|
||||
);
|
||||
assert.equal(p.type, "chapter");
|
||||
assert.equal(p.chapterNum, null);
|
||||
});
|
||||
|
||||
test("kagane ignores unrelated paths", () => {
|
||||
assert.equal(kagane.detect(loc("https://kagane.to/search")).type, "other");
|
||||
});
|
||||
|
||||
test("kagane anchor scanning is structurally impossible and returns null", () => {
|
||||
const anchors = anchorsFromHTML(
|
||||
`<a href="/series/${KAGANE_SERIES}/reader/${KAGANE_BOOK}">Chapter 41</a>`
|
||||
);
|
||||
assert.equal(kagane.latestChapterFromAnchors(anchors, KAGANE_SERIES), null);
|
||||
});
|
||||
|
||||
test("kagane latestChapterFromApi takes the max chapter_no", async () => {
|
||||
globalThis.fetch = async (url) => {
|
||||
assert.equal(url, "/api/v2/series/" + KAGANE_SERIES);
|
||||
return {
|
||||
ok: true,
|
||||
json: async () => ({
|
||||
series_books: [
|
||||
{ chapter_no: "1", title: "Episode 1" },
|
||||
{ chapter_no: "41", title: "Episode 41" },
|
||||
{ chapter_no: "40.5", title: "Episode 40.5" },
|
||||
],
|
||||
}),
|
||||
};
|
||||
};
|
||||
assert.deepEqual(await kagane.latestChapterFromApi(KAGANE_SERIES), {
|
||||
num: 41,
|
||||
label: "Chapter 41",
|
||||
});
|
||||
});
|
||||
|
||||
test("kagane latestChapterFromApi returns null on a challenge or error", async () => {
|
||||
globalThis.fetch = async () => ({ ok: false, status: 403 });
|
||||
assert.equal(await kagane.latestChapterFromApi(KAGANE_SERIES), null);
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// Shared helpers
|
||||
// ============================================================
|
||||
|
||||
Reference in New Issue
Block a user