diff --git a/app/index.html b/app/index.html index 63788d8..2ab716a 100644 --- a/app/index.html +++ b/app/index.html @@ -44,7 +44,9 @@
-
+
+ +
diff --git a/app/js/app.js b/app/js/app.js index 9ddc754..2955e2e 100644 --- a/app/js/app.js +++ b/app/js/app.js @@ -6,8 +6,9 @@ import * as queue from "./queue.js"; import * as library from "./library.js"; import * as fs from "./fs.js"; import * as playlists from "./playlists.js"; +import * as yt from "./yt.js"; -const components = { queue, library, fs, playlists }; +const components = { queue, library, fs, playlists, yt }; export function activate(what) { for (let id in components) { @@ -33,7 +34,7 @@ async function init() { player.init(document.querySelector("#player")); - activate("fs"); + activate("yt"); } diff --git a/app/js/lib/ui.js b/app/js/lib/ui.js index d368a56..d8f519e 100644 --- a/app/js/lib/ui.js +++ b/app/js/lib/ui.js @@ -28,17 +28,20 @@ function fileName(data) { } function formatTitle(ctx, data) { + let tokens = []; switch (ctx) { case CTX_FS: return `🎵 ${fileName(data)}`; break; case CTX_LIBRARY: - return data["Artist"] || fileName(data); + data["Track"] && tokens.push(data["Track"].padStart(2, "0")); + data["Title"] && tokens.push(data["Title"]); + if (!tokens.length) {tokens.push(fileName(data)); } + return tokens.join(" "); break; case CTX_QUEUE: - let tokens = []; data["Artist"] && tokens.push(data["Artist"]); data["Title"] && tokens.push(data["Title"]); if (!tokens.length) { tokens.push(fileName(data)); } @@ -118,6 +121,7 @@ export function song(ctx, data, parent) { deleteButton(TYPE_ID, id, node); break; + case CTX_LIBRARY: case CTX_FS: let url = data["file"]; playButton(TYPE_URL, url, node); diff --git a/app/js/yt.js b/app/js/yt.js new file mode 100644 index 0000000..f7fb6f9 --- /dev/null +++ b/app/js/yt.js @@ -0,0 +1,26 @@ +import * as mpd from "./lib/mpd.js"; +import * as html from "./lib/html.js"; +import * as pubsub from "./lib/pubsub.js"; +import * as ui from "./lib/ui.js"; + +let node; + +async function onClick(e) { + let url = prompt("Please enter a YouTube URL:"); + if (!url) { return; } + + let body = new URLSearchParams(); + body.set("url", url); + let response = await fetch("/youtube", {method:"POST", body}); + console.log(response); + let text = await response.text(); + console.log(text, text.length); +} + +export async function activate() {} + +export function init(n) { + node = n; + + node.querySelector(".go").addEventListener("click", onClick); +} diff --git a/index.js b/index.js index 4c06723..1f145dd 100644 --- a/index.js +++ b/index.js @@ -2,9 +2,61 @@ const static = require("node-static"); const app = new static.Server("./app"); const port = 8080; -let httpServer = require("http").createServer((request, response) => { - request.on("end", () => app.serve(request, response)).resume(); -}); -httpServer.listen(port); +function downloadYoutube(url, response) { + console.log("YouTube downloading", url); + let args = [ + "-f", "bestaudio", + "-o", `${__dirname}/_youtube/%(title)s-%(id)s.%(ext)s`, + url + ] + let child = require("child_process").spawn("youtube-dl", args); + let stdOut = ""; + let stdErr = ""; + child.stdout.setEncoding("utf8").on("data", chunk => stdOut += chunk); + child.stderr.setEncoding("utf8").on("data", chunk => stdErr += chunk); + + child.on("error", error => { + console.log(error); + response.writeHead(500); + response.end(error.message); + }); + + child.on("close", code => { + if (code == 0) { + console.log("OK"); + response.end(stdOut); + } else { + console.log(code, stdOut, stdErr); + response.writeHead(500); + response.end(stdErr); + } + }); +} + +function handleYoutube(request, response) { + let str = ""; + request.setEncoding("utf8"); + request.on("data", chunk => str += chunk); + request.on("end", () => { + let url = require("querystring").parse(str)["url"]; + console.log(url); + if (url) { + downloadYoutube(url, response); + } else { + response.writeHead(404); + response.end(); + } + }); +} + +function onRequest(request, response) { + if (request.method == "POST" && request.url == "/youtube") { + return handleYoutube(request, response); + } else { + request.on("end", () => app.serve(request, response)).resume(); + } +} + +let httpServer = require("http").createServer(onRequest).listen(port); require("ws2mpd").ws2mpd(httpServer, `http://localhost:${port}`);