-
Notifications
You must be signed in to change notification settings - Fork 0
/
metadata.ts
138 lines (115 loc) · 3.86 KB
/
metadata.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import { DOMParser } from "https://deno.land/x/[email protected]/deno-dom-wasm.ts";
const MANGA_BASEURL = "https://mangasee123.com/manga/";
const NOT_FOUND_STRING = "We're sorry, the page you rquested could not be found.";
export async function getMangaPage(mangaIndexName: string) {
const res = await fetch(MANGA_BASEURL + mangaIndexName);
return await res.text();
}
export interface BasicMangaMetadata {
title: string;
authors: string[];
genres: string[];
type: string;
release_year: string;
ongoing: boolean;
description: string;
chapters_available: number;
}
export async function getBasicMetadata(mangaIndexName: string) {
const html_document = await getMangaPage(mangaIndexName);
return extractMetadata(html_document);
}
export function extractMetadata(html_document: string) {
const document = new DOMParser().parseFromString(html_document, "text/html");
if (document == null || document?.querySelector(".top-15.bottom-15")?.innerText.includes(NOT_FOUND_STRING)) return undefined;
const metadata_list = document.querySelector(".list-group.list-group-flush");
if (metadata_list == null) return undefined;
const metadata: BasicMangaMetadata = {
title: metadata_list.querySelector("h1")?.innerText as string,
authors: [],
genres: [],
type: "",
release_year: "",
ongoing: true,
description: "",
chapters_available: JSON.parse(html_document.match(/vm\.Chapters = (.+);/m)?.[1] || "[]")?.length || 0,
};
for (const child of metadata_list.children || []) {
const label = child.querySelector(".mlabel");
switch (label?.innerText) {
case "Author(s):": {
child.querySelectorAll("a").forEach((a) => {
//@ts-ignore property innerText does exist but is not in the Interface/Declaration
metadata.authors.push(a.innerText);
});
continue;
}
case "Genre(s):": {
child.querySelectorAll("a").forEach((a) => {
//@ts-ignore property innerText does exist but is not in the Interface/Declaration
metadata.genres.push(a.innerText);
});
continue;
}
case "Type:": {
metadata.type = child.querySelector("a")?.innerText as string;
continue;
}
case "Released:": {
metadata.release_year = child.querySelector("a")?.innerText as string;
continue;
}
case "Status:": {
metadata.ongoing = child.innerText.includes("Ongoing");
continue;
}
case "Description:": {
metadata.description = child.querySelector(".top-5.Content")?.innerText as string;
continue;
}
default:
continue;
}
}
return metadata;
}
export interface Chapter {
pretype: number;
main: number;
sub: number;
raw: string;
}
export async function getChapters(mangaIndexName: string) {
const html_document = await getMangaPage(mangaIndexName);
return extractChapters(html_document);
}
export function extractChapters(html_document: string) {
const raw_chapters: Array<{ Chapter: string }> = JSON.parse(html_document.match(/vm\.Chapters = (.+);/m)?.[1] || "[]");
const parsed: Chapter[] = [];
for (const chapter of raw_chapters) {
const match = chapter.Chapter.match(/(\d)(\d{4})(\d)/);
if (match == null) continue;
parsed.push({
pretype: parseInt(match[1]),
main: parseInt(match[2]),
sub: parseInt(match[3]),
raw: chapter.Chapter,
});
}
return parsed;
}
export interface FullMangaMetadata {
basic: BasicMangaMetadata;
chapters: Chapter[];
}
export async function getFullMetadata(mangaIndexName: string) {
const html_document = await getMangaPage(mangaIndexName);
const basic = extractMetadata(html_document);
const chapters = extractChapters(html_document);
if (basic == undefined) return null;
const full_metadata: FullMangaMetadata = {
basic,
chapters,
};
return full_metadata;
}