From fa52034fb7ab126e4f7e6b8b7dad0dfadb894328 Mon Sep 17 00:00:00 2001 From: sky Date: Mon, 30 Jun 2025 03:19:11 -0400 Subject: [PATCH 01/13] fix stuff after moving to resources --- accounts/profile.js | 4 ++-- index.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/accounts/profile.js b/accounts/profile.js index 69c4c78..e06f5a7 100755 --- a/accounts/profile.js +++ b/accounts/profile.js @@ -37,8 +37,8 @@ let rawProfileHTML = fs.readFileSync("./html/profile.html").toString(); let rawEditProfileHTML = fs.readFileSync("./html/profile_edit.html").toString(); let profile404 = fs.readFileSync("./html/profile_404.html").toString(); let profileBan = fs.readFileSync("./html/profile_ban.html").toString(); -let gamesJSON = JSON.parse(fs.readFileSync("./selenite/data/games.json").toString()); -let appsJSON = JSON.parse(fs.readFileSync("./selenite/data/apps.json").toString()); +let gamesJSON = JSON.parse(fs.readFileSync("./public/resources/games.json").toString()); +let appsJSON = JSON.parse(fs.readFileSync("./public/resources/apps.json").toString()); let profileReadyJSON = {}; for (let i = 0; i < gamesJSON.length; i++) { profileReadyJSON[gamesJSON[i].directory] = { name: gamesJSON[i].name, image: gamesJSON[i].image }; diff --git a/index.js b/index.js index 4a7eab2..10a42c1 100755 --- a/index.js +++ b/index.js @@ -387,7 +387,7 @@ app.use("/ai", async (req, res, next) => { next(); } }); -app.use("/", express.static("./selenite", { extensions: ["html"] })); +app.use("/", express.static("./public", { extensions: ["html"] })); app.use("/data/:id/:file", async (req, res) => { const id = path.basename(req.params.id); const file = path.basename(req.params.file); @@ -490,6 +490,6 @@ server.on("upgrade", (request, socket, head) => { app.use(async (req, res) => { res .type("text/html") - .send(await fs.readFile(`./selenite/404.html`)) + .send(await fs.readFile(`./public/404.html`)) .status(404); }); -- 2.49.0 From cbdf039eab0c41dab4986f0e65e14c03227cc9a1 Mon Sep 17 00:00:00 2001 From: sky Date: Tue, 8 Jul 2025 00:23:29 -0400 Subject: [PATCH 02/13] begin work on redesign for user pages --- html/admin.html | 2 +- html/ai.html | 2 +- html/login.html | 33 +++------- html/profile.html | 2 +- html/profile_404.html | 2 +- html/profile_ban.html | 2 +- html/profile_edit.html | 2 +- html/register.html | 145 ++++++++++++++++++----------------------- html/reset.html | 2 +- html/users.html | 2 +- html/users.html.old | 2 +- 11 files changed, 81 insertions(+), 115 deletions(-) diff --git a/html/admin.html b/html/admin.html index 47a6b0a..8202531 100755 --- a/html/admin.html +++ b/html/admin.html @@ -1,5 +1,5 @@ - + diff --git a/html/ai.html b/html/ai.html index 10ce76f..573f417 100755 --- a/html/ai.html +++ b/html/ai.html @@ -1,5 +1,5 @@ - + diff --git a/html/login.html b/html/login.html index 6495227..0c1cab3 100755 --- a/html/login.html +++ b/html/login.html @@ -1,5 +1,5 @@ - + @@ -14,7 +14,8 @@ - + + Login | Selenite @@ -60,27 +61,17 @@ - -
- Home - Bookmarklets - Games - Apps - Settings - Open Blank - -
-
-

Login to your account

+ +

login..


- Forgot password? or Create a free account
- + forgot password?
+ create a free account
+
-
- diff --git a/html/profile.html b/html/profile.html index b0b088d..45ab2c8 100755 --- a/html/profile.html +++ b/html/profile.html @@ -1,5 +1,5 @@ - + diff --git a/html/profile_404.html b/html/profile_404.html index ebd5958..13a8861 100755 --- a/html/profile_404.html +++ b/html/profile_404.html @@ -1,5 +1,5 @@ - + diff --git a/html/profile_ban.html b/html/profile_ban.html index 2b65a54..5c58b85 100755 --- a/html/profile_ban.html +++ b/html/profile_ban.html @@ -1,5 +1,5 @@ - + diff --git a/html/profile_edit.html b/html/profile_edit.html index 20ae88c..413eef8 100755 --- a/html/profile_edit.html +++ b/html/profile_edit.html @@ -1,5 +1,5 @@ - + diff --git a/html/register.html b/html/register.html index dd5d73b..2e5da6b 100755 --- a/html/register.html +++ b/html/register.html @@ -1,5 +1,5 @@ - + @@ -14,91 +14,82 @@ - + + - Register | Selenite + Login | Selenite - -
- Home - Bookmarklets - Games - Apps - Settings - Open Blank - -
-
-

Register a new account

+ +

register..

+

3-16 characters
capital, lowercase, numbers, dash, underscore, and dots allowed

6+ characters
one uppercase, lowercase, and number at least

-

Or login

- -
+

already have an account? login here.

+ + - diff --git a/html/reset.html b/html/reset.html index 9178016..7f15635 100755 --- a/html/reset.html +++ b/html/reset.html @@ -1,5 +1,5 @@ - + diff --git a/html/users.html b/html/users.html index d26d9c3..0f9faed 100644 --- a/html/users.html +++ b/html/users.html @@ -1,5 +1,5 @@ - + diff --git a/html/users.html.old b/html/users.html.old index 9393634..f5fbf38 100755 --- a/html/users.html.old +++ b/html/users.html.old @@ -1,5 +1,5 @@ - + -- 2.49.0 From acd6d2e9e2e106062dc394165c69deadbf83ccce Mon Sep 17 00:00:00 2001 From: sky Date: Tue, 8 Jul 2025 22:01:16 -0400 Subject: [PATCH 03/13] finish up profiles, begin custom songs --- accounts/music.js | 39 +++++++ accounts/profile.js | 2 +- html/profile.html | 129 ++++++++++++++-------- html/profile_edit.html | 244 +++++++++++++++++++++++++++-------------- index.js | 55 ++-------- package-lock.json | 207 +++++++++++++++++++++++++++++++++- package.json | 1 + 7 files changed, 502 insertions(+), 175 deletions(-) create mode 100644 accounts/music.js diff --git a/accounts/music.js b/accounts/music.js new file mode 100644 index 0000000..8a22e36 --- /dev/null +++ b/accounts/music.js @@ -0,0 +1,39 @@ +import Soundcloud from 'lucida/streamers/soundcloud/main.js' +let clientId = process.env.SOUNDCLOUD_CLIENT_ID; + +let sc = new Soundcloud({ + // oauthToken: clientId +}) + +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=') + } + + try { + const info = await sc.getByUrl(url) + + if (info.type !== 'track') { + return res.status(400).send('URL is not a SoundCloud track') + } + + 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) + } catch (err) { + console.error('Stream error:', err) + res.status(500).send(err.message || 'Failed to stream track') + } +} + +export { search, download }; \ No newline at end of file diff --git a/accounts/profile.js b/accounts/profile.js index e06f5a7..3bc1775 100755 --- a/accounts/profile.js +++ b/accounts/profile.js @@ -235,7 +235,7 @@ async function generateAccountPage(name, cookie, admin) { modifiedHTML = modifiedHTML.replaceAll("{{ user_pfp }}", userData.pfp_url || "/img/user.svg"); modifiedHTML = modifiedHTML.replaceAll("{{ custom_css }}", userData.custom_css || ""); modifiedHTML = modifiedHTML.replaceAll("{{ online_time }}", dayjs(userData.last_login).fromNow()); - modifiedHTML = modifiedHTML.replaceAll("{{ played_games }}", buildGameHTML(userData)); + modifiedHTML = modifiedHTML.replaceAll("{{ username }}", sanitizeHtml(userData.username, allowNone)); let badges_html = ""; if (userData.badges !== null) { diff --git a/html/profile.html b/html/profile.html index 45ab2c8..49a5242 100755 --- a/html/profile.html +++ b/html/profile.html @@ -4,64 +4,99 @@ - - - - - - + + + + + + + + + + + + - + - - + + + + - {{ name }}'s Profile | Selenite + + - -
- Home - Bookmarklets - Games - Apps - Settings - Open Blank - -
-
-
- -
-

{{ name }}

-
{{ badges }}
-

Joined {{ join_date }}

-

Last online {{ online_time }}

-
-
-

About Me

-

{{ about }}

-
+ +

click to enter

this user selected a song, please mute the tab if you don't want to listen

+

{{ name }}'s profile

+
+ +
+

{{ name }}

+

/u/{{ username }}

+
{{ badges }}
-
-

Top Games:

-
- {{ played_games }} -
+
+

{{ song_title }}

+

{{ song_artist }}

+
+

0:00

+ +

9:99

+
+
+ + +
-
- +
+

Joined {{ join_date }}

+

Last online {{ online_time }}

+
+ +
+

about me

+

{{ about }}

+
diff --git a/html/profile_edit.html b/html/profile_edit.html index 413eef8..9b1d41d 100755 --- a/html/profile_edit.html +++ b/html/profile_edit.html @@ -5,18 +5,65 @@ https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff --> - - + + + + + + + + + + + + - + - - + + + + {{ name }}'s Profile | Selenite + + - -
- Home - Bookmarklets - Games - Apps - Settings - Open Blank - -
-
- - -
- - + +
+ + +
+

{{ name }}'s profile

+
+ + +
+
+

{{ name }}

+ +
+

/u/{{ username }}

+
{{ badges }}
-
- {{ css_edit }} +
+

{{ song_title }}

+ +
+

{{ song_artist }}

+
+

0:00

+ +

9:99

+
+
+ + +
-
- +
+

Joined {{ join_date }}

+

Last online {{ online_time }}

+
+
+
+
+

about me

-
-
-

{{ name }}

- -
-
{{ badges }}
-

Joined {{ join_date }}

-

Last online {{ online_time }}

-
-
-
-

Bio

- -
-

{{ about }}

-
-
-

Top Games:

-
- {{ played_games }} -
-
-
- - - - +

{{ about }}

+ diff --git a/index.js b/index.js index 10a42c1..ad1a636 100755 --- a/index.js +++ b/index.js @@ -1,4 +1,3 @@ -const io = require('@pm2/io') import { log } from "./log.js"; import bodyParser from "body-parser"; import express from "express"; @@ -10,6 +9,7 @@ import mime from "mime-types"; import compression from "compression"; import { accs, infdb, polytrack } from "./database.js"; import { } from "./accounts/friend.js"; +import { search, download } from "./accounts/music.js"; import { banUser, removeAccount, verifyCookie, getUserFromCookie, createAccount, resetPassword, loginAccount, addBadge } from "./accounts/manage.js"; import { } from "./accounts/misc.js"; import { getRawData, generateAccountPage, editProfile, saveData, getUsers, isAdmin, retrieveData } from "./accounts/profile.js"; @@ -26,29 +26,13 @@ app.use(cookieParser()); app.use(express.json({ limit: "10mb" })); app.use(express.urlencoded({ extended: false })); app.use(express.text()); -let requests = 0; -const requestsPerSec = io.meter({ - name: 'req/sec', - id: 'app/requests/sec' -}); -const requestsPerMin = io.meter({ - name: 'req/min', - id: 'app/requests/min' -}); app.use("/", (req, res, next) => { - requestsPerSec.mark(); - requestsPerMin.mark(); next(); }); -const sockets = io.metric({ - name: 'Open Websockets', - id: 'app/requests/sockets', -}); // setInterval(()=>{ // }, 1000) import WebSocket, { WebSocketServer } from "ws"; -import { request } from "node:http"; const wss = new WebSocketServer({ noServer: true }); let openSockets = 0; wss.on("connection", function connection(ws, req, res) { @@ -77,32 +61,11 @@ wss.on("connection", function connection(ws, req, res) { if (ws.id) { const updateAccount = accs.query(`UPDATE accounts SET last_login = $login WHERE username = $user`) updateAccount.get({ $login: new Date().toUTCString(), $user: ws.id }); - if (message.substring(4)) { - const existingAccount = accs.query(`SELECT * FROM accounts WHERE username LIKE $1`) - let userData = existingAccount.get({ $1: ws.id }); - if (userData == null) { - return { success: false, reason: "The account doesn't exist." }; - } - let games; - if (userData.playedgames) { - games = JSON.parse(userData.playedgames); - } else { - games = {}; - } - if (games[message.substring(4)]) { - games[message.substring(4)] += 30; - } else { - games[message.substring(4)] = 30; - } - const updateAccount = accs.query(`UPDATE accounts SET playedgames = $playedgames WHERE username = $user`) - updateAccount.get({ $playedgames: JSON.stringify(games), $user: ws.id }); - } } } }); - ws.on("close", () => {openSockets--; - sockets.set(openSockets);}); + ws.on("close", () => {openSockets--;}); }); app.post( "/api/event", @@ -120,11 +83,6 @@ app.post( }) } ); -// app.use("*.json", async (req, res, next) => { -// optimize json -// console.log("got data"); -// next() -// }); app.post("/register", async (req, res) => { let status = await createAccount(req.body.username, req.body.password, req.body["h-captcha-response"]); if (status["success"]) { @@ -477,6 +435,15 @@ app.post("/api/admin/ban", async (req, res) => { let status = await banUser(req.body.name, req.body.reason, req.cookies.token); res.status(200).send(status); }); + + +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)); diff --git a/package-lock.json b/package-lock.json index 5941336..ffe0ab7 100755 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "fast-glob": "^3.3.2", "file-type": "^19.0.0", "install": "^0.13.0", + "lucida": "^2.0.0-54", "mime-types": "^2.1.35", "node-html-parser": "^6.1.13", "openai": "^4.85.3", @@ -40,6 +41,15 @@ "tslib": "^2.4.0" } }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/@img/sharp-darwin-arm64": { "version": "0.33.4", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.4.tgz", @@ -569,6 +579,70 @@ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", "license": "Apache-2.0" }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, "node_modules/@tokenizer/token": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", @@ -664,9 +738,9 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", - "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -674,6 +748,17 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/blowfish-cbc": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/blowfish-cbc/-/blowfish-cbc-1.0.1.tgz", + "integrity": "sha512-o1JN6g6+ATW/4k7q1BZzy14VqLxwYa1mCii47qT4kmAaYD0NAfdM6/pz6uizbhTra/xunsPQI27LZt08OQS4sA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.1.0" + } + }, "node_modules/body-parser": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.0.2.tgz", @@ -1661,6 +1746,21 @@ } ] }, + "node_modules/image-size": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz", + "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==", + "license": "MIT", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, "node_modules/inflection": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", @@ -1754,11 +1854,39 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, + "node_modules/librespot": { + "version": "0.2.22", + "resolved": "https://registry.npmjs.org/librespot/-/librespot-0.2.22.tgz", + "integrity": "sha512-szLknWSrgF+mRuypNXQTmdq8PGGhgPRAazm8sJmD8wiCAbtO9LYHihZhQcRmCzmVz818sRHZM/BU6K6XslXSHQ==", + "license": "MIT", + "dependencies": { + "protobufjs": "^7.2.5", + "undici": "^5.27.0" + } + }, + "node_modules/librespot/node_modules/undici": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -1771,6 +1899,19 @@ "node": ">=10" } }, + "node_modules/lucida": { + "version": "2.0.0-54", + "resolved": "https://registry.npmjs.org/lucida/-/lucida-2.0.0-54.tgz", + "integrity": "sha512-3Y24WkCI1Ks6EjOAElYAeYXkxT/HtunEW+SnhDKFb681B/QEMhS/EzLzFi8D5l95/pOVODUZQMMxYNKmMMC1fQ==", + "license": "OQL", + "dependencies": { + "blowfish-cbc": "^1.0.1", + "image-size": "^1.1.1", + "librespot": "^0.2.21", + "undici": "^6.19.4", + "xmldom-qsa": "^1.1.3" + } + }, "node_modules/media-typer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", @@ -1897,6 +2038,15 @@ "node": ">= 0.6" } }, + "node_modules/node-addon-api": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.4.0.tgz", + "integrity": "sha512-D9DI/gXHvVmjHS08SVch0Em8G5S1P+QWtU31appcKT/8wFSPRcdHadIFSAntdMMVM5zz+/DL+bL/gz3UDppqtg==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -2125,6 +2275,30 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/protobufjs": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.3.tgz", + "integrity": "sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -2157,6 +2331,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.3" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -2826,6 +3009,15 @@ "node": ">= 0.6" } }, + "node_modules/undici": { + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", + "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -2924,6 +3116,15 @@ } } }, + "node_modules/xmldom-qsa": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/xmldom-qsa/-/xmldom-qsa-1.1.3.tgz", + "integrity": "sha512-IJBOczBpAYrIBJFFsmCBwfBhwe4zdMR3Xz0ZBX0OFtgO49rLy/BWbhkegOwsthdBWb1gUtFK6ZZnGdT8ZqPRBA==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index 38d6312..0c97e11 100755 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "fast-glob": "^3.3.2", "file-type": "^19.0.0", "install": "^0.13.0", + "lucida": "^2.0.0-54", "mime-types": "^2.1.35", "node-html-parser": "^6.1.13", "openai": "^4.85.3", -- 2.49.0 From daf54267b40fd52fae020b281e6a39dea1067408 Mon Sep 17 00:00:00 2001 From: sky Date: Wed, 9 Jul 2025 02:35:38 -0400 Subject: [PATCH 04/13] 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)); -- 2.49.0 From 9389d0c7e418fed3d0a70251e0f1c3c0fd744edb Mon Sep 17 00:00:00 2001 From: sky Date: Thu, 10 Jul 2025 04:55:08 -0400 Subject: [PATCH 05/13] music control --- accounts/profile.js | 9 +++++++++ html/profile.html | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/accounts/profile.js b/accounts/profile.js index 72ce3d1..257bb8e 100755 --- a/accounts/profile.js +++ b/accounts/profile.js @@ -295,6 +295,7 @@ async function generateAccountPage(name, cookie, admin) { return modified_ban; } let modifiedHTML = rawEditProfileHTML; + let songData = JSON.parse(userData.music) || false; modifiedHTML = modifiedHTML.replaceAll("{{ name }}", sanitizeHtml(userData.name, sanitizeConfig)); modifiedHTML = modifiedHTML.replaceAll("{{ username }}", userData.username); modifiedHTML = modifiedHTML.replaceAll("{{ join_date }}", dayjs(userData.createdAt).fromNow()); @@ -304,6 +305,14 @@ 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 ? '' : ""); + 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) { diff --git a/html/profile.html b/html/profile.html index 28919e8..a2f6e4b 100755 --- a/html/profile.html +++ b/html/profile.html @@ -49,9 +49,10 @@ let audioObject; document.addEventListener("DOMContentLoaded", ()=>{ let music = {{ is_music }}; + let audioObject; if(music) { let url = "{{ song_url }}"; - let audioObject = new Audio(url); + audioObject = new Audio(url); document.getElementById("enter").addEventListener("click", async ()=>{ document.getElementById("enter").style.backgroundColor = "#00000000" document.getElementById("enter").style.backdropFilter = "blur(0px)" @@ -65,6 +66,33 @@ } else { document.getElementById("enter").style.display = "none"; } + document.getElementById("playPause").addEventListener("click", ()=>{ + if(audioObject.paused) { + document.getElementById("playPause").src = "/img/pause.svg"; + audioObject.play(); + } else { + document.getElementById("playPause").src = "/img/play.svg"; + audioObject.pause(); + } + }); + document.getElementById("mute").addEventListener("click", ()=>{ + if(audioObject.volume == 0) { + document.getElementById("mute").src = "/img/volume.svg"; + audioObject.volume = 1; + } else { + document.getElementById("mute").src = "/img/muted.svg"; + audioObject.volume = 0; + } + }); + document.getElementById("playbar").addEventListener("input", (e) => { + audioObject.currentTime = document.getElementById("playbar").value/1000*audioObject.duration; + document.getElementById("playbar").value = (audioObject.currentTime / audioObject.duration) * 1000; + }); + audioObject.addEventListener("timeupdate", (e) => { + document.getElementById("totalLength").innerText = `${Math.floor(audioObject.duration/60)}:${String(Math.floor(audioObject.duration%60)).padStart(2, "0")}` + document.getElementById("curPos").innerText = `${Math.floor(audioObject.currentTime/60)}:${String(Math.floor(audioObject.currentTime%60)).padStart(2, "0")}` + document.getElementById("playbar").value = (audioObject.currentTime / audioObject.duration) * 1000; + }) }) @@ -74,12 +102,12 @@

{{ name }}'s profile

-
+

{{ name }}

/u/{{ username }}

{{ badges }}
-
+

{{ song_title }}

{{ song_artist }}

@@ -92,7 +120,7 @@
-
+

Joined {{ join_date }}

Last online {{ online_time }}

-- 2.49.0 From db94e9fe497195f41da54784c94ad51203de3ddd Mon Sep 17 00:00:00 2001 From: sky Date: Tue, 12 Aug 2025 14:14:36 -0400 Subject: [PATCH 06/13] add processing server check --- accounts/profile.js | 17 +++- html/profile.html | 14 ++- html/profile_edit.html | 221 +++++++++++++++++++++++------------------ html/users.html | 82 ++++++++++++++- index.js | 4 + 5 files changed, 228 insertions(+), 110 deletions(-) diff --git a/accounts/profile.js b/accounts/profile.js index 257bb8e..20049f9 100755 --- a/accounts/profile.js +++ b/accounts/profile.js @@ -194,22 +194,29 @@ async function editProfile(body, token, admin) { let fileType = (await fileTypeFromBuffer(pfp))["ext"]; if (["png", "jpg", "gif", "avif", "webp", "tiff"].includes(fileType)) { let url; - let dir = `${process.env.DATA_PATH}/data/${existingAccount.id}/`; + let dir = `${process.env.DATA_PATH}/data/${userData.id}/`; let uuid = crypto.randomUUID(); - let path = `${process.env.DATA_PATH}/data/${existingAccount.id}/${uuid}.webp`; - url = `/data/${existingAccount.id}/${uuid}.webp`; + let path = `${process.env.DATA_PATH}/data/${userData.id}/${uuid}.webp`; + url = `/data/${userData.id}/${uuid}.webp`; fs.mkdirSync(dir, { recursive: true }); fs.writeFileSync(path, ""); await sharp(pfp, { animated: fileType == "gif" }) .resize({ width: 300, withoutEnlargement: true }) .webp({ quality: 70, effort: 4 }) .toFile(path); - await fs.unlink(`${__dirname}/${existingAccount.pfp_url}`, () => {}); + await fs.unlink(`${__dirname}/${userData.pfp_url}`, () => {}); const updateAccount = accs.query(`UPDATE accounts SET pfp_url = $url WHERE username = $user`) updateAccount.get({ $url: url, $user: user }); } } if (body.artist) { + let checkStatus = new Request({ + url: process.env.PROCESSING_SERVER + "/status" + }); + let checkStatusRequest = await fetch(checkStatus); + if(checkStatusRequest.status != 200) { + return { success: false, err: "processing server is down, try again later"}; + } let path = await download(body.url); console.log("exit download"); let file = Bun.file(path); @@ -224,7 +231,7 @@ async function editProfile(body, token, admin) { console.log("created request"); let oggFile = await fetch(request); console.log("finished request"); - let filePath = `/data/${existingAccount.id}/${crypto.randomUUID()}.ogg`; + let filePath = `/data/${userData.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({ diff --git a/html/profile.html b/html/profile.html index a2f6e4b..c874996 100755 --- a/html/profile.html +++ b/html/profile.html @@ -46,25 +46,31 @@ +

{{ name }}'s profile

+

click on one of the following areas to edit

+

profile picture, name, song, and about me

+

share your profile at {{ url_gen }}

- - -
-
-

{{ name }}

- -
+ +
+

{{ name }}

/u/{{ username }}

{{ badges }}
-
-
-

{{ song_title }}

- -
+
+

{{ song_title }}

{{ song_artist }}

0:00

@@ -405,17 +433,14 @@
-
+

Joined {{ join_date }}

Last online {{ online_time }}

-
-
-

about me

- -
-

{{ about }}

+
+

about me

+

{{ about }}

diff --git a/html/users.html b/html/users.html index 0f9faed..d1660c2 100644 --- a/html/users.html +++ b/html/users.html @@ -42,17 +42,93 @@ + Selenite +

users

-
- -
+
+
diff --git a/index.js b/index.js index 69fd89f..8fcf001 100755 --- a/index.js +++ b/index.js @@ -338,6 +338,10 @@ 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) => { + res.status(200).send(await download(req.query.url)) +}); const server = app.listen(port, () => { console.log(log.success("Express is online.")); console.log("- " + log.info("http://localhost:" + port)); -- 2.49.0 From 4e315c993a5099c69b3c8eb6ca4d93e00f732dfc Mon Sep 17 00:00:00 2001 From: sky Date: Sun, 17 Aug 2025 19:14:11 -0400 Subject: [PATCH 07/13] mobile, idek --- accounts/music.js | 146 +++++++++++++++++++++++++-- accounts/profile.js | 23 ++++- html/profile.html | 11 ++- html/profile_edit.html | 11 +-- html/users.html | 2 +- package-lock.json | 219 ++++++++++++++++++++++++----------------- 6 files changed, 293 insertions(+), 119 deletions(-) diff --git a/accounts/music.js b/accounts/music.js index fb9a59e..5492fc1 100644 --- a/accounts/music.js +++ b/accounts/music.js @@ -9,17 +9,145 @@ async function search(query) { let data = sc.search(query); return data; } -async function download(url) { - try { - const info = await sc.getByUrl(url); +// so um fuck lucida +// based on https://github.com/imputnet/cobalt/blob/58ea4aed01383ead74d5e32e75335eddc2f015be/api/src/processing/services/soundcloud.js - const { stream } = await info.getStream(); +const cachedID = { + version: '', + id: '' +} - return stream.path; - } catch (err) { - console.error('Stream error:', err) - return(err.message || 'Failed to stream track') - } +async function findClientID() { + try { + const sc = await fetch('https://soundcloud.com/').then(r => r.text()).catch(() => {}); + const scVersion = String(sc.match(/ - + @@ -50,6 +50,7 @@ let music = {{ is_music }}; let audioObject; if(music) { + document.body.classList = "enter-on"; let url = "{{ song_url }}"; audioObject = new Audio(url); audioObject.addEventListener("loadeddata", () => { @@ -63,6 +64,7 @@ setTimeout(() => { audioObject.play(); audioObject.loop = true; + document.body.classList = ""; }, 500) setTimeout( () => { document.getElementById("enter").style.display = "none"; @@ -91,8 +93,9 @@ } }); document.getElementById("playbar").addEventListener("input", (e) => { - audioObject.currentTime = document.getElementById("playbar").value/1000*audioObject.duration; - document.getElementById("playbar").value = (audioObject.currentTime / audioObject.duration) * 1000; + let value = document.getElementById("playbar").value; + audioObject.currentTime = value/1000*audioObject.duration; + document.getElementById("playbar").value = value; }); audioObject.addEventListener("timeupdate", (e) => { document.getElementById("totalLength").innerText = `${Math.floor(audioObject.duration/60)}:${String(Math.floor(audioObject.duration%60)).padStart(2, "0")}` @@ -131,7 +134,7 @@

Last online {{ online_time }}

-
+

about me

{{ about }}

diff --git a/html/profile_edit.html b/html/profile_edit.html index cfeffa4..e54fcf3 100755 --- a/html/profile_edit.html +++ b/html/profile_edit.html @@ -34,7 +34,7 @@ - + @@ -423,15 +423,6 @@

{{ song_title }}

{{ song_artist }}

-
-

0:00

- -

9:99

-
-
- - -

Joined {{ join_date }}

diff --git a/html/users.html b/html/users.html index d1660c2..2c93324 100644 --- a/html/users.html +++ b/html/users.html @@ -34,7 +34,7 @@ - + - + + + + + + + + + + + - + - - + + + - Profile + Selenite - - - -
- Home - Bookmarklets - Games - Apps - Settings - Open Blank - -
+ -
- - - - -
- + + + +

admin page

+ + + diff --git a/html/profile_edit.html b/html/profile_edit.html index 0fb07e3..d6cccee 100755 --- a/html/profile_edit.html +++ b/html/profile_edit.html @@ -406,13 +406,13 @@
- - + +

{{ name }}'s profile

-

click on one of the following areas to edit

-

profile picture, name, song, and about me

+

click on an area to edit

share your profile at {{ url_gen }}

+ {{ staff_buttons }}
diff --git a/html/stats.html b/html/stats.html index e69de29..40359c6 100755 --- a/html/stats.html +++ b/html/stats.html @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Selenite + + + + + +

stats

+ + diff --git a/index.js b/index.js index f40c4e3..f592736 100755 --- a/index.js +++ b/index.js @@ -64,6 +64,13 @@ wss.on("connection", function connection(ws, req, res) { const updateAccount = accs.query(`UPDATE accounts SET last_login = $login WHERE username = $user`) updateAccount.get({ $login: new Date().toUTCString(), $user: ws.id }); } + } else if (message.startsWith("annc")) { + let splitMessage = message.split(";;"); + if(await isAdmin(splitMessage[1])) { + wss.clients.forEach(client => { + client.send(`annc;;${splitMessage[2]};;${splitMessage[3]}`); + }) + } } }); -- 2.49.0