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).
|
||||
|
||||
|
||||
23
build.ts
23
build.ts
@@ -8,7 +8,7 @@ import _host_info from './host_info.json';
|
||||
|
||||
interface Listing {
|
||||
name: string;
|
||||
type: "anime" | "manga";
|
||||
type: "anime" | "manga" | "music";
|
||||
}
|
||||
|
||||
interface DirectoryVars {
|
||||
@@ -23,6 +23,8 @@ interface AnimeVars {
|
||||
prev_chapter?: string | boolean;
|
||||
}
|
||||
|
||||
type MusicVars = AnimeVars;
|
||||
|
||||
interface MangaVars {
|
||||
listing: Listing;
|
||||
chapter: string;
|
||||
@@ -31,7 +33,7 @@ interface MangaVars {
|
||||
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 builder: Builder;
|
||||
@@ -61,10 +63,13 @@ let anime_vars: AnimeVars[] = [];
|
||||
let manga_serve_paths: string[] = [];
|
||||
let manga_vars: MangaVars[] = [];
|
||||
|
||||
let music_serve_paths: string[] = [];
|
||||
let music_vars: MusicVars[] = [];
|
||||
|
||||
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/${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({
|
||||
listing,
|
||||
chapters,
|
||||
@@ -93,9 +98,21 @@ for (let i = 0; i < listings.length; i++) {
|
||||
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, 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);
|
||||
|
||||
18
host.ts
18
host.ts
@@ -19,10 +19,19 @@ const stream_chunk_size: number = 2 * 1024 * 1024; //2 MiB
|
||||
createServer((req, res) => {
|
||||
const todays_password: string = get_password();
|
||||
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(".")) {
|
||||
req_path = path.join(__dirname, "build", req.url, "index.html");
|
||||
req_path = path.join(__dirname, "build", decodeURI(req.url), "index.html");
|
||||
} 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}`);
|
||||
//check for auth
|
||||
@@ -56,7 +65,7 @@ createServer((req, res) => {
|
||||
return res.end();
|
||||
}
|
||||
//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;
|
||||
switch (req_path.split(".")[1]) {
|
||||
case "html":
|
||||
@@ -82,6 +91,9 @@ createServer((req, res) => {
|
||||
case "jpg":
|
||||
content_type = "image/jpeg";
|
||||
break;
|
||||
case "mp3":
|
||||
content_type = "audio/mpeg";
|
||||
break;
|
||||
case "mp4":
|
||||
content_type = "video/mp4";
|
||||
break;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<div>
|
||||
<a href="/">Front page</a>
|
||||
<ul>
|
||||
<!-- called chapters, but both anime and manga will use this -->
|
||||
<!-- called chapters, but anime, manga, music will all use this -->
|
||||
[[ for:chapters:chapter ]]
|
||||
[[ component:chapter-listing ]]
|
||||
[[ 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