Compare commits

..

5 commits

Author SHA1 Message Date
34a6cd3458 Download button 2024-04-23 13:19:02 -05:00
f9ca0c8adf Download exists now 2024-04-23 13:15:38 -05:00
c66f324b20 New buttons in the watch tab 2024-04-23 13:11:17 -05:00
c08af44759 General fixes 2024-04-23 13:05:34 -05:00
d5402f3aa4 Local CSS file & remove root 2024-04-23 11:13:46 -05:00
6 changed files with 326 additions and 52 deletions

3
.gitignore vendored
View file

@ -130,3 +130,6 @@ dist
.yarn/install-state.gz .yarn/install-state.gz
.pnp.* .pnp.*
# Violet's Limbo
testPath
public

View file

@ -40,6 +40,7 @@ const videoFormats = ["mp4", "mkv"]
app.use(express.static(directory)) app.use(express.static(directory))
app.use(express.static(pubDir)) app.use(express.static(pubDir))
app.use(express.static(path.join(__dirname, 'resources')))
app.listen(PORT, () => { app.listen(PORT, () => {
console.log("Now listening on PORT: " + PORT) console.log("Now listening on PORT: " + PORT)
@ -100,43 +101,54 @@ app.get("/video/*", (req, res) => {
stream.pipe(res) stream.pipe(res)
}) })
app.get("/download/*", (req, res) => {
var download = req.params[0]
var downloadPath = path.join(directory, download)
var downloadName = downloadPath.substring(downloadPath.lastIndexOf("/"))
if (!fs.existsSync(downloadPath)) {
downloadPath = path.join(pubDir, download)
}
res.setHeader('Content-disposition', `attachment; filename=${downloadName}`);
var stream = fs.createReadStream(downloadPath)
stream.pipe(res)
})
app.get("/*", (req, res) => { app.get("/*", (req, res) => {
var file = req.params[0] var file = req.params[0]
var absPath = path.join(pubDir, file) var absPath = path.join(pubDir, file)
if (file != '') { var html = fs.readFileSync(path.join(__dirname, 'resources/base.html')).toString()
var baseHTML = fs.readFileSync(path.join(__dirname, 'resources/base.html')).toString()
} else {
var baseHTML = fs.readFileSync(path.join(__dirname, 'resources/root.html')).toString()
}
var baseStart = baseHTML.substring(0, baseHTML.indexOf('{CONTENT}'))
var baseEnd = baseHTML.substring(baseHTML.indexOf('{CONTENT}') + 9, baseHTML.length)
res.setHeader('Content-Type', 'text/html') res.setHeader('Content-Type', 'text/html')
var addedHTML = ""
res.setHeader("X-Accel-Buffering", "no") html = html.replace("{TITLE}", '/' + file)
try { try {
var dirContents = fs.readdirSync(absPath) var dirContents = fs.readdirSync(absPath)
var dirStats = fs.statSync(absPath) var dirStats = fs.statSync(absPath)
} catch (error) { } catch (error) {
res.send(baseStart.replace("{TITLE}", "404: not found!") + "<h2>404: not found!</h2>" + baseEnd) html = html.replace("{CONTENT}", "<h3>404: not found!</h3><a href='/'>Go to root</a>")
res.send(html)
return return
} }
res.write(baseStart.replace("{TITLE}", '/' + file)) addedHTML += `<h3>${dirContents.length} Files</h3>`.trim()
res.write(`<h3>${dirContents.length} Files</h3>`)
if (file != '') { if (file != '') {
res.write('<a href="../">Parent Directory</a><br>') addedHTML += '<a href="../">Parent Directory</a><br>'
} }
var dirs = [] var dirs = []
var ogFolder = file var ogFolder = file
addedHTML += "<ul>"
for (let index = 0; index < dirContents.length; index++) { for (let index = 0; index < dirContents.length; index++) {
const file = dirContents[index]; const file = dirContents[index];
var userPath = path.join(ogFolder, file) var userPath = path.join(ogFolder, file)
@ -146,9 +158,9 @@ app.get("/*", (req, res) => {
if (!fileStats.isDirectory()) { if (!fileStats.isDirectory()) {
var fileExtension = file.substring(file.lastIndexOf('.') + 1, ) var fileExtension = file.substring(file.lastIndexOf('.') + 1, )
if (videoFormats.includes(fileExtension)) { if (videoFormats.includes(fileExtension)) {
res.write(`<li><a href="/watch/${userPath}">${file}</a> | ${humanFileSize(fileStats.size)}</li>`) addedHTML += `<li><a href="/watch/${userPath}">${file}</a> | ${humanFileSize(fileStats.size)} | <a href="/download/${userPath}">download</a></li>`
} else { } else {
res.write(`<li><a href="./${file}">${file}</a> | ${humanFileSize(fileStats.size)}</li>`) addedHTML += `<li><a href="./${file}">${file}</a> | ${humanFileSize(fileStats.size)} | <a href="/download/${userPath}">download</a></li>`
} }
} else { } else {
@ -161,14 +173,18 @@ app.get("/*", (req, res) => {
var fileStats = fs.statSync(path.join(absPath, file)) var fileStats = fs.statSync(path.join(absPath, file))
res.write(`<li><a href="./${file}">./${file}/</a></li>`) addedHTML += `<li><a href="./${file}">./${file}/</a></li>`
} }
// res.write(`<a href="./${file}">./${file}/</a><br>`) // res.write(`<a href="./${file}">./${file}/</a><br>`)
res.write(baseEnd) addedHTML += "</ul>"
res.end() html = html.replace("{CONTENT}", addedHTML)
res.write(html, () => {
res.end()
})
}) })
process.on('uncaughtException', (err, origin) => { process.on('uncaughtException', (err, origin) => {

View file

@ -6,17 +6,16 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://violets-purgatory.dev/style.css"> <link rel="stylesheet" href="/style.css">
<title>{TITLE}</title> <title>{TITLE}</title>
</head> </head>
<body> <body>
<h1>The Violet Archive</h1>
<div class="fadediv"> <div class="fadediv">
<ul> {CONTENT}
{CONTENT}
</ul>
</div> </div>
</body> </body>

View file

@ -1,28 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://violets-purgatory.dev/style.css">
<title>Violet's Clipdump</title>
</head>
<body>
<h1>Welcome to Violet's Clip dump</h1>
<div class="fadediv">
<p>Yes, you heard that right. Well its more like a File Share but "Clip dump" is still pretty accurate,
and rolls off the tongue better.<br>
Here you'll mainly find just clips of me playin games and stuff. Its not really something designed to be
"looked through"
but I decided why not. It's not very organized so be warned!</p>
<ul>
{CONTENT}
</ul>
</div>
</body>
</html>

281
resources/style.css Normal file
View file

@ -0,0 +1,281 @@
/*DO NOT MODIFY IF YOU ARE TRYING TO CHANGE THINGS ON THE SITE!!!This exists for compatibility with services on Violet's purgatorySoon, this will be removed, and replaced with a CDN or something...*/
@import url("https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css");
@font-face {
font-display: swap;
font-family: 'Rubik';
font-style: normal;
font-weight: 400;
src: url('./fonts/rubik-v28-latin-regular.woff2') format('woff2');
}
* {
font-family: 'Rubik', Verdana, Geneva, Tahoma, sans-serif;
padding: 0;
text-align: center;
}
h1 {
color: rgb(225, 215, 255);
font-size: 2.5rem;
}
h2 {
font-size: 2rem;
color: rgb(225, 215, 255)
}
h3 {
font-size: 1.65rem
}
h3,
li {
color: white;
}
ul,
ol {
display: inline-block
}
li {
font-size: 1.2rem;
text-align: left;
}
body,
html {
overflow-x: hidden;
margin: auto;
background-color: rgb(15, 4, 45);
background: linear-gradient(rgb(20, 4, 55), black);
width: 100vw;
height: 100vh;
margin: 0;
padding: 0;
background-attachment: local;
}
body {
padding: 2.5%;
}
.fadediv {
animation-name: fade-in;
animation-duration: .75s;
animation-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
margin: auto;
max-width: 1000px;
}
a {
color: rgb(175, 225, 255);
display: inline-block;
transition: 1.5s all cubic-bezier(0.075, 0.82, 0.165, 1);
}
.chip {
position: relative;
z-index: 3;
font-size: 1.3rem;
border: 2px gray solid;
border-radius: 6px;
background-color: black;
padding: 8px;
margin: 3px;
display: inline-block;
transform: scale(0.95);
transition: transform 1.25s cubic-bezier(0.075, 0.82, 0.165, 1), background-color 2s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.chip,
.chip>* {
text-decoration: none;
}
.chip:hover {
background-color: rgb(10, 0, 25);
transform: scale(1);
/* font-size: 1.35rem; */
border-color: white;
transition: transform 0.75s cubic-bezier(0.075, 0.82, 0.165, 1), background-color 3s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.chip:hover>.smallimg {
background-color: rgb(10, 0, 25);
}
.activity {
border-width: 3px;
border-radius: 10px;
overflow: hidden;
margin: auto;
padding: 0;
display: flex;
position: relative;
z-index: 3;
}
.activity>p {
width: 100%;
overflow-wrap: break-word;
}
.activity>img {
width: 128px;
aspect-ratio: 1/1;
object-fit: cover;
}
.activity>.smallimg {
width: 64px;
height: 64px;
position: absolute;
bottom: 0px;
left: 72px;
border-radius: 50px;
background: black;
padding: 5px;
/* border: 2px gray solid; */
transform: scale(0.9);
}
.activity>.smallimg:hover {
transform: scale(1);
}
a:hover {
color: white;
transition: 0.5s all cubic-bezier(0.075, 0.82, 0.165, 1);
}
p {
color: white;
font-size: 1.2rem;
padding: 0;
margin: 10px;
}
img:not(.project-inner > div > img) {
width: 100%;
max-width: 135px;
transition: all 2s cubic-bezier(0.075, 0.82, 0.165, 1);
}
.pfp {
border-radius: 15px;
border: darkgray 4px solid;
width: 60%;
aspect-ratio: 1/1;
transform: scale(0.9);
border-radius: 50%;
}
.pfp:hover {
transform: scale(1);
border-color: rgb(255, 200, 255);
object-fit: cover;
}
.emoji {
width: 32px;
border-radius: 10%;
/* border: 1px gray solid; */
}
hr {
color: white;
opacity: 0.25;
border-width: 2px;
margin: 15px 10%;
}
#card {
background-color: rgb(15, 5, 80);
padding: 15px;
border: 2px white solid;
margin: 20px auto;
width: 95%;
max-width: 800px;
z-index: 3;
position: relative;
}
.me {
border-color: limegreen;
}
.project {
background-color: rgba(35, 35, 35, 0.8);
padding: 15px;
border: 2px gray solid;
margin: 20px 0px;
border-radius: 15px;
}
.project-inner {
overflow: hidden;
padding: 0;
margin: auto;
z-index: 3;
}
.project-inner>div>img {
object-fit: cover;
border: 2px white solid;
width: 80%;
max-width: 500px;
margin: auto;
border-radius: 10px;
}
.project>p {
display: inline-block;
}
.minipfp {
width: 70px;
display: inline-block;
margin-right: 10px;
border: 2px lightgray solid;
border-radius: 5px;
}
.lengthBar {
background-color: rgb(50, 40, 60);
display: inline-block;
width: 80%;
height: 10px;
padding: 0;
overflow: hidden;
border-radius: 5px;
margin-right: 1.9%;
}
.lengthBar>span {
margin: 0;
padding: 0;
width: 100%;
background-color: rgb(200, 200, 230);
height: 20px;
display: block;
position: relative;
}
.note {
font-size: 0.95rem;
color: lightgray;
}
@keyframes fade-in {
0% {
opacity: 0;
transform: translateY(50vh);
}
100% {
opacity: 1;
transform: none;
}
}

View file

@ -6,7 +6,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://violets-purgatory.dev/style.css"> <link rel="stylesheet" href="/style.css">
<meta property="og:site_name" content="Violet's Clipdump"> <meta property="og:site_name" content="Violet's Clipdump">
<meta property="og:url" content="https://fs.violets-purgatory.dev/watch/{VID_PATH}"> <meta property="og:url" content="https://fs.violets-purgatory.dev/watch/{VID_PATH}">
@ -26,9 +26,12 @@
<h1>{TITLE}</h1> <h1>{TITLE}</h1>
<p><a href="{BACK}">Back</a></p> <p><a href="{BACK}">Back</a></p>
<p>{VID_INFO}</p> <p>{VID_INFO}</p>
<p><a href="/download/{VID_PATH}">Download</a>
<br><a href="/{VID_PATH}">Compatibility Video player</a></p>
<div class="fadediv"> <div class="fadediv">
<video src="/video/{VID_PATH}" width="100%" controls></video> <video src="/video/{VID_PATH}" width="100%" controls></video>
</div> </div>
<p class="note">Please note that the video player is unfinished, most commonly having issues on iOS devices.</p>
</body> </body>
</html> </html>