-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild.ts
187 lines (162 loc) · 6.3 KB
/
build.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import * as path from 'path';
import { readdirSync, existsSync } from 'fs';
import { Renderer } from './ryuji.js';
import { Builder } from './saki.js';
import _favourites_info from './favourites_info.json';
//todo: music?
interface FavouritesInfo {
favourites: {
listing: boolean; //whether to mark entire listing as favourite
chapters: string[]; //favourite chapters
};
}
interface Listing extends FavouritesInfo {
name: string;
type: "anime" | "manga" | "music";
}
interface DirectoryVars {
listing: Listing;
chapters: string[]; //name of all the chapters
}
interface ListingVars {
listing: Listing;
chapter: string;
next_chapter?: string | boolean;
prev_chapter?: string | boolean;
}
type MusicVars = ListingVars;
interface AnimeVars extends ListingVars {
higher_quality_available: boolean;
};
interface MangaVars extends ListingVars {
images: string[]; //file names of all the images in the chapter
}
const favourites_info: Record<string, FavouritesInfo> = _favourites_info;
let listings: Listing[] = [];
//add listings from static_assets/anime_assets
for (let listing_type of ["anime", "manga", "music"]) {
listings.push(...readdirSync(path.join(__dirname, `/static_assets/${listing_type}_assets`)).map(
(listing_name: string) =>
({
name: listing_name,
type: listing_type,
favourites: {
listing: favourites_info[`${listing_type}-${listing_name}`] ? favourites_info[`${listing_type}-${listing_name}`].favourites.listing : false,
chapters: favourites_info[`${listing_type}-${listing_name}`] ? favourites_info[`${listing_type}-${listing_name}`].favourites.chapters : [],
}
})
).filter(
(listing: any): listing is Listing =>
typeof listing.name === "string" && (listing?.type === "anime" || listing?.type === "manga" || listing?.type === "music")
));
}
//get playlists if any (will add to player at a later step)
let playlists: string[] = [];
if (existsSync(path.join(__dirname, "/static_assets/playlists"))) {
playlists.push(...readdirSync(path.join(__dirname, "/static_assets/playlists")).map((name: string) => name));
}
let renderer: Renderer = new Renderer("templates", "components");
let builder: Builder = new Builder("/build");
//static page
builder.serve_static_folder("static");
//main page
builder.serve_template(renderer, "/", "index", {
listings,
});
//directories, anime, manga
let directory_serve_paths: string[] = [];
let directory_vars: DirectoryVars[] = [];
let anime_serve_paths: string[] = [];
let anime_vars: AnimeVars[] = [];
let manga_serve_paths: string[] = [];
let manga_vars: MangaVars[] = [];
let music_serve_paths: string[] = [];
let music_vars: MusicVars[] = [];
let songs: string[] = [];
let manga_pages_count: number = 0;
let subbed_songs = [];
for (let i = 0; i < listings.length; i++) {
const listing: Listing = listings[i];
directory_serve_paths.push(`/${listing.type}/${listing.name}`);
const chapters: string[] = readdirSync(path.join(__dirname, `/static_assets/${listing.type}_assets/${listing.name}`), { withFileTypes: true }).map((d) => d.name.replace(".mp4", "").replace(".mp3", "")).filter(
(chapter: string) =>
!(listing.type === "anime" && chapter.endsWith("_higher_quality"))
); //filter out the higher quality anime videos, we want those to be on the same page as the low quality (select quality with dropdown), not listed as a separate episode
directory_vars.push({
listing,
chapters,
});
for (let j = 0; j < chapters.length; j++) {
const chapter: string = chapters[j];
const base = {
listing,
chapter,
next_chapter: chapters[j + 1] ? chapters[j + 1] : false,
prev_chapter: j > 0 ? chapters[j - 1] : false,
};
const serve_path = `/${listing.type}/${listing.name}/${chapter}`;
if (listing.type === "anime") {
anime_serve_paths.push(serve_path);
anime_vars.push({
...base,
higher_quality_available: existsSync(path.join(__dirname, `/static_assets/${listing.type}_assets/${listing.name}`, `${chapter}_higher_quality.mp4`)),
});
} else if (listing.type === "manga") {
manga_serve_paths.push(serve_path);
const images: string[] = readdirSync(path.join(__dirname, `/static_assets/${listing.type}_assets/${listing.name}/${chapter}`), { withFileTypes: true }).map((d) => d.name);
manga_pages_count += images.length;
manga_vars.push({
...base,
images,
});
} else if (listing.type === "music") {
music_serve_paths.push(serve_path);
songs.push(`${listing.name}/${chapter}`);
music_vars.push({
...base,
});
if (existsSync(path.join(__dirname, `/static_assets/music_subtitle_assets/${listing.name}/${chapter}.vtt`))) {
subbed_songs.push(`${listing.name}/${chapter}`);
}
}
//
}
}
builder.serve_templates(renderer, directory_serve_paths, "directory", directory_vars);
builder.serve_templates(renderer, anime_serve_paths, "anime", anime_vars);
builder.serve_templates(renderer, manga_serve_paths, "manga", manga_vars);
builder.serve_templates(renderer, music_serve_paths, "music", music_vars);
builder.serve_template(renderer, "/stats", "stats", {
manga_series_count: listings.filter((l) => l.type === "manga").length,
manga_chapters_count: manga_serve_paths.length,
manga_pages_count,
anime_series_count: listings.filter((l) => l.type === "anime").length,
anime_episodes_count: anime_serve_paths.length,
artists_count: listings.filter((l) => l.type === "music").length,
songs_count: songs.length,
sub_count: subbed_songs.length,
});
builder.serve_template(renderer, "/player", "player", {
playlists,
songs,
artists: listings.filter((l) => l.type === "music").map(
(l) => (
{
name: l.name,
sanitized_name: l.name.replaceAll("\"", "\\\""),
songs: songs.filter((s) => s.startsWith(`${l.name}/`)).map(
(song) => (
{
name: song.slice(`${l.name}/`.length),
//I don't think " can be in file names... but just in case
sanitized_name: song.slice(`${l.name}/`.length).replaceAll("\"", "\\\""),
favourite: l.favourites.chapters.includes(song.slice(`${l.name}/`.length)),
subbed: subbed_songs.includes(song),
}
)
),
favourite: l.favourites.listing,
}
)
),
});