Compare commits

...

7 Commits

Author SHA1 Message Date
sky
9e022b2745 more edu 2025-11-19 12:05:45 -05:00
sky
ef7c90840b educational variant 2025-11-19 10:41:46 -05:00
sky
5045f30a4e logs and package updates and shit 2025-11-14 21:51:43 -05:00
sky
1f13ba2afb music start 2025-11-04 22:11:04 -05:00
sky
9b66df772a more html stuff 2025-10-26 18:48:17 -04:00
sky
76094830c4 modernize reset password page 2025-10-26 17:52:35 -04:00
sky
39cdf17e3e close socket 2025-10-26 15:30:09 -04:00
16 changed files with 1176 additions and 797 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
node_modules/ node_modules/
.env .env
public/ public/
data/

View File

@ -9,6 +9,7 @@ async function search(query) {
let data = sc.search(query); let data = sc.search(query);
return data; return data;
} }
// so um fuck lucida // so um fuck lucida
// based on https://github.com/imputnet/cobalt/blob/58ea4aed01383ead74d5e32e75335eddc2f015be/api/src/processing/services/soundcloud.js // based on https://github.com/imputnet/cobalt/blob/58ea4aed01383ead74d5e32e75335eddc2f015be/api/src/processing/services/soundcloud.js
@ -72,7 +73,7 @@ const findBestForPreset = (transcodings, preset) => {
return inferior; return inferior;
} }
async function download(obj) { async function download(obj) {
const clientId = await findClientID(); const clientId = cachedID.id;
if (!clientId) return { error: "fetch.fail" }; if (!clientId) return { error: "fetch.fail" };
let link = obj; let link = obj;
@ -150,4 +151,4 @@ async function download(obj) {
} }
} }
export { search, download }; export { search, download, findClientID };

192
edu/index.html Normal file
View File

@ -0,0 +1,192 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Open Learning Hub - Your gateway to free educational resources for coding, science, math, humanities, languages, and more.">
<meta name="keywords" content="education, free learning, online courses, coding, science, math, humanities, languages, study tools">
<meta name="author" content="Open Learning Hub">
<meta property="og:title" content="Open Learning Hub">
<meta property="og:description" content="Discover free educational resources and daily learning tips.">
<meta property="og:type" content="website">
<title>Open Learning Hub</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<div class="container">
<h1>Open Learning Hub</h1>
<p>Your gateway to free educational resources across the web.</p>
</div>
</header>
<main class="container">
<section id="tip-section">
<h2>💡 Tip of the Day</h2>
<p id="daily-tip">Loading tip...</p>
<button id="new-tip-btn">Get Another Tip</button>
</section>
<section id="resources">
<h2>Educational Resources</h2>
<div class="filter-controls">
<button class="filter-btn active" data-filter="all">All</button>
<button class="filter-btn" data-filter="coding">Coding</button>
<button class="filter-btn" data-filter="science">Science</button>
<button class="filter-btn" data-filter="math">Math</button>
<button class="filter-btn" data-filter="humanities">Humanities</button>
<button class="filter-btn" data-filter="languages">Languages</button>
<button class="filter-btn" data-filter="courses">Online Courses</button>
<button class="filter-btn" data-filter="tools">Study Tools</button>
</div>
<div class="resource-grid">
<!-- Coding -->
<article class="card" data-category="coding">
<h3>freeCodeCamp</h3>
<p>Learn to code for free with interactive lessons and projects.</p>
<a href="https://www.freecodecamp.org" target="_blank">Visit Site</a>
</article>
<article class="card" data-category="coding">
<h3>MDN Web Docs</h3>
<p>Resources for developers, by developers. The bible of web dev.</p>
<a href="https://developer.mozilla.org" target="_blank">Visit Site</a>
</article>
<article class="card" data-category="coding">
<h3>GitHub</h3>
<p>The world's largest platform for software development and version control.</p>
<a href="https://github.com" target="_blank">Visit Site</a>
</article>
<article class="card" data-category="coding">
<h3>The Odin Project</h3>
<p>A full stack curriculum that is free and supported by a passionate open source community.</p>
<a href="https://www.theodinproject.com/" target="_blank">Visit Site</a>
</article>
<!-- Science -->
<article class="card" data-category="science">
<h3>NASA</h3>
<p>Explore the universe with images, videos, and news from NASA.</p>
<a href="https://www.nasa.gov" target="_blank">Visit Site</a>
</article>
<article class="card" data-category="science">
<h3>National Geographic</h3>
<p>World leader in geography, cartography and exploration.</p>
<a href="https://www.nationalgeographic.com" target="_blank">Visit Site</a>
</article>
<article class="card" data-category="science">
<h3>Nature</h3>
<p>Leading international weekly journal of science.</p>
<a href="https://www.nature.com" target="_blank">Visit Site</a>
</article>
<!-- Math -->
<article class="card" data-category="math">
<h3>Khan Academy</h3>
<p>Free, world-class education for anyone, anywhere.</p>
<a href="https://www.khanacademy.org" target="_blank">Visit Site</a>
</article>
<article class="card" data-category="math">
<h3>Wolfram MathWorld</h3>
<p>The web's most extensive mathematics resource.</p>
<a href="https://mathworld.wolfram.com" target="_blank">Visit Site</a>
</article>
<article class="card" data-category="math">
<h3>Desmos</h3>
<p>Beautiful, free online graphing calculator.</p>
<a href="https://www.desmos.com" target="_blank">Visit Site</a>
</article>
<!-- Humanities -->
<article class="card" data-category="humanities">
<h3>Project Gutenberg</h3>
<p>A library of over 60,000 free eBooks.</p>
<a href="https://www.gutenberg.org" target="_blank">Visit Site</a>
</article>
<article class="card" data-category="humanities">
<h3>Smithsonian</h3>
<p>Official website of the Smithsonian Institution.</p>
<a href="https://www.si.edu" target="_blank">Visit Site</a>
</article>
<article class="card" data-category="humanities">
<h3>Internet Archive</h3>
<p>Non-profit library of millions of free books, movies, software, and music.</p>
<a href="https://archive.org" target="_blank">Visit Site</a>
</article>
<!-- Languages -->
<article class="card" data-category="languages">
<h3>Duolingo</h3>
<p>The world's most popular way to learn a language. It's 100% free.</p>
<a href="https://www.duolingo.com" target="_blank">Visit Site</a>
</article>
<article class="card" data-category="languages">
<h3>BBC Languages</h3>
<p>Archived but excellent resources for learning 40 languages.</p>
<a href="https://www.bbc.co.uk/languages/" target="_blank">Visit Site</a>
</article>
<!-- Online Courses -->
<article class="card" data-category="courses">
<h3>Coursera</h3>
<p>Build skills with courses, certificates, and degrees online from world-class universities.</p>
<a href="https://www.coursera.org" target="_blank">Visit Site</a>
</article>
<article class="card" data-category="courses">
<h3>edX</h3>
<p>Access 2000+ free online courses from 140 leading institutions worldwide.</p>
<a href="https://www.edx.org" target="_blank">Visit Site</a>
</article>
<article class="card" data-category="courses">
<h3>MIT OpenCourseWare</h3>
<p>A web-based publication of virtually all MIT course content.</p>
<a href="https://ocw.mit.edu" target="_blank">Visit Site</a>
</article>
<!-- Study Tools -->
<article class="card" data-category="tools">
<h3>Anki</h3>
<p>Powerful, intelligent flashcards. Remembering things just became much easier.</p>
<a href="https://apps.ankiweb.net/" target="_blank">Visit Site</a>
</article>
<article class="card" data-category="tools">
<h3>Notion</h3>
<p>The all-in-one workspace for your notes, tasks, wikis, and databases.</p>
<a href="https://www.notion.so/" target="_blank">Visit Site</a>
</article>
<article class="card" data-category="tools">
<h3>Pomofocus</h3>
<p>A customizable Pomodoro timer that works on desktop & mobile browser.</p>
<a href="https://pomofocus.io/" target="_blank">Visit Site</a>
</article>
</div>
</section>
<section id="learning-paths">
<h2>🚀 Learning Paths</h2>
<div class="paths-container">
<div class="path-card">
<h3>For Beginners</h3>
<p>Start with <strong>Khan Academy</strong> to build a strong foundation in Math and Science. Then, try <strong>Duolingo</strong> for a new language.</p>
</div>
<div class="path-card">
<h3>For Career Switchers</h3>
<p>Dive into <strong>freeCodeCamp</strong> or <strong>The Odin Project</strong> (add this!) to learn web development. Supplement with <strong>CS50</strong> on edX.</p>
</div>
<div class="path-card">
<h3>For Lifelong Learners</h3>
<p>Explore <strong>Project Gutenberg</strong> for classics, <strong>TED Talks</strong> for inspiration, and <strong>Coursera</strong> for specific interests.</p>
</div>
</div>
</section>
</main>
<footer>
<div class="container">
<p>&copy; 2025 Open Learning Hub.</p>
</div>
</footer>
<script src="script.js"></script>
</body>
</html>

65
edu/script.js Normal file
View File

@ -0,0 +1,65 @@
document.addEventListener('DOMContentLoaded', () => {
// --- Tip of the Day Logic ---
const tips = [
"Spaced repetition is a learning technique that incorporates increasing intervals of time between subsequent review of previously learned material.",
"The Pomodoro Technique uses a timer to break down work into intervals, traditionally 25 minutes in length, separated by short breaks.",
"Teaching someone else is one of the best ways to learn a new concept (The Feynman Technique).",
"Sleep is crucial for memory consolidation. Pulling an all-nighter is often counterproductive.",
"Active recall (testing yourself) is far more effective than passive re-reading.",
"Interleaving practice (mixing different subjects or topics) improves long-term retention compared to blocked practice.",
"Exercise increases blood flow to the brain and can improve cognitive performance.",
"Setting specific, measurable goals (SMART goals) helps maintain motivation.",
"Taking handwritten notes can improve conceptual understanding better than typing.",
"Mnemonic devices like acronyms or rhymes can help encode information into long-term memory."
];
const tipElement = document.getElementById('daily-tip');
const newTipBtn = document.getElementById('new-tip-btn');
function showRandomTip() {
const randomIndex = Math.floor(Math.random() * tips.length);
tipElement.textContent = tips[randomIndex];
// Add a subtle animation effect
tipElement.style.opacity = 0;
setTimeout(() => {
tipElement.style.opacity = 1;
}, 50);
}
if (newTipBtn) {
newTipBtn.addEventListener('click', showRandomTip);
}
// Show initial tip
if (tipElement) {
showRandomTip();
tipElement.style.transition = "opacity 0.5s ease-in-out";
}
// --- Filtering Logic ---
const filterBtns = document.querySelectorAll('.filter-btn');
const cards = document.querySelectorAll('.card');
filterBtns.forEach(btn => {
btn.addEventListener('click', () => {
// Remove active class from all buttons
filterBtns.forEach(b => b.classList.remove('active'));
// Add active class to clicked button
btn.classList.add('active');
const filterValue = btn.getAttribute('data-filter');
cards.forEach(card => {
if (filterValue === 'all' || card.getAttribute('data-category') === filterValue) {
card.style.display = 'flex';
// Add animation for appearing elements
card.style.animation = 'fadeIn 0.5s ease-in-out';
} else {
card.style.display = 'none';
}
});
});
});
});

185
edu/style.css Normal file
View File

@ -0,0 +1,185 @@
:root {
--primary-color: #2c3e50;
--secondary-color: #3498db;
--accent-color: #e74c3c;
--bg-color: #f4f4f4;
--card-bg: #ffffff;
--text-color: #333;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
background-color: var(--bg-color);
color: var(--text-color);
}
.container {
max-width: 1100px;
margin: 0 auto;
padding: 0 20px;
}
header {
background-color: var(--primary-color);
color: white;
padding: 2rem 0;
text-align: center;
margin-bottom: 2rem;
}
header h1 {
font-size: 2.5rem;
margin-bottom: 0.5rem;
}
section {
margin-bottom: 3rem;
}
h2 {
color: var(--primary-color);
border-bottom: 2px solid var(--secondary-color);
padding-bottom: 0.5rem;
margin-bottom: 1.5rem;
display: inline-block;
}
/* Tip Section */
#tip-section {
background-color: var(--card-bg);
padding: 1.5rem;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
border-left: 5px solid var(--accent-color);
}
#new-tip-btn {
background-color: var(--secondary-color);
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
margin-top: 1rem;
transition: background 0.3s;
}
#new-tip-btn:hover {
background-color: #2980b9;
}
/* Filter Controls */
.filter-controls {
margin-bottom: 1.5rem;
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.filter-btn {
background: transparent;
border: 2px solid var(--secondary-color);
color: var(--secondary-color);
padding: 6px 12px;
border-radius: 20px;
cursor: pointer;
font-weight: bold;
transition: all 0.3s;
}
.filter-btn:hover, .filter-btn.active {
background-color: var(--secondary-color);
color: white;
}
/* Resource Grid */
.resource-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
}
.card {
background-color: var(--card-bg);
padding: 1.5rem;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
transition: transform 0.2s;
display: flex;
flex-direction: column;
}
.card:hover {
transform: translateY(-5px);
}
.card h3 {
margin-bottom: 0.5rem;
color: var(--primary-color);
}
.card p {
flex-grow: 1;
margin-bottom: 1rem;
color: #666;
}
.card a {
display: inline-block;
text-decoration: none;
color: var(--secondary-color);
font-weight: bold;
}
.card a:hover {
text-decoration: underline;
}
footer {
text-align: center;
padding: 2rem 0;
margin-top: 2rem;
color: #777;
border-top: 1px solid #ddd;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
@media (max-width: 600px) {
header h1 {
font-size: 2rem;
}
.resource-grid {
grid-template-columns: 1fr;
}
}
/* Learning Paths */
.paths-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
.path-card {
background-color: #e8f4f8;
padding: 1.5rem;
border-radius: 8px;
border-left: 4px solid var(--secondary-color);
}
.path-card h3 {
color: var(--primary-color);
margin-bottom: 0.5rem;
}

View File

@ -5,15 +5,6 @@
https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff --> https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff -->
<!-- initialize externals --> <!-- initialize externals -->
<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 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"> <script type="application/ld+json">
{ {
@ -59,6 +50,17 @@
} }
} }
} }
function setRecat() {
let domain = prompt("domain");
if(domain) {
fetch("/api/recat", {
method: "POST",
body: JSON.stringify({domain: domain})
})
.then(data => data.text())
.then(data => alert(data));
}
}
</script> </script>
</head> </head>
<alerts> </alerts> <alerts> </alerts>
@ -66,6 +68,7 @@
<h1 class="title">admin page</h1> <h1 class="title">admin page</h1>
<sections> <sections>
<button onclick="sendAnnouncement()">send announcement</button> <button onclick="sendAnnouncement()">send announcement</button>
<button onclick="setRecat()">set a domain to recat</button>
</sections> </sections>
</body> </body>
</html> </html>

View File

@ -5,8 +5,6 @@
https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff --> https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff -->
<!-- initialize externals --> <!-- 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>
<!-- initialize my stuff --> <!-- initialize my stuff -->
<script src="/js/all.min.js"></script> <script src="/js/all.min.js"></script>

View File

@ -5,16 +5,6 @@
https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff --> https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff -->
<!-- initialize externals --> <!-- initialize externals -->
<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 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"> <script type="application/ld+json">
{ {

View File

@ -5,16 +5,6 @@
https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff --> https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff -->
<!-- initialize externals --> <!-- initialize externals -->
<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 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"> <script type="application/ld+json">
{ {

View File

@ -5,8 +5,6 @@
https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff --> https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff -->
<!-- initialize externals --> <!-- 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>
<!-- initialize my stuff --> <!-- initialize my stuff -->
<script src="/js/all.min.js"></script> <script src="/js/all.min.js"></script>
@ -14,7 +12,9 @@
<script src="https://js.hcaptcha.com/1/api.js" async defer></script> <script src="https://js.hcaptcha.com/1/api.js" async defer></script>
<link rel="stylesheet" href="/style.css" /> <link rel="stylesheet" href="/css/main.css" />
<link rel="stylesheet" href="/css/pages.css" />
<!-- seo + other things --> <!-- seo + other things -->
<title>Reset Password | Selenite</title> <title>Reset Password | Selenite</title>
@ -62,26 +62,15 @@
</script> </script>
</head> </head>
<alerts> </alerts> <alerts> </alerts>
<body id="noscroll"> <body>
<header> <h2>reset password</h2>
<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 id="main" class="noscroll">
<h2>Reset Password</h2>
<form action="" id="reset"> <form action="" id="reset">
<input type="text" id="username" placeholder="username" /> <input type="text" id="username" placeholder="username" />
<input type="password" id="key" placeholder="key" /> <input type="password" id="key" placeholder="key" />
<input type="password" id="password" placeholder="password" /> <input type="password" id="password" placeholder="password" />
<div class="h-captcha" id="hcaptcha" data-sitekey="1774ec96-39be-4fb0-9e82-f4c62354b8fa"></div> <div class="h-captcha" id="hcaptcha" data-sitekey="1774ec96-39be-4fb0-9e82-f4c62354b8fa"></div>
<button type="submit" value="Submit">Reset Password</button> <button type="submit" value="Submit">reset password</button>
</form> </form>
</main>
<popups> <popups>
<div id="popup" style="display: none"> <div id="popup" style="display: none">
<h1 id="title"></h1> <h1 id="title"></h1>
@ -89,13 +78,5 @@
<button id="close">X</button> <button id="close">X</button>
</div> </div>
</popups> </popups>
<footer class="noscroll">
<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>
</body> </body>
</html> </html>

View File

@ -5,15 +5,6 @@
https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff --> https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff -->
<!-- initialize externals --> <!-- initialize externals -->
<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 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"> <script type="application/ld+json">
{ {

View File

@ -5,16 +5,6 @@
https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff --> https://coolors.co/10002b-240046-3c096c-5a189a-7b2cbf-9d4edd-c77dff-e0aaff -->
<!-- initialize externals --> <!-- initialize externals -->
<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 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"> <script type="application/ld+json">
{ {

View File

@ -10,18 +10,46 @@ import compression from "compression";
// import { accs, infdb, polytrack } from "./database.js"; // import { accs, infdb, polytrack } from "./database.js";
import { accs } from "./database.js"; import { accs } from "./database.js";
import { } from "./accounts/friend.js"; import { } from "./accounts/friend.js";
import { search, download } from "./accounts/music.js"; import { findClientID, search, download } from "./accounts/music.js";
import { banUser, removeAccount, verifyCookie, getUserFromCookie, createAccount, resetPassword, loginAccount, addBadge } from "./accounts/manage.js"; import { banUser, removeAccount, verifyCookie, getUserFromCookie, createAccount, resetPassword, loginAccount, addBadge } from "./accounts/manage.js";
import { } from "./accounts/misc.js"; import { } from "./accounts/misc.js";
import { getRawData, generateAccountPage, editProfile, saveData, getUsers, isAdmin, retrieveData } from "./accounts/profile.js"; import { getRawData, generateAccountPage, editProfile, saveData, getUsers, isAdmin, retrieveData } from "./accounts/profile.js";
import { callAI } from "./ai.js"; import { callAI } from "./ai.js";
import { Readable } from 'stream';
import os from "node:os"; import os from "node:os";
import chokidar from 'chokidar';
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename); const __dirname = dirname(__filename);
let recatters = JSON.parse(await fs.readFile("./data/recats.json"));
const watcher = chokidar.watch('./data/recats.json', {
persistent: true,
awaitWriteFinish: {
stabilityThreshold: 500,
pollInterval: 100
}
});
watcher.on('change', async (event, filePath) => {
recatters = JSON.parse(await fs.readFile("./data/recats.json"));
});
await findClientID();
setInterval(async () => {
await findClientID();
}, 1000 * 60 * 20);
const port = process.env.PORT || 3000; const port = process.env.PORT || 3000;
const app = express(); const app = express();
let recatFolder = express.static("./edu", { extensions: ["html"] });
app.use((req, res, next) => {
if(recatters.includes(req.hostname)) {
return recatFolder(req, res, next);
}
next();
});
// why the fuck does this have to exist? // why the fuck does this have to exist?
app.use("/resources/semag/hotline-miami/", (req,res,next) => { app.use("/resources/semag/hotline-miami/", (req,res,next) => {
if(req.method == "HEAD") { if(req.method == "HEAD") {
@ -85,7 +113,7 @@ wss.on("connection", function connection(ws, req, res) {
} }
}); });
ws.on("close", () => {}); ws.on("close", () => {server.close()});
}); });
app.post( app.post(
"/api/event", "/api/event",
@ -160,6 +188,41 @@ app.post("/api/ai/sendMessage", async (req, res) => {
// stream back reply // stream back reply
}) })
// music endpoints
app.get("/api/music/search", async (req, res) => {
res.status(200).send(await search(req.query.q))
})
app.use("/api/music/download", async (req, res, next) => {
// console.log()
let song = req.query.url;
song = song.replaceAll(" ", "");
const processor = Bun.spawn([
"yt-dlp",
"bestaudio[abr<=160]",
"-o", `-`,
"https://soundcloud.com/" + req.query.url
]);
for await (const chunk of processor.stdout) {
res.write(chunk);
}
res.end();
});
app.post("/api/recat", async (req, res) => {
if(isAdmin(req.cookies.token)) {
let domain = JSON.parse(req.body)["domain"];
let message;
if(recatters.includes(domain)) {
recatters.pop(domain);
message = `Successfully set ${domain} to Selenite.`
} else {
recatters.push(domain);
message = `Successfully set ${domain} as educational.`
}
fs.writeFile("./data/recats.json", JSON.stringify(recatters));
res.send(message);
};
})
// friends endpoints // friends endpoints
app.get("/api/friends/list", async (req, res) => { app.get("/api/friends/list", async (req, res) => {

1356
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@
"axios": "^1.12.2", "axios": "^1.12.2",
"body-parser": "^2.2.0", "body-parser": "^2.2.0",
"chalk": "^5.6.2", "chalk": "^5.6.2",
"chokidar": "^4.0.3",
"compression": "^1.8.1", "compression": "^1.8.1",
"cookie-parser": "^1.4.7", "cookie-parser": "^1.4.7",
"cors": "^2.8.5", "cors": "^2.8.5",

View File

@ -1,5 +1,8 @@
import { appendFile } from 'fs/promises';
import WebSocket, { WebSocketServer } from "ws"; import WebSocket, { WebSocketServer } from "ws";
const wss = new WebSocketServer({ noServer: true }); const wss = new WebSocketServer({ noServer: true });
let dataFile = "data/online.txt";
wss.on("connection", function connection(ws, req, res) { wss.on("connection", function connection(ws, req, res) {
ws.send(`online=${wss.clients.size}`); ws.send(`online=${wss.clients.size}`);
@ -31,3 +34,6 @@ server.on("upgrade", (request, socket, head) => {
wss.emit("connection", socket, request); wss.emit("connection", socket, request);
}); });
}); });
setInterval(async () => {
await appendFile(dataFile, String(wss.clients.size) + "\n")
}, 10000)