From daf54267b40fd52fae020b281e6a39dea1067408 Mon Sep 17 00:00:00 2001 From: sky Date: Wed, 9 Jul 2025 02:35:38 -0400 Subject: [PATCH] mostly finish custom music --- .env.example | 6 ++- accounts/music.js | 24 ++------- accounts/profile.js | 74 +++++++++++++-------------- html/profile.html | 7 ++- html/profile_edit.html | 52 ++++++++++++------- index.js | 112 ++--------------------------------------- 6 files changed, 88 insertions(+), 187 deletions(-) diff --git a/.env.example b/.env.example index 8421bf7..9068157 100755 --- a/.env.example +++ b/.env.example @@ -4,4 +4,8 @@ HCAPTCHA_SECRET=hcaptcha ANNOUNCEMENT_KEY=text. GROQ_API_KEY=["groq_api"] NTFY_ALERT=ntfy_channel -DATA_PATH=where_to_store_data \ No newline at end of file +DATA_PATH=where_to_store_data +NODE_ENV=production +DISCORD_AI_WEBHOOK=discord_webhook_url +PROCESSING_SERVER=https://git.ceres.rip/selenite/processing +PROCESSING_SERVER_SECRET=secret \ No newline at end of file diff --git a/accounts/music.js b/accounts/music.js index 8a22e36..fb9a59e 100644 --- a/accounts/music.js +++ b/accounts/music.js @@ -9,30 +9,16 @@ async function search(query) { let data = sc.search(query); return data; } -async function download(url, res) { - if (!url) { - return res.status(400).send('Please provide a SoundCloud track URL as ?url=') - } - +async function download(url) { try { - const info = await sc.getByUrl(url) + const info = await sc.getByUrl(url); - if (info.type !== 'track') { - return res.status(400).send('URL is not a SoundCloud track') - } + const { stream } = await info.getStream(); - const { stream, mimeType, sizeBytes } = await info.getStream() - - res.setHeader('Content-Type', mimeType) - if (sizeBytes) { - res.setHeader('Content-Length', sizeBytes.toString()) - } - res.setHeader('Cache-Control', 'no-cache') - - stream.pipe(res) + return stream.path; } catch (err) { console.error('Stream error:', err) - res.status(500).send(err.message || 'Failed to stream track') + return(err.message || 'Failed to stream track') } } diff --git a/accounts/profile.js b/accounts/profile.js index 3bc1775..72ce3d1 100755 --- a/accounts/profile.js +++ b/accounts/profile.js @@ -4,6 +4,7 @@ import sanitizeHtml from "sanitize-html"; import sharp from "sharp"; import { accs } from "../database.js"; import { getUserFromCookie, isBanned, decryptCookie, verifyCookie } from "./manage.js"; +import { download } from "./music.js"; import dayjs from "dayjs"; import relativeTime from "dayjs/plugin/relativeTime.js"; @@ -208,6 +209,31 @@ async function editProfile(body, token, admin) { updateAccount.get({ $url: url, $user: user }); } } + if (body.artist) { + let path = await download(body.url); + console.log("exit download"); + let file = Bun.file(path); + let request = new Request({ + url: process.env.PROCESSING_SERVER + "/process", + method: "POST", + body: await file.arrayBuffer(), + headers: { + "X-Authentication": process.env.PROCESSING_SERVER_SECRET + } + }); + console.log("created request"); + let oggFile = await fetch(request); + console.log("finished request"); + let filePath = `/data/${existingAccount.id}/${crypto.randomUUID()}.ogg`; + await Bun.write(process.env.DATA_PATH + filePath, oggFile); + const updateAccount = accs.query(`UPDATE accounts SET music = $music WHERE username = $user`) + updateAccount.get({ $music: JSON.stringify({ + path: filePath, + name: body.title, + artist: body.artist + }), $user: user }); + console.log("database"); + } return { success: true }; } @@ -228,6 +254,7 @@ async function generateAccountPage(name, cookie, admin) { } let modifiedHTML = rawProfileHTML; + let songData = JSON.parse(userData.music) || false; modifiedHTML = modifiedHTML.replaceAll("{{ name }}", sanitizeHtml(userData.name, allowNone)); modifiedHTML = modifiedHTML.replaceAll("{{ join_date }}", dayjs(userData.createdAt).fromNow()); modifiedHTML = modifiedHTML.replaceAll("{{ about }}", sanitizeHtml(userData.about, sanitizeConfig) || "No about me available.."); @@ -236,6 +263,14 @@ async function generateAccountPage(name, cookie, admin) { modifiedHTML = modifiedHTML.replaceAll("{{ custom_css }}", userData.custom_css || ""); modifiedHTML = modifiedHTML.replaceAll("{{ online_time }}", dayjs(userData.last_login).fromNow()); modifiedHTML = modifiedHTML.replaceAll("{{ username }}", sanitizeHtml(userData.username, allowNone)); + if(songData) { + modifiedHTML = modifiedHTML.replaceAll("{{ song_title }}", sanitizeHtml(songData.name, allowNone)); + modifiedHTML = modifiedHTML.replaceAll("{{ song_artist }}", sanitizeHtml(songData.artist, allowNone)); + modifiedHTML = modifiedHTML.replaceAll("{{ song_url }}", sanitizeHtml(songData.path, allowNone)); + modifiedHTML = modifiedHTML.replaceAll("{{ is_music }}", "true"); + } else { + modifiedHTML = modifiedHTML.replaceAll("{{ is_music }}", "false"); + } let badges_html = ""; if (userData.badges !== null) { @@ -269,7 +304,6 @@ async function generateAccountPage(name, cookie, admin) { modifiedHTML = modifiedHTML.replaceAll("{{ url_gen }}", `https://selenite.cc/u/${userData.username}`); modifiedHTML = modifiedHTML.replaceAll("{{ online_time }}", dayjs(userData.last_login).fromNow()); modifiedHTML = modifiedHTML.replaceAll("{{ css_edit }}", (userData.badges ? userData.badges.length : 0) > 0 ? '' : ""); - modifiedHTML = modifiedHTML.replaceAll("{{ played_games }}", buildGameHTML(userData)); let badges_html = ""; if (userData.badges !== null) { @@ -282,43 +316,7 @@ async function generateAccountPage(name, cookie, admin) { return modifiedHTML; } } -function buildGameHTML(existingAccount) { - if (existingAccount.playedgames) { - let games = JSON.parse(existingAccount.playedgames); - let sortedGames = Object.keys(games).sort((a, b) => games[b] - games[a]); - let return_data = []; - if (Object.keys(games).length < 10) { - for (let i = 0; i < sortedGames.length; i++) { - try { - let origin = gamesExceptions[sortedGames[i]] ? "sppa" : "semag"; - sortedGames[i] = gamesExceptions[sortedGames[i]] ? gamesExceptions[sortedGames[i]] : sortedGames[i]; - return_data[i] = { name: profileReadyJSON[sortedGames[i]].name, image: profileReadyJSON[sortedGames[i]].image, path: sortedGames[i], origin: origin, valid: true }; - } catch (e) { - return_data[i] = { valid: false }; - } - } - } else { - for (let i = 0; i < 10; i++) { - try { - let origin = gamesExceptions[sortedGames[i]] ? "sppa" : "semag"; - sortedGames[i] = gamesExceptions[sortedGames[i]] ? gamesExceptions[sortedGames[i]] : sortedGames[i]; - return_data[i] = { name: profileReadyJSON[sortedGames[i]].name, image: profileReadyJSON[sortedGames[i]].image, path: sortedGames[i], origin: origin, valid: true }; - } catch (e) { - return_data[i] = { valid: false }; - } - } - } - let return_html = ""; - for (let i = 0; i < Object.keys(return_data).length; i++) { - if (return_data[i].valid) { - return_html += `

${return_data[i].name}

`; - } - } - return return_html; - } else { - return "

Play some games to view things appear here!

"; - } -} + async function getUsers(page, search) { let amount = 12; if (!page) { diff --git a/html/profile.html b/html/profile.html index 49a5242..28919e8 100755 --- a/html/profile.html +++ b/html/profile.html @@ -48,9 +48,9 @@ diff --git a/html/profile_edit.html b/html/profile_edit.html index 9b1d41d..347da90 100755 --- a/html/profile_edit.html +++ b/html/profile_edit.html @@ -45,7 +45,7 @@ {{ name }}'s Profile | Selenite - --> diff --git a/index.js b/index.js index ad1a636..69fd89f 100755 --- a/index.js +++ b/index.js @@ -37,7 +37,6 @@ const wss = new WebSocketServer({ noServer: true }); let openSockets = 0; wss.on("connection", function connection(ws, req, res) { openSockets++; - sockets.set(openSockets); setInterval(() => { ws.send("ping"); }, 30000); @@ -185,110 +184,6 @@ app.get("/api/chat/recent", async (req, res) => { // get last 50 recent messages // offset by a page param }) -app.get("/api/infinite/get", async (req, res, next) => { - if (req.query[1] && req.query[2]) { - let success = false; - let data; - try { - let search1Query = infdb.query(`SELECT * FROM caches WHERE 1 = $one AND 2 = $two`) - let search1 = await search1Query.get({ $one: req.query[1], $two: req.query[2] }); - console.log(search1); - if (search1 && search1.length > 0) { - data = { item: search1[0].result_item, emoji: search1[0].result_emoji, new: false }; - success = true; - } else { - let search2Query = infdb.query(`SELECT * FROM caches WHERE 1 = $two AND 2 = $one`) - let search2 = await search2Query.get({ $one: req.query[1], $two: req.query[2] }); - console.log(search2); - if (search2 && search2.length > 0) { - data = { item: search2[0].result_item, emoji: search2[0].result_emoji, new: false }; - success = true; - } - } - } catch (error) { - console.error(error); - } - if (success) { - console.log("success"); - res.send(data); - return; - } - data = await infiniteCraft(req.query[1], req.query[2]); - try { - let parse = JSON.parse(data); - let keys = Object.keys(parse); - if (keys.indexOf("item") > -1 && keys.indexOf("emoji") > -1) { - parse.new = true; - data = parse; - const createCached = infdb.query(`INSERT INTO caches (1, 2, result_item, result_emoji) VALUES ($one, $two, $item, $emoji)`) - createCached.run({ $one: req.query[1], $two: req.query[2], $item: data.item, $emoji: data.emoji }); - res.send(data); - } - } catch (error) { - console.error(error); - data = { item: "N/A", emoji: "N/A" }; - res.send(data); - } - } -}); -app.use("/semag/polytrack/data/", async (req, res, next) => { - let path = req.path.substring(1, req.path.length); - if(path == "user") { - res.sendStatus(200); - } else if(path == "leaderboard") { - let data = {}; - - if(req.method == "POST") { - req.body.split("&").forEach((item) => { - data[item.split("=")[0]] = item.split("=")[1] - }); - console.log(data); - const getExistingRuns = polytrack.query(`SELECT * FROM polytrack WHERE userid = $usrid AND trackid = $trackid`); - let existingRuns = getExistingRuns.all({ $usrid: data["userToken"], $trackid: data["trackId"] }); - let saveRun = true; - if(existingRuns !== null) { - existingRuns.forEach((item) => { - if(saveRun) { - if(data.frames > item.frames) { - saveRun = false; - } else { - let deleteRun = polytrack.query(`DELETE FROM polytrack WHERE id = $id`); - deleteRun.run({ $id: item.id }) - } - } - }) - } - if(saveRun) { - const addRun = polytrack.query(`INSERT INTO polytrack (trackid, username, colors, recording, frames, userid) VALUES ($id, $usr, $clr, $record, $frames, $usrid)`) - let runData = addRun.run({ $id: data["trackId"], $usr: data["name"], $clr: data["carColors"], $record: data["recording"], $usrid: data["userToken"], $frames: data["frames"] }); - console.log("run", runData); - res.send(runData.lastInsertRowid); - } - } else { - let leaderboard = polytrack.query(`SELECT * FROM polytrack WHERE trackid = $id LIMIT $limit OFFSET $offset`).all({ $id: req.query.trackId, $limit: req.query.amount, $offset: req.query.skip }) - console.log(leaderboard); - let returnValue = {"total": leaderboard.length, "entries":[]} - for(let i = 0; i { if (req.cookies.token && (await verifyCookie(req.cookies.token))) { let status = await retrieveData(req.cookies.token); @@ -358,6 +253,9 @@ app.use("/data/:id/:file", async (req, res) => { if (mime.lookup(filePath) == "image/webp") { res.type("image/webp"); res.status(200).send(image); + } else if (mime.lookup(filePath) == "audio/ogg") { + res.type("audio/ogg"); + res.status(200).send(image); } else { res.status(404).send("File not found"); } @@ -440,10 +338,6 @@ app.post("/api/admin/ban", async (req, res) => { app.use("/api/music/search", async (req, res, next) => { res.status(200).send(await search(req.query.q)) }); -app.use("/api/music/download", async (req, res, next) => { - await download(req.query.url, res); -}); - const server = app.listen(port, () => { console.log(log.success("Express is online.")); console.log("- " + log.info("http://localhost:" + port));