fix server

This commit is contained in:
Lamp 2023-10-21 01:24:06 -07:00
parent c0608568b9
commit d553b7406f
4 changed files with 40 additions and 114 deletions

@ -1,17 +1,14 @@
var express = require("express");
require("express-async-errors");
var morgan = require("morgan");
var {WebSocket, WebSocketServer} = require("ws");
var fs = require("fs/promises");
var {execFile} = require("child_process");
var app = express();
app.set("env", process.env.NODE_ENV || "production");
app.set("trust proxy", ["loopback","linklocal","uniquelocal","173.245.48.0/20","103.21.244.0/22","103.22.200.0/22","103.31.4.0/22","141.101.64.0/18","108.162.192.0/18","190.93.240.0/20","188.114.96.0/20","197.234.240.0/22","198.41.128.0/17","162.158.0.0/15","104.16.0.0/13","104.24.0.0/14","172.64.0.0/13","131.0.72.0/22","2400:cb00::/32","2606:4700::/32","2803:f800::/32","2405:b500::/32","2405:8100::/32","2a06:98c0::/29","2c0f:f248::/32"]);
app.set("trust proxy", "loopback");
var server = app.listen(process.env.PORT || 8080, process.env.ADDR);
app.use(morgan(`:date[iso] :remote-addr :method :url ":req[user-agent]" :referrer`));
app.get("/channels", async (req, res) => {
res.send(await getChannels());
});
@ -21,7 +18,7 @@ app.post("/newchannel", async (req, res, next) => {
switch (req.query.from) {
case "search":
var {query, number} = req.query;
if (!query || !(number > 1 && number < 1000)) return res.sendStatus(400);
if (!query || !(number >= 1 && number <= 1000)) return res.sendStatus(400);
var url = `ytsearch${number}:${query}`;
var channel = `${query.replaceAll(' ','-')}~${number}`;
break;
@ -54,7 +51,11 @@ app.post("/newchannel", async (req, res, next) => {
execFile("python3", ["getvideos.py", url, `public/channels/${channel}/dump.json`], (error, stdout, stderr) => {
console.log({stdout, stderr});
if (error) return next(error);
if (error) {
next(error);
fs.unlink(`public/channels/${channel}`).catch(console.error);
return;
}
generatePlaylist(channel).then(() => {
broadcastChannels();
res.status(200).type("text").send(channel);
@ -85,11 +86,20 @@ async function generatePlaylist(channel) {
var entries = dump.entries.find(x => x.title.includes("Videos")).entries;
}
if (!entries) entries = dump.entries;*/
var videos = entries.map(v => ({
var videos = dump.entries.map(v => ({
id: v.id,
duration: v.duration,
title: v.title
}));
}))
var length1 = videos.length;
videos = videos.filter(video => {
if (!video.duration || isNaN(video.duration)) {
console.warn(channel, "bad duration", video);
} else return true;
});
if (videos.length < length1) {
console.warn(channel, `${videos.length} out of ${length1} videos valid`);
}
shuffle(videos);
var playlist = {
videos,
@ -98,7 +108,7 @@ async function generatePlaylist(channel) {
};
await fs.writeFile(`public/channels/${channel}/playlist.json`, JSON.stringify(playlist));
var expiresIn = playlist.timestamp + playlist.totalDuration*1000 - Date.now();
if (!isNaN(expiresIn)) setTimeout(generatePlaylist, expiresIn, channel);
setTimeout(generatePlaylist, expiresIn, channel);
console.log(`generated new playlist for ${channel} expires in ${expiresIn/1000}s`);
} catch (error) {
console.error(channel, error.stack);
@ -114,8 +124,12 @@ async function generatePlaylist(channel) {
} catch (error) {
if (error.code != "ENOENT") console.error(error.stack);
}
if (!playlist || Date.now() > playlist.timestamp + playlist.totalDuration*1000) {
if (!playlist) {
await generatePlaylist(channel);
} else {
var expiresIn = playlist.timestamp + playlist.totalDuration*1000 - Date.now();
console.debug(`${channel} playlist expires in ${expiresIn/1000}s`);
setTimeout(generatePlaylist, expiresIn, channel);
}
} catch (error) {
console.error(error.stack);

93
package-lock.json generated

@ -7,7 +7,6 @@
"dependencies": {
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
"morgan": "^1.10.0",
"ws": "^8.14.2"
}
},
@ -28,22 +27,6 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
},
"node_modules/basic-auth": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
"integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
"dependencies": {
"safe-buffer": "5.1.2"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/basic-auth/node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/body-parser": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
@ -391,32 +374,6 @@
"node": ">= 0.6"
}
},
"node_modules/morgan": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz",
"integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==",
"dependencies": {
"basic-auth": "~2.0.1",
"debug": "2.6.9",
"depd": "~2.0.0",
"on-finished": "~2.3.0",
"on-headers": "~1.0.2"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/morgan/node_modules/on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
"dependencies": {
"ee-first": "1.1.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@ -449,14 +406,6 @@
"node": ">= 0.8"
}
},
"node_modules/on-headers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@ -690,21 +639,6 @@
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
},
"basic-auth": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
"integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
"requires": {
"safe-buffer": "5.1.2"
},
"dependencies": {
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
}
}
},
"body-parser": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
@ -961,28 +895,6 @@
"mime-db": "1.52.0"
}
},
"morgan": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz",
"integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==",
"requires": {
"basic-auth": "~2.0.1",
"debug": "2.6.9",
"depd": "~2.0.0",
"on-finished": "~2.3.0",
"on-headers": "~1.0.2"
},
"dependencies": {
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
"requires": {
"ee-first": "1.1.1"
}
}
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@ -1006,11 +918,6 @@
"ee-first": "1.1.1"
}
},
"on-headers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
},
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",

@ -2,7 +2,6 @@
"dependencies": {
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
"morgan": "^1.10.0",
"ws": "^8.14.2"
}
}

@ -3,7 +3,7 @@
<head>
<title>Non-stop MMD</title>
<meta property="og:title" content="Non-stop MMD" />
<meta property="og:description" content="Multiplayer YouTube TV" />
<meta name="description" property="og:description" content="Real-time synchronized live multiplayer video entertainment system" />
<meta name="theme-color" content="#00FFFF" />
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+Symbols+2|Bevan&display=block" rel="stylesheet" />
<script src="https://www.youtube.com/iframe_api"></script>
@ -274,37 +274,43 @@
await initializePlayer(id, position);
}
if (player.getVideoData().video_id != id) {
console.debug("change video");
var currentId = player.getVideoData().video_id;
if (currentId != id) {
console.debug("change video", currentId, id);
player.loadVideoById(id, position);
player.playVideo();
}
if (player.getPlayerState() != YT.PlayerState.PLAYING) {
console.debug("play!");
player.playVideo();
}
if (force || Math.abs(player.getCurrentTime() - position) > 1) {
var currentPos = player.getCurrentTime();
console.log("desync", currentPos, position, (currentPos - position) * 1000 + "ms");
if (force || Math.abs(currentPos - position) > 1) {
console.debug("change position", currentPos, position);
player.seekTo(position);
}
console.log("desync", (player.getCurrentTime() - position) * 1000, "ms");
}
var playlist;
async function nowPlaying() {
if (!playlist || Date.now() > playlist.timestamp + playlist.totalDuration*1000) {
var expired;
if (!playlist || (expired = Date.now() > playlist.timestamp + playlist.totalDuration*1000)) {
playlist = await fetch(`channels/${gChannel}/playlist.json`).then(res => res.json());
}
if (Date.now() > playlist.timestamp + playlist.totalDuration*1000) {
console.error("server not updating playlist!!!!");
if (expired) {
console.warn("got expired playlist");
while (Date.now() > playlist.timestamp + playlist.totalDuration*1000) {
playlist.timestamp = playlist.timestamp + playlist.totalDuration*1000;
}
}
for (var i = 0, pastDurations = 0; i < playlist.videos.length; i++) {
@ -378,7 +384,7 @@
break;
case "channel":
gChannel = j[1];
history.pushState({}, "", encodeURIComponent(gChannel));
history.pushState({}, "", `/${gChannel}`);
playlist = undefined;
sync();
[...document.getElementsByClassName('mousie')].forEach(m => m.remove());