fix server
This commit is contained in:
parent
c0608568b9
commit
d553b7406f
34
index.js
34
index.js
@ -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
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());
|
||||
|
Loading…
x
Reference in New Issue
Block a user