anime quality, https

This commit is contained in:
Jon Dough
2024-03-29 06:38:52 +00:00
parent 96da42f1cf
commit ddf88ed2fc
8 changed files with 72 additions and 40 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
* text eol=lf

4
.gitignore vendored
View File

@@ -4,4 +4,6 @@ static_assets
favourites_info.json favourites_info.json
*.js *.js
package-lock.json package-lock.json
build build
*.key
*.cert

2
.torrc
View File

@@ -1,4 +1,4 @@
HiddenServiceDir ./tor/hidden_service HiddenServiceDir ./tor/hidden_service
HiddenServicePort 80 0.0.0.0:8043 HiddenServicePort 80 0.0.0.0:8043
ContactInfo Billy Bob <billybob@example.com> ContactInfo Billy Bob <billybob@example.com>

View File

@@ -4,6 +4,8 @@ Most of the code is a modification of [hedgeblog](https://github.com/jetstream0/
Since TOR is pretty slow to download large files (eg, videos), the videos are streamed so load time isn't as bad as one might expect (HTTP protocol is amazing, browsers are amazing). Since TOR is pretty slow to download large files (eg, videos), the videos are streamed so load time isn't as bad as one might expect (HTTP protocol is amazing, browsers are amazing).
Optionally, this site can be run locally or on the regular web with HTTP(S).
# Running # Running
After first cloning or downloading the repository: After first cloning or downloading the repository:

View File

@@ -1,5 +1,5 @@
import * as path from 'path'; import * as path from 'path';
import { readdirSync } from 'fs'; import { readdirSync, existsSync } from 'fs';
import { Renderer } from './ryuji.js'; import { Renderer } from './ryuji.js';
import { Builder } from './saki.js'; import { Builder } from './saki.js';
import _favourites_info from './favourites_info.json'; import _favourites_info from './favourites_info.json';
@@ -23,21 +23,21 @@ interface DirectoryVars {
chapters: string[]; //name of all the chapters chapters: string[]; //name of all the chapters
} }
interface AnimeVars { interface ListingVars {
listing: Listing; listing: Listing;
chapter: string; chapter: string;
next_chapter?: string | boolean; next_chapter?: string | boolean;
prev_chapter?: string | boolean; prev_chapter?: string | boolean;
} }
type MusicVars = AnimeVars; type MusicVars = ListingVars;
interface MangaVars { interface AnimeVars extends ListingVars {
listing: Listing; higher_quality_available: boolean;
chapter: string; };
interface MangaVars extends ListingVars {
images: string[]; //file names of all the images in the chapter images: string[]; //file names of all the images in the chapter
next_chapter?: string | boolean;
prev_chapter?: string | boolean;
} }
const favourites_info: Record<string, FavouritesInfo> = _favourites_info; const favourites_info: Record<string, FavouritesInfo> = _favourites_info;
@@ -92,48 +92,45 @@ let manga_pages_count: number = 0;
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_assets/${listing.type}_assets/${listing.name}`), { withFileTypes: true }).map((d) => d.name.replace(".mp4", "").replace(".mp3", "")); 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({ directory_vars.push({
listing, listing,
chapters, chapters,
}); });
if (listing.type === "anime") { for (let j = 0; j < chapters.length; j++) {
for (let j = 0; j < chapters.length; j++) { const chapter: string = chapters[j];
const chapter: string = chapters[j]; const base = {
anime_serve_paths.push(`/${listing.type}/${listing.name}/${chapter}`); 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({ anime_vars.push({
listing, ...base,
chapter, higher_quality_available: existsSync(path.join(__dirname, `/static_assets/${listing.type}_assets/${listing.name}`, `${chapter}_higher_quality.mp4`)),
next_chapter: chapters[j + 1] ? chapters[j + 1] : false,
prev_chapter: j > 0 ? chapters[j - 1] : false,
}); });
} } else if (listing.type === "manga") {
} else if (listing.type === "manga") { manga_serve_paths.push(serve_path);
for (let j = 0; j < chapters.length; j++) {
const chapter: string = chapters[j];
manga_serve_paths.push(`/${listing.type}/${listing.name}/${chapter}`);
const images: string[] = readdirSync(path.join(__dirname, `/static_assets/${listing.type}_assets/${listing.name}/${chapter}`), { withFileTypes: true }).map((d) => d.name); 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_pages_count += images.length;
manga_vars.push({ manga_vars.push({
listing, ...base,
chapter,
images, images,
next_chapter: chapters[j + 1] ? chapters[j + 1] : false,
prev_chapter: j > 0 ? chapters[j - 1] : false,
}); });
} } else if (listing.type === "music") {
} else if (listing.type === "music") { music_serve_paths.push(serve_path);
for (let j = 0; j < chapters.length; j++) {
const chapter: string = chapters[j];
songs.push(`${listing.name}/${chapter}`); songs.push(`${listing.name}/${chapter}`);
music_serve_paths.push(`/${listing.type}/${listing.name}/${chapter}`);
music_vars.push({ music_vars.push({
listing, ...base,
chapter,
next_chapter: chapters[j + 1] ? chapters[j + 1] : false,
prev_chapter: j > 0 ? chapters[j - 1] : false,
}); });
} }
//
} }
} }

14
host.ts
View File

@@ -1,4 +1,5 @@
import { createServer } from 'http'; import { createServer } from 'http';
import { createServer as createServerHttps } from 'https';
import * as path from 'path'; import * as path from 'path';
import { existsSync, readFileSync, statSync, createReadStream } from 'fs'; import { existsSync, readFileSync, statSync, createReadStream } from 'fs';
import { createHash } from 'crypto'; import { createHash } from 'crypto';
@@ -16,7 +17,7 @@ function get_password(date: Date = new Date()): string {
const port: number = 8043; const port: number = 8043;
const stream_chunk_size: number = 2 * 1024 * 1024; //2 MiB const stream_chunk_size: number = 2 * 1024 * 1024; //2 MiB
createServer((req, res) => { const request_handler = (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("..")) { if (req.url.includes("..")) {
@@ -162,6 +163,15 @@ createServer((req, res) => {
} }
//end response //end response
return res.end(); return res.end();
}).listen(port); };
if (process.argv[2] === "--https") {
createServerHttps({
key: readFileSync("server.key"),
cert: readFileSync("server.cert"),
}, request_handler).listen(port + 1);
console.log(`Hosting HTTPS on port ${port + 1}`);
}
createServer(request_handler).listen(port);
console.log(`Hosting on port ${port}`); console.log(`Hosting on port ${port}`);

View File

@@ -7,6 +7,7 @@
"compile": "tsc -p .", "compile": "tsc -p .",
"build": "node build.js", "build": "node build.js",
"host": "node host.js", "host": "node host.js",
"host-https": "node host.js --https",
"start": "npm run compile && npm run build && npm run host" "start": "npm run compile && npm run build && npm run host"
}, },
"repository": { "repository": {

View File

@@ -24,7 +24,26 @@
<div id="main"> <div id="main">
<div class="anime"> <div class="anime">
<h2 style="margin: 0;">[[ listing.name ]] [[ chapter ]]</h2> <h2 style="margin: 0;">[[ listing.name ]] [[ chapter ]]</h2>
<video src="/anime_assets/[[ listing.name ]]/[[ chapter ]].mp4" controls></video> <video id="video" src="/anime_assets/[[ listing.name ]]/[[ chapter ]].mp4" controls></video>
<br/>
[[ if:higher_quality_available ]]
<label for="quality">Choose quality:</label>
<select id="quality" onchange="quality_change()">
<option selected value="low">Low/Regular Quality</option>
<option value="high">Higher Quality</option>
</select>
<script>
function quality_change() {
let video = document.getElementById("video");
if (document.getElementById("quality").value === "low") {
video.src = "/anime_assets/[[ listing.name ]]/[[ chapter ]].mp4";
} else if (document.getElementById("quality").value === "high") {
video.src = "/anime_assets/[[ listing.name ]]/[[ chapter ]]_higher_quality.mp4";
}
}
quality_change();
</script>
[[ endif ]]
[[ component:nav ]] [[ component:nav ]]
</div> </div>
</div> </div>