mostly finish custom music

This commit is contained in:
sky
2025-07-09 02:35:38 -04:00
parent acd6d2e9e2
commit daf54267b4
6 changed files with 88 additions and 187 deletions

View File

@ -5,3 +5,7 @@ ANNOUNCEMENT_KEY=text.
GROQ_API_KEY=["groq_api"]
NTFY_ALERT=ntfy_channel
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

View File

@ -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')
}
}

View File

@ -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 ? '<img src="/img/edit.svg" id="edit" />' : "");
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 += `<div class="played-game"><img src="/${return_data[i].origin}/${return_data[i].path}/${return_data[i].image}"/><p>${return_data[i].name}</p></div>`;
}
}
return return_html;
} else {
return "<h3>Play some games to view things appear here!</h3>";
}
}
async function getUsers(page, search) {
let amount = 12;
if (!page) {

View File

@ -48,9 +48,9 @@
<script>
let audioObject;
document.addEventListener("DOMContentLoaded", ()=>{
let music = true; // {{ is_music }}
let music = {{ is_music }};
if(music) {
let url = "/api/music/download?url=https://soundcloud.com/archive5077/fostered-alcoholism-grayskies"; // {{ music_url }}
let url = "{{ song_url }}";
let audioObject = new Audio(url);
document.getElementById("enter").addEventListener("click", async ()=>{
document.getElementById("enter").style.backgroundColor = "#00000000"
@ -59,8 +59,11 @@
setTimeout( () => {
document.getElementById("enter").style.display = "none";
audioObject.play();
audioObject.loop = true;
}, 700);
});
} else {
document.getElementById("enter").style.display = "none";
}
})
</script>

View File

@ -45,7 +45,7 @@
<title>{{ name }}'s Profile | Selenite</title>
<link rel="icon" href="/favicon.ico" />
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3415518411898563" crossorigin="anonymous"></script>
<script>
<!-- <script>
let audioObject;
document.addEventListener("DOMContentLoaded", ()=>{
let music = false; // {{ is_music }}
@ -63,10 +63,11 @@
});
}
})
</script>
</script> -->
<script>
let username = "{{ username }}";
let userData;
let songData;
(async () => {
userData = await (await fetch("/u/raw")).json();
})();
@ -100,16 +101,8 @@
console.log("promise finished");
body = { pfp: fileData };
console.log("body set");
} else if (state == "pfp") {
console.log("pfp");
let file = document.getElementById("pfp_upload").files[0];
if (file.size > 4000000) {
file.input = "";
return;
}
const fileData = await readFileAsDataURL(file);
console.log("promise finished");
body = { pfp: fileData };
} else if (state == "song") {
body = songData;
console.log("body set");
} else if (state == "clearpfp") {
body = { pfp: "del" };
@ -186,11 +179,20 @@
for (let i = 0; i < storeNames.length; i++) {
localStorage.setItem(storeNames[i], storage[storeNames[i]]);
}
} else if (state == song) {
// create body
}
console.log("sending");
body.username = username;
document.getElementById("title").innerText = "processing...";
document.getElementById("pfp_upload").style.display = "none";
document.getElementById("pfp_reminder").style.display = "none";
document.getElementById("body-text").style.display = "none";
document.getElementById("clear").style.display = "none";
document.getElementById("text").style.display = "none";
document.getElementById("counter").style.display = "none";
document.getElementById("submit").style.display = "none";
document.getElementById("search").style.display = "none";
document.querySelector("results").style.display = "none";
document.getElementById("popup").style.display = "flex";
await fetch("/api/profile/edit", {
credentials: "include",
headers: {
@ -200,8 +202,6 @@
method: "POST",
mode: "cors",
});
console.log("sent");
document.getElementById("popup").style.display = "none";
location.reload();
}
document.addEventListener("DOMContentLoaded", async () => {
@ -230,6 +230,8 @@
document.getElementById("counter").style.display = "flex";
document.getElementById("submit").style.display = "flex";
document.getElementById("popup").style.display = "flex";
document.getElementById("search").style.display = "none";
document.querySelector("results").style.display = "none";
} else if (e.target.parentElement.children[0].id == "bio") {
state = "bio";
document.getElementById("title").innerText = "change your about me";
@ -244,6 +246,8 @@
document.getElementById("counter").style.display = "flex";
document.getElementById("submit").style.display = "flex";
document.getElementById("popup").style.display = "flex";
document.getElementById("search").style.display = "none";
document.querySelector("results").style.display = "none";
} else if (e.target.parentElement.children[0].id == "song") {
state = "song";
document.getElementById("title").innerText = "pick a song";
@ -256,6 +260,8 @@
document.getElementById("counter").style.display = "none";
document.getElementById("submit").style.display = "none";
document.getElementById("popup").style.display = "flex";
document.getElementById("search").style.display = "flex";
document.querySelector("results").style.display = "flex";
} else if (e.target.parentElement.children[0].id == "pfp") {
state = "pfp";
document.getElementById("title").innerText = "upload a new profile picture";
@ -267,6 +273,8 @@
document.getElementById("counter").style.display = "none";
document.getElementById("submit").style.display = "flex";
document.getElementById("popup").style.display = "flex";
document.getElementById("search").style.display = "none";
document.querySelector("results").style.display = "none";
}
});
});
@ -326,8 +334,16 @@
document.getElementById("submit").style.display = "flex";
document.getElementById("popup").style.display = "flex";
});
document.querySelectorAll("results").forEach(async e => {
e.addEventListener("click", await setProfile)
document.querySelectorAll("result").forEach(async e => {
e.addEventListener("click", async (element) => {
songData = {
url: e.getAttribute("data-url"),
title: e.childNodes[0].innerText,
artist: e.childNodes[1].innerText,
}
console.log(songData);
await setProfile();
})
});
});
</script>

112
index.js
View File

@ -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<leaderboard.length;i++) {
returnValue["entries"][i] = {};
returnValue["entries"][i]["id"] = leaderboard[i]["id"];
returnValue["entries"][i]["name"] = decodeURIComponent(leaderboard[i]["username"]);
returnValue["entries"][i]["carColors"] = leaderboard[i]["colors"];
returnValue["entries"][i]["frames"] = leaderboard[i]["frames"];
returnValue["entries"][i]["verifiedState"] = true;
returnValue["entries"][i]["isSelf"] = false;
}
res.send(returnValue);
}
} else if(path == "recording") {
let recordingQuery = polytrack.query(`SELECT * FROM polytrack WHERE id = $id`).get({ $id: req.query.recordingId });
res.send({
"recording": recordingQuery.recording,
"frames": recordingQuery.frames,
"verifiedState": true,
"carColors": recordingQuery.colors
});
}
})
app.use("/api/account/load", async (req, res, next) => {
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));