finish up profiles, begin custom songs
This commit is contained in:
39
accounts/music.js
Normal file
39
accounts/music.js
Normal file
@ -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 };
|
@ -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) {
|
||||
|
@ -4,64 +4,99 @@
|
||||
<!-- initialize theme vars
|
||||
https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff -->
|
||||
|
||||
<meta content="{{ name }}" property="og:title" />
|
||||
<meta content="{{ about_none }}" property="og:description" />
|
||||
<meta content="{{ user_pfp }}" property="og:image" />
|
||||
<meta content="#c77dff" data-react-helmet="true" name="theme-color" />
|
||||
<!-- initialize externals -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
|
||||
<script src=" https://cdn.jsdelivr.net/npm/js-cookie@3.0.5/dist/js.cookie.min.js "></script>
|
||||
<meta property="og:title" content="Selenite" />
|
||||
<meta property="description" content="Selenite is the best unblocked games site. With over 400 games and an account system, no other websites come close to Selenite." />
|
||||
<meta name="keywords" content="proxy, web proxy, unblock websites, unblock chromebook, free web proxy, proxy list, proxy sites, un block chromebook, online proxy, proxy server, proxysite, proxy youtube, bypass securly, bypass iboss, bypass lightspeed filter, chromebooks, unblock youtube, youtube proxy, unblocked youtube, youtube unblocked, unblock games, selenite, unblocked games, free games">
|
||||
<meta content="/favicon.png" property="og:image" />
|
||||
<meta content="#c77dff" data-react-helmet="true" name="theme-color" />
|
||||
<meta name="googlebot" content="index, follow, snippet" />
|
||||
<link rel="canonical" href="https://selenite.cc/" />
|
||||
<meta property="og:description" content="Selenite is the best unblocked games site. With over 400 games and an account system, no other websites come close to Selenite." />
|
||||
<meta property="og:title" content="Selenite">
|
||||
<meta property="og:type" content="website">
|
||||
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
"name": "Selenite",
|
||||
"alternateName": "selenite.cc",
|
||||
"url": "https://selenite.cc",
|
||||
"logo": "https://selenite.cc/favicon.png",
|
||||
"sameAs": [
|
||||
"https://github.com/selenite-cc",
|
||||
"https://youtube.com/@selenitecc",
|
||||
"https://tiktok.com/@selenitecc",
|
||||
"https://selenite.cc",
|
||||
]
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- initialize my stuff -->
|
||||
<script src="/js/all.min.js"></script>
|
||||
<script src="/js/all.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="/style.css" />
|
||||
|
||||
<link rel="stylesheet" href="/css/main.css" />
|
||||
<link rel="stylesheet" href="/css/pages.css" />
|
||||
<link rel="stylesheet" href="/css/profile.css" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<!-- seo + other things -->
|
||||
<style>{{ custom_css }}</style>
|
||||
<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>
|
||||
let audioObject;
|
||||
document.addEventListener("DOMContentLoaded", ()=>{
|
||||
let music = true; // {{ is_music }}
|
||||
if(music) {
|
||||
let url = "/api/music/download?url=https://soundcloud.com/archive5077/fostered-alcoholism-grayskies"; // {{ music_url }}
|
||||
let audioObject = new Audio(url);
|
||||
document.getElementById("enter").addEventListener("click", async ()=>{
|
||||
document.getElementById("enter").style.backgroundColor = "#00000000"
|
||||
document.getElementById("enter").style.backdropFilter = "blur(0px)"
|
||||
document.getElementById("enter").style.opacity = "0";
|
||||
setTimeout( () => {
|
||||
document.getElementById("enter").style.display = "none";
|
||||
audioObject.play();
|
||||
}, 700);
|
||||
});
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</head>
|
||||
<alerts> </alerts>
|
||||
<body class="profile">
|
||||
<header>
|
||||
<a href="/index.html">Home</a>
|
||||
<a href="/bookmarklets.html">Bookmarklets</a>
|
||||
<a href="/projects.html">Games</a>
|
||||
<a href="/apps.html">Apps</a>
|
||||
<a href="/settings.html">Settings</a>
|
||||
<a id="blank" href="#">Open Blank</a>
|
||||
<a href="/u/" class="usericon"><img src="/img/user.svg" /></a>
|
||||
</header>
|
||||
<main>
|
||||
<div class="profile top">
|
||||
<img src="{{ user_pfp }}" class="pfp" />
|
||||
<div class="profile top text">
|
||||
<h1>{{ name }}</h1>
|
||||
<div class="samerow">{{ badges }}</div>
|
||||
<h2>Joined {{ join_date }}</h2>
|
||||
<h2>Last online {{ online_time }}</h2>
|
||||
</div>
|
||||
<div class="profile top text right">
|
||||
<h1>About Me</h1>
|
||||
<h2 class="about">{{ about }}</h2>
|
||||
</div>
|
||||
<body>
|
||||
<div id="enter"><h1 class="title">click to enter</h1><p>this user selected a song, please mute the tab if you don't want to listen</p></div>
|
||||
<h1 class="title">{{ name }}'s profile</h1>
|
||||
<section>
|
||||
<img src="{{ user_pfp }}" class="pfp" />
|
||||
<div>
|
||||
<h1>{{ name }}</h1>
|
||||
<p>/u/{{ username }}</p>
|
||||
<div class="badges">{{ badges }}</div>
|
||||
</div>
|
||||
<div class="profile played">
|
||||
<h2>Top Games:</h2>
|
||||
<div id="played-games">
|
||||
{{ played_games }}
|
||||
</div>
|
||||
<div>
|
||||
<h2>{{ song_title }}</h2>
|
||||
<h3>{{ song_artist }}</h3>
|
||||
<div class="samerow">
|
||||
<p id="curPos">0:00</p>
|
||||
<input type="range" id="playbar" min="1" max="1000" />
|
||||
<p id="totalLength">9:99</p>
|
||||
</div>
|
||||
<div class="samerow">
|
||||
<img id="playPause" src="/img/pause.svg" class="controls"/>
|
||||
<img id="mute" src="/img/volume.svg" class="controls"/>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
<a href="https://gitlab.com/skysthelimit.dev/selenite">Source</a>
|
||||
<a href="https://discord.gg/7jyufnwJNf">Discord</a>
|
||||
<a href="/suggest.html">Suggestions & Bugs</a>
|
||||
<a href="/contact.html">Contact</a>
|
||||
<a href="/support.html">Donate</a>
|
||||
<a href="/about.html">About</a>
|
||||
</footer>
|
||||
<div>
|
||||
<h2>Joined {{ join_date }}</h2>
|
||||
<h2>Last online {{ online_time }}</h2>
|
||||
</div>
|
||||
</section>
|
||||
<section class="column">
|
||||
<h1>about me</h1>
|
||||
<p>{{ about }}</p>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -5,18 +5,65 @@
|
||||
https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff -->
|
||||
|
||||
<!-- initialize externals -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
|
||||
<script src=" https://cdn.jsdelivr.net/npm/js-cookie@3.0.5/dist/js.cookie.min.js "></script>
|
||||
<meta property="og:title" content="Selenite" />
|
||||
<meta property="description" content="Selenite is the best unblocked games site. With over 400 games and an account system, no other websites come close to Selenite." />
|
||||
<meta name="keywords" content="proxy, web proxy, unblock websites, unblock chromebook, free web proxy, proxy list, proxy sites, un block chromebook, online proxy, proxy server, proxysite, proxy youtube, bypass securly, bypass iboss, bypass lightspeed filter, chromebooks, unblock youtube, youtube proxy, unblocked youtube, youtube unblocked, unblock games, selenite, unblocked games, free games">
|
||||
<meta content="/favicon.png" property="og:image" />
|
||||
<meta content="#c77dff" data-react-helmet="true" name="theme-color" />
|
||||
<meta name="googlebot" content="index, follow, snippet" />
|
||||
<link rel="canonical" href="https://selenite.cc/" />
|
||||
<meta property="og:description" content="Selenite is the best unblocked games site. With over 400 games and an account system, no other websites come close to Selenite." />
|
||||
<meta property="og:title" content="Selenite">
|
||||
<meta property="og:type" content="website">
|
||||
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
"name": "Selenite",
|
||||
"alternateName": "selenite.cc",
|
||||
"url": "https://selenite.cc",
|
||||
"logo": "https://selenite.cc/favicon.png",
|
||||
"sameAs": [
|
||||
"https://github.com/selenite-cc",
|
||||
"https://youtube.com/@selenitecc",
|
||||
"https://tiktok.com/@selenitecc",
|
||||
"https://selenite.cc",
|
||||
]
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- initialize my stuff -->
|
||||
<script src="/js/all.min.js"></script>
|
||||
<script src="/js/all.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="/style.css" />
|
||||
|
||||
<link rel="stylesheet" href="/css/main.css" />
|
||||
<link rel="stylesheet" href="/css/pages.css" />
|
||||
<link rel="stylesheet" href="/css/profile.css" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<!-- seo + other things -->
|
||||
<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>
|
||||
let audioObject;
|
||||
document.addEventListener("DOMContentLoaded", ()=>{
|
||||
let music = false; // {{ is_music }}
|
||||
if(music) {
|
||||
let url = "/api/music/download?url=https://soundcloud.com/archive5077/fostered-alcoholism-grayskies"; // {{ music_url }}
|
||||
let audioObject = new Audio(url);
|
||||
document.getElementById("enter").addEventListener("click", async ()=>{
|
||||
document.getElementById("enter").style.backgroundColor = "#00000000"
|
||||
document.getElementById("enter").style.backdropFilter = "blur(0px)"
|
||||
document.getElementById("enter").style.opacity = "0";
|
||||
setTimeout( () => {
|
||||
document.getElementById("enter").style.display = "none";
|
||||
audioObject.play();
|
||||
}, 700);
|
||||
});
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<script>
|
||||
let username = "{{ username }}";
|
||||
let userData;
|
||||
@ -53,6 +100,17 @@
|
||||
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 };
|
||||
console.log("body set");
|
||||
} else if (state == "clearpfp") {
|
||||
body = { pfp: "del" };
|
||||
} else if (state == "close") {
|
||||
@ -128,6 +186,8 @@
|
||||
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;
|
||||
@ -158,7 +218,7 @@
|
||||
console.log(e.target.parentElement.children[0].id);
|
||||
if (e.target.parentElement.children[0].id == "name") {
|
||||
state = "name";
|
||||
document.getElementById("title").innerText = "Set your name.";
|
||||
document.getElementById("title").innerText = "change your name";
|
||||
document.getElementById("text").setAttribute("maxlength", "20");
|
||||
document.getElementById("pfp_upload").style.display = "none";
|
||||
document.getElementById("pfp_reminder").style.display = "none";
|
||||
@ -172,7 +232,7 @@
|
||||
document.getElementById("popup").style.display = "flex";
|
||||
} else if (e.target.parentElement.children[0].id == "bio") {
|
||||
state = "bio";
|
||||
document.getElementById("title").innerText = "Set your about me.";
|
||||
document.getElementById("title").innerText = "change your about me";
|
||||
document.getElementById("text").setAttribute("maxlength", "200");
|
||||
document.getElementById("pfp_upload").style.display = "none";
|
||||
document.getElementById("pfp_reminder").style.display = "none";
|
||||
@ -184,23 +244,21 @@
|
||||
document.getElementById("counter").style.display = "flex";
|
||||
document.getElementById("submit").style.display = "flex";
|
||||
document.getElementById("popup").style.display = "flex";
|
||||
} else if (e.target.parentElement.children[0].id == "custom") {
|
||||
state = "custom";
|
||||
document.getElementById("title").innerText = "Set your custom CSS.";
|
||||
} else if (e.target.parentElement.children[0].id == "song") {
|
||||
state = "song";
|
||||
document.getElementById("title").innerText = "pick a song";
|
||||
document.getElementById("text").setAttribute("maxlength", "2048");
|
||||
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 = "flex";
|
||||
document.getElementById("text").value = userData["css"];
|
||||
document.getElementById("counter").innerText = `${document.getElementById("text").value.length} / ${document.getElementById("text").attributes.maxlength.value}`;
|
||||
document.getElementById("counter").style.display = "flex";
|
||||
document.getElementById("submit").style.display = "flex";
|
||||
document.getElementById("text").style.display = "none";
|
||||
document.getElementById("counter").style.display = "none";
|
||||
document.getElementById("submit").style.display = "none";
|
||||
document.getElementById("popup").style.display = "flex";
|
||||
} else if (e.target.parentElement.children[0].id == "pfp") {
|
||||
state = "pfp";
|
||||
document.getElementById("title").innerText = "Set your new profile picture.";
|
||||
document.getElementById("title").innerText = "upload a new profile picture";
|
||||
document.getElementById("pfp_upload").style.display = "flex";
|
||||
document.getElementById("pfp_reminder").style.display = "flex";
|
||||
document.getElementById("body-text").style.display = "none";
|
||||
@ -218,6 +276,30 @@
|
||||
document.getElementById("text").addEventListener("input", () => {
|
||||
document.getElementById("counter").innerText = `${document.getElementById("text").value.length} / ${document.getElementById("text").attributes.maxlength.value}`;
|
||||
});
|
||||
document.getElementById("search").addEventListener("input", async ()=>{
|
||||
if(document.getElementById("search").value.length > 0) {
|
||||
let query = document.getElementById("search").value;
|
||||
let results = await fetch("/api/music/search?q=" + encodeURIComponent(document.getElementById("search").value));
|
||||
let json = await results.json();
|
||||
if(document.getElementById("search").value == query) {
|
||||
document.querySelector("results").display = "flex";
|
||||
console.log("searched")
|
||||
let i = 0;
|
||||
json.tracks.forEach((e)=>{
|
||||
document.querySelectorAll("result")[i].querySelector("h2").innerText = e.title;
|
||||
document.querySelectorAll("result")[i].querySelector("p").innerText = e.artists[0].name;
|
||||
document.querySelectorAll("result")[i].setAttribute("data-url", e.url);
|
||||
i++;
|
||||
})
|
||||
}
|
||||
} else {
|
||||
document.querySelectorAll("result").forEach((e) => {
|
||||
e.removeAttribute("data-url");
|
||||
e.querySelector("h2").innerText = null;
|
||||
e.querySelector("p").innerText = null;
|
||||
})
|
||||
}
|
||||
})
|
||||
document.getElementById("upload").addEventListener("click", async () => {
|
||||
state = "upload";
|
||||
document.getElementById("title").innerText = "Warning";
|
||||
@ -244,78 +326,80 @@
|
||||
document.getElementById("submit").style.display = "flex";
|
||||
document.getElementById("popup").style.display = "flex";
|
||||
});
|
||||
document.querySelectorAll("results").forEach(async e => {
|
||||
e.addEventListener("click", await setProfile)
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<alerts> </alerts>
|
||||
<body>
|
||||
<header>
|
||||
<a href="/index.html">Home</a>
|
||||
<a href="/bookmarklets.html">Bookmarklets</a>
|
||||
<a href="/projects.html">Games</a>
|
||||
<a href="/apps.html">Apps</a>
|
||||
<a href="/settings.html">Settings</a>
|
||||
<a id="blank" href="#">Open Blank</a>
|
||||
<a href="/u/" class="usericon"><img src="/img/user.svg" /></a>
|
||||
</header>
|
||||
<main>
|
||||
<!-- <a class="friend-icon" href="/friends"><img src="/img/friend.svg"></a> -->
|
||||
<input type="text" readonly value="{{ url_gen }}" />
|
||||
<div class="samerow">
|
||||
<button id="download">Download Backup</button>
|
||||
<button id="upload">Upload Backup</button>
|
||||
<div id="popup" style="display: none">
|
||||
<h1 id="title"></h1>
|
||||
<p id="body-text"></p>
|
||||
<input type="text" id="text" />
|
||||
<input type="text" id="search" />
|
||||
<results id="results">
|
||||
<result><h2></h2><p></p></result>
|
||||
<result><h2></h2><p></p></result>
|
||||
<result><h2></h2><p></p></result>
|
||||
<result><h2></h2><p></p></result>
|
||||
<result><h2></h2><p></p></result>
|
||||
<result><h2></h2><p></p></result>
|
||||
<result><h2></h2><p></p></result>
|
||||
<result><h2></h2><p></p></result>
|
||||
<result><h2></h2><p></p></result>
|
||||
<result><h2></h2><p></p></result>
|
||||
</results>
|
||||
<p id="counter">0 / 0</p>
|
||||
<input type="file" id="pfp_upload" name="filename" accept=".png,.jpg,.jpeg,.gif,.avif,.webp,.tiff,.svg" />
|
||||
<p id="pfp_reminder">4 MB file upload max</p>
|
||||
<button id="clear">Clear Profile Picture</button>
|
||||
<button id="submit">Submit</button>
|
||||
<button id="close">X</button>
|
||||
</div>
|
||||
<div class="samerow">
|
||||
<button id="download">Download Backup</button>
|
||||
<button id="upload">Upload Backup</button>
|
||||
</div>
|
||||
<h1 class="title">{{ name }}'s profile</h1>
|
||||
<section>
|
||||
<img src="{{ user_pfp }}" class="pfp" id="pfp"/>
|
||||
<img src="/img/edit.svg" id="edit" />
|
||||
<div>
|
||||
<div class="samerow" id="name">
|
||||
<h1 id="name">{{ name }}</h1>
|
||||
<img src="/img/edit.svg" id="edit" />
|
||||
</div>
|
||||
<p>/u/{{ username }}</p>
|
||||
<div class="badges">{{ badges }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="custom"></div>
|
||||
{{ css_edit }}
|
||||
<div class="samerow" id="song">
|
||||
<h2 id="song">{{ song_title }}</h2>
|
||||
<img src="/img/edit.svg" id="edit" />
|
||||
</div>
|
||||
<h3>{{ song_artist }}</h3>
|
||||
<div class="samerow">
|
||||
<p id="curPos">0:00</p>
|
||||
<input type="range" id="playbar" min="1" max="1000" />
|
||||
<p id="totalLength">9:99</p>
|
||||
</div>
|
||||
<div class="samerow">
|
||||
<img id="playPause" src="/img/pause.svg" class="controls"/>
|
||||
<img id="mute" src="/img/volume.svg" class="controls"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="profile top">
|
||||
<img src="{{ user_pfp }}" class="pfp" id="pfp" />
|
||||
<div>
|
||||
<h2>Joined {{ join_date }}</h2>
|
||||
<h2>Last online {{ online_time }}</h2>
|
||||
</div>
|
||||
</section>
|
||||
<section class="column">
|
||||
<div class="samerow edit" id="about">
|
||||
<h1 id="bio">about me</h1>
|
||||
<img src="/img/edit.svg" id="edit" />
|
||||
<div class="profile top text">
|
||||
<div class="samerow edit" id="name">
|
||||
<h1 id="name">{{ name }}</h1>
|
||||
<img src="/img/edit.svg" id="edit" />
|
||||
</div>
|
||||
<div class="samerow">{{ badges }}</div>
|
||||
<h2>Joined {{ join_date }}</h2>
|
||||
<h2>Last online {{ online_time }}</h2>
|
||||
</div>
|
||||
<div class="profile top text right">
|
||||
<div class="samerow edit" id="about">
|
||||
<h1 id="bio">Bio</h1>
|
||||
<img src="/img/edit.svg" id="edit" />
|
||||
</div>
|
||||
<h2 id="about">{{ about }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="profile played">
|
||||
<h2>Top Games:</h2>
|
||||
<div id="played-games">
|
||||
{{ played_games }}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<popups>
|
||||
<div id="popup" style="display: none">
|
||||
<h1 id="title"></h1>
|
||||
<p id="body-text"></p>
|
||||
<input type="text" id="text" />
|
||||
<p id="counter">0 / 0</p>
|
||||
<input type="file" id="pfp_upload" name="filename" accept=".png,.jpg,.jpeg,.gif,.avif,.webp,.tiff,.svg" />
|
||||
<p id="pfp_reminder">4 MB file upload max</p>
|
||||
<button id="clear">Clear Profile Picture</button>
|
||||
<button id="submit">Submit</button>
|
||||
<button id="close">X</button>
|
||||
</div>
|
||||
</popups>
|
||||
<footer>
|
||||
<a href="https://gitlab.com/skysthelimit.dev/selenite">Source</a>
|
||||
<a href="https://discord.gg/7jyufnwJNf">Discord</a>
|
||||
<a href="/suggest.html">Suggestions & Bugs</a>
|
||||
<a href="/contact.html">Contact</a>
|
||||
<a href="/support.html">Donate</a>
|
||||
<a href="/about.html">About</a>
|
||||
</footer>
|
||||
<p>{{ about }}</p>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
55
index.js
55
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));
|
||||
|
207
package-lock.json
generated
207
package-lock.json
generated
@ -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",
|
||||
|
@ -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",
|
||||
|
Reference in New Issue
Block a user