music draft
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
The most legalest private file (specifically manga and anime) hosting ever, on TOR. Includes a manga viewer. Nothing fancy. Uses HTTP Basic Authentication with daily rotating password derived from a master password.
|
The most legalest private file (specifically for manga, anime, music) hosting ever, on TOR. Includes a manga viewer. Nothing fancy. Uses HTTP Basic Authentication with daily rotating password derived from a master password.
|
||||||
|
|
||||||
Most of the code is a modification of [hedgeblog](https://github.com/jetstream0/hedgeblog), albeit with some pretty significant modifications in places (templates, host.ts, build.ts, saki.ts).
|
Most of the code is a modification of [hedgeblog](https://github.com/jetstream0/hedgeblog), albeit with some pretty significant modifications in places (templates, host.ts, build.ts, saki.ts).
|
||||||
|
|
||||||
|
|||||||
23
build.ts
23
build.ts
@@ -8,7 +8,7 @@ import _host_info from './host_info.json';
|
|||||||
|
|
||||||
interface Listing {
|
interface Listing {
|
||||||
name: string;
|
name: string;
|
||||||
type: "anime" | "manga";
|
type: "anime" | "manga" | "music";
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DirectoryVars {
|
interface DirectoryVars {
|
||||||
@@ -23,6 +23,8 @@ interface AnimeVars {
|
|||||||
prev_chapter?: string | boolean;
|
prev_chapter?: string | boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MusicVars = AnimeVars;
|
||||||
|
|
||||||
interface MangaVars {
|
interface MangaVars {
|
||||||
listing: Listing;
|
listing: Listing;
|
||||||
chapter: string;
|
chapter: string;
|
||||||
@@ -31,7 +33,7 @@ interface MangaVars {
|
|||||||
prev_chapter?: string | boolean;
|
prev_chapter?: string | boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const listings: Listing[] = _host_info.listings.filter((listing: any): listing is Listing => typeof listing.name === "string" && (listing?.type === "anime" || listing?.type === "manga"));
|
const listings: Listing[] = _host_info.listings.filter((listing: any): listing is Listing => typeof listing.name === "string" && (listing?.type === "anime" || listing?.type === "manga" || listing?.type === "music"));
|
||||||
|
|
||||||
let renderer: Renderer = new Renderer("templates", "components");
|
let renderer: Renderer = new Renderer("templates", "components");
|
||||||
let builder: Builder;
|
let builder: Builder;
|
||||||
@@ -61,10 +63,13 @@ let anime_vars: AnimeVars[] = [];
|
|||||||
let manga_serve_paths: string[] = [];
|
let manga_serve_paths: string[] = [];
|
||||||
let manga_vars: MangaVars[] = [];
|
let manga_vars: MangaVars[] = [];
|
||||||
|
|
||||||
|
let music_serve_paths: string[] = [];
|
||||||
|
let music_vars: MusicVars[] = [];
|
||||||
|
|
||||||
for (let i = 0; i < listings.length; i++) {
|
for (let i = 0; i < listings.length; i++) {
|
||||||
const listing: Listing = listings[i];
|
const listing: Listing = listings[i];
|
||||||
directory_serve_paths.push(`/${listing.type}/${listing.name}`);
|
directory_serve_paths.push(`/${listing.type}/${listing.name}`);
|
||||||
const chapters: string[] = readdirSync(path.join(__dirname, `/static/${listing.type}_assets/${listing.name}`), { withFileTypes: true }).map((d) => d.name.replace(".mp4", ""));
|
const chapters: string[] = readdirSync(path.join(__dirname, `/static/${listing.type}_assets/${listing.name}`), { withFileTypes: true }).map((d) => d.name.replace(".mp4", "").replace(".mp3", ""));
|
||||||
directory_vars.push({
|
directory_vars.push({
|
||||||
listing,
|
listing,
|
||||||
chapters,
|
chapters,
|
||||||
@@ -93,9 +98,21 @@ for (let i = 0; i < listings.length; i++) {
|
|||||||
prev_chapter: j > 0 ? chapters[j - 1] : false,
|
prev_chapter: j > 0 ? chapters[j - 1] : false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} else if (listing.type === "music") {
|
||||||
|
for (let j = 0; j < chapters.length; j++) {
|
||||||
|
const chapter: string = chapters[j];
|
||||||
|
music_serve_paths.push(`/${listing.type}/${listing.name}/${chapter}`);
|
||||||
|
music_vars.push({
|
||||||
|
listing,
|
||||||
|
chapter,
|
||||||
|
next_chapter: chapters[j + 1] ? chapters[j + 1] : false,
|
||||||
|
prev_chapter: j > 0 ? chapters[j - 1] : false,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.serve_templates(renderer, directory_serve_paths, "directory", directory_vars);
|
builder.serve_templates(renderer, directory_serve_paths, "directory", directory_vars);
|
||||||
builder.serve_templates(renderer, anime_serve_paths, "anime", anime_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, manga_serve_paths, "manga", manga_vars);
|
||||||
|
builder.serve_templates(renderer, music_serve_paths, "music", music_vars);
|
||||||
|
|||||||
18
host.ts
18
host.ts
@@ -19,10 +19,19 @@ const stream_chunk_size: number = 2 * 1024 * 1024; //2 MiB
|
|||||||
createServer((req, res) => {
|
createServer((req, res) => {
|
||||||
const todays_password: string = get_password();
|
const todays_password: string = get_password();
|
||||||
let req_path: string;
|
let req_path: string;
|
||||||
|
if (req.url.includes("..")) {
|
||||||
|
//nice try
|
||||||
|
//bad request
|
||||||
|
res.writeHead(400);
|
||||||
|
//write file
|
||||||
|
res.write("400");
|
||||||
|
//end response
|
||||||
|
return res.end();
|
||||||
|
}
|
||||||
if (!req.url.includes(".")) {
|
if (!req.url.includes(".")) {
|
||||||
req_path = path.join(__dirname, "build", req.url, "index.html");
|
req_path = path.join(__dirname, "build", decodeURI(req.url), "index.html");
|
||||||
} else {
|
} else {
|
||||||
req_path = path.join(__dirname, "build", req.url);
|
req_path = path.join(__dirname, "build", decodeURI(req.url));
|
||||||
}
|
}
|
||||||
const url_obj = new URL(req.url, `http://${req.headers.host}`);
|
const url_obj = new URL(req.url, `http://${req.headers.host}`);
|
||||||
//check for auth
|
//check for auth
|
||||||
@@ -56,7 +65,7 @@ createServer((req, res) => {
|
|||||||
return res.end();
|
return res.end();
|
||||||
}
|
}
|
||||||
//set content type
|
//set content type
|
||||||
let non_utf8_content_types: string[] = ["image/png", "image/gif", "image/jpeg", "video/mp4"];
|
let non_utf8_content_types: string[] = ["image/png", "image/gif", "image/jpeg", "audio/mpeg", "video/mp4"];
|
||||||
let content_type: string;
|
let content_type: string;
|
||||||
switch (req_path.split(".")[1]) {
|
switch (req_path.split(".")[1]) {
|
||||||
case "html":
|
case "html":
|
||||||
@@ -82,6 +91,9 @@ createServer((req, res) => {
|
|||||||
case "jpg":
|
case "jpg":
|
||||||
content_type = "image/jpeg";
|
content_type = "image/jpeg";
|
||||||
break;
|
break;
|
||||||
|
case "mp3":
|
||||||
|
content_type = "audio/mpeg";
|
||||||
|
break;
|
||||||
case "mp4":
|
case "mp4":
|
||||||
content_type = "video/mp4";
|
content_type = "video/mp4";
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<a href="/">Front page</a>
|
<a href="/">Front page</a>
|
||||||
<ul>
|
<ul>
|
||||||
<!-- called chapters, but both anime and manga will use this -->
|
<!-- called chapters, but anime, manga, music will all use this -->
|
||||||
[[ for:chapters:chapter ]]
|
[[ for:chapters:chapter ]]
|
||||||
[[ component:chapter-listing ]]
|
[[ component:chapter-listing ]]
|
||||||
[[ endfor ]]
|
[[ endfor ]]
|
||||||
|
|||||||
32
templates/music.html
Normal file
32
templates/music.html
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>listening to [[ listing.name ]]</title>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.music {
|
||||||
|
margin: 25px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
[[ component:return ]]
|
||||||
|
<div id="main">
|
||||||
|
<div class="music">
|
||||||
|
<h2 style="display: inline-block;">[[ listing.name ]] [[ chapter ]]</h2>
|
||||||
|
<br>
|
||||||
|
<audio controls>
|
||||||
|
<source src="/music_assets/[[ listing.name ]]/[[ chapter ]].mp3" type="audio/mpeg">
|
||||||
|
</audio>
|
||||||
|
[[ component:nav ]] <!-- id: nav -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user