Activities are back!

This commit is contained in:
Bingus_Violet 2024-02-18 08:01:58 -06:00
parent a66a3a9198
commit 10ed08795a
9 changed files with 368 additions and 93 deletions

View file

@ -75,6 +75,8 @@
"Github": "gray", "Github": "gray",
"Steam": "lightgray", "Steam": "lightgray",
"Univerter": "rgb(200, 175, 255)", "Univerter": "rgb(200, 175, 255)",
"Ko-fi": "rgb(255, 150, 150)" "Ko-fi": "rgb(255, 150, 150)",
"Revolt": "rgb(255, 50, 50)",
"Discord": "rgb(150, 150, 255)"
} }
} }

View file

@ -11,7 +11,6 @@ const PORT = process.env.PORT || 8080
const staticpath = path.join(__dirname, 'static') const staticpath = path.join(__dirname, 'static')
var mostRecentVideo = undefined var mostRecentVideo = undefined
var lanyardData = undefined
var config = JSON.parse(fs.readFileSync(path.join(__dirname, 'config.json'))) var config = JSON.parse(fs.readFileSync(path.join(__dirname, 'config.json')))
@ -39,38 +38,17 @@ app.listen(PORT, () => {
console.log("Violet's Purgatory is now listening on port: " + PORT) console.log("Violet's Purgatory is now listening on port: " + PORT)
}) })
if (!fs.existsSync(path.join(staticpath, 'cached'))) { var cachePath = path.join(staticpath, 'cached')
fs.mkdirSync(path.join(staticpath, 'cached')) var imgPath = path.join(staticpath, 'imgs')
}
var randomQuotes = config.quotes if (!fs.existsSync(cachePath)) {
fs.mkdirSync(cachePath)
var commitCount = "300+" } else {
var files = fs.readdirSync(cachePath)
function timeFormatter(seconds) { for (let index = 0; index < files.length; index++) {
seconds = Math.ceil(seconds) const file = files[index];
var minutes = Math.floor(seconds / 60) fs.rmSync(path.join(cachePath, file))
if (seconds % 60 < 10) {
return `${minutes}:0${seconds % 60}`
} else {
return `${minutes}:${seconds % 60}`
} }
}
function gameTimeFormatter(seconds) {
seconds = Math.ceil(seconds)
var minutes = Math.ceil(seconds / 60)
var hours = Math.floor(minutes / 60)
if (seconds <= 60) {
return 'about ' + seconds + ' seconds'
} else if (minutes < 60) {
return `${minutes} Minutes`
}
return `${hours} hours and ${minutes % 60} minutes`
} }
app.use(pageUpdater.middleWare) app.use(pageUpdater.middleWare)

195
overcomplicatedStatuses.js Normal file
View file

@ -0,0 +1,195 @@
const path = require("path")
function get_img_url(activity, size = "large_image") {
if ("assets" in activity) {
var image = activity.assets[size]
if (image) {
if (image.includes("https/")) {
return decodeURIComponent('https://' + image.substr(image.indexOf('https/') + 6, image.length))
} else if (image.includes("spotify")) {
return decodeURIComponent('https://i.scdn.co/image/' + image.substr(image.indexOf('spotify:') + 8, image.length))
} else {
return decodeURIComponent(`https://cdn.discordapp.com/app-assets/${activity.application_id}/${image}.png`)
}
}
}
if (!image) {
if (activity.name in activityImages) {
return decodeURIComponent(activityImages[activity.name])
} else {
return null
}
}
}
function timeFormatter(seconds) {
seconds = Math.ceil(seconds)
var minutes = Math.floor(seconds / 60)
if (seconds % 60 < 10) {
return `${minutes}:0${seconds % 60}`
} else {
return `${minutes}:${seconds % 60}`
}
}
function gameTimeFormatter(seconds) {
seconds = Math.ceil(seconds)
var minutes = Math.ceil(seconds / 60)
var hours = Math.floor(minutes / 60)
if (seconds <= 60) {
return 'about ' + seconds + ' seconds'
} else if (minutes < 60) {
return `${minutes} Minutes`
}
return `${hours} hours and ${minutes % 60} minutes`
}
module.exports = {
activitiesToHTML: (lanyardData, cachedImages) => {
var debounce = false
var addedHTML = ""
if (lanyardData && lanyardData.activities.length > 0) {
for (let index = 0; index < lanyardData.activities.length; index++) {
const activity = lanyardData.activities[index];
var found = false
for (let index = 0; index < lanyardData.activities.length; index++) {
const act = lanyardData.activities[index]
if (act.name == activity.name) {
if (Object.keys(act).length > Object.keys(activity).length) {
found = true
}
}
}
if (found) {
continue
}
if (!debounce && activity.type != 4) {
addedHTML += `<h2><hr>What I'm up to:</h2><div class="activity-container">`
debounce = true
}
function get_img(activity, size = "large_image") {
if (cachedImages[get_img_url(activity, size)]) {
var fn = cachedImages[get_img_url(activity, size)]
var fp = path.join(__dirname, 'static/cached', fn)
} else {
return 'imgs/notFound.png'
}
return '/cached/' + fn
}
function songStats() {
var html = ``
if (activity.assets && activity.assets.large_text != activity.details) {
html += `
<br> Album: ${activity.assets.large_text || " "}
<br> Artist: ${activity.state || " "}
`
} else {
html += `<br> Artist: ${activity.state || " "}`
}
return html
}
if (activity.type == 2) {
var timeLeft = Math.round((activity.timestamps.end - Date.now()) / 1000)
var currentPercent = (Date.now() - activity.timestamps.start) / (activity.timestamps.end - activity.timestamps.start) * 100
addedHTML += `
<div class="chip activity grid-child">
<img src="${get_img(activity)}" title="${activity.assets.large_text || activity.assets.small_text || activity.state || ""}">
<p>
Listening to <span style="color: limegreen;">${activity.name}</span>
<br> Song: ${activity.details || " "}
${songStats()}
<br>
<span class="lengthBar lengthBar${index}"><span></span></span>
${timeFormatter((activity.timestamps.end - activity.timestamps.start) / 1000)}
</p>
</div>
<style>
.lengthBar${index} > span {
animation-name: songSlider${index};
animation-duration: ${timeLeft}s;
animation-timing-function: linear;
}
@keyframes songSlider${index} {
0% {
width: ${currentPercent}%;
}
100% {
width: 100%;
}
}
</style>
`
} else if (activity.type == 0) {
var time = activity.created_at
if (activity.timestamps) {
time = activity.timestamps.start
}
if (!activity.assets) {
activity.assets = { "large_text": " ", "small_text": " " }
}
function smch() {
if (get_img_url(activity, "small_image")) {
return `<img class="smallimg" src="${get_img(activity, "small_image")}" title="${activity.assets.small_text}">`
}
return ""
}
addedHTML += `
<div class="chip activity grid-child">
<img src="${get_img(activity)}" title="${activity.assets.large_text}">
${smch()}
<p>
Playing <span style="color: rgb(255, 100, 150);">${activity.name}</span>
<br> ${(activity.details || activity.assets.large_text || " ")}
<br> ${(activity.state || activity.assets.small_text || " ")}
<br> ${gameTimeFormatter((Date.now() - time) / 1000)}
</p>
</div>
`
} else if (activity.type != 4) {
var time = activity.created_at
if (activity.timestamps) {
time = activity.timestamps.start
}
if (!activity.assets) {
activity.assets = { "large_text": " ", "small_text": " " }
}
addedHTML += `
<div class="chip activity grid-child">
<img src="${get_img(activity)}" title="${activity.assets.large_text || activity.assets.small_text}">
<p>
<span style="color: rgb(225, 200, 255);">${activity.name}</span>
<br> ${(activity.details || activity.assets.large_text || " ")}
<br> ${(activity.state || activity.assets.small_text || " ")}
<br> ${gameTimeFormatter((Date.now() - time) / 1000)}
</p>
</div>
`
}
}
}
return addedHTML + "</div>"
}
}

View file

@ -1,7 +1,8 @@
const path = require('path'), const path = require('path'),
fs = require('fs'), fs = require('fs'),
WebSocket = require('ws'), WebSocket = require('ws'),
minify = require('minify-html') minify = require('minify-html'),
activityToHTML = require("./overcomplicatedStatuses.js")
var config = JSON.parse(fs.readFileSync(path.join(__dirname, 'config.json'))) var config = JSON.parse(fs.readFileSync(path.join(__dirname, 'config.json')))
@ -16,30 +17,6 @@ var lanyardData = undefined
var uptime = Date.now() var uptime = Date.now()
function converter(html) { function converter(html) {
if (lanyardData) {
var statusData = config.discStatuses[lanyardData.discord_status]
} else {
var statusData = config.discStatuses.offline
}
var replacers = {
"COMMIT_COUNT": commitCount,
"RANDOM_QUOTE": quotes[Math.floor(Math.random() * quotes.length)],
"QUOTE_COUNT": quotes.length,
"RANDOM_TITLE": titles[Math.floor(Math.random() * titles.length)],
"DISCORD_STATUS":
`<span style="color: ${statusData.color};">${statusData.text}</span>` +
`<style>.pfp { border-color: ${statusData.color} }</style>`,
"UPTIME": uptime,
"TOPBAR": `<div id="topbar"><h3><a href="/socials">Socials</a></h3></div>`
}
var rpTable = Object.keys(replacers)
for (let index = 0; index < rpTable.length; index++) {
const text = rpTable[index];
html = html.replaceAll(`{${text}}`, replacers[text])
}
while (html.includes("{PATH_")) { while (html.includes("{PATH_")) {
var pagePath = html.substring(html.indexOf("{PATH_")) var pagePath = html.substring(html.indexOf("{PATH_"))
pagePath = pagePath.substring(6, pagePath.indexOf('}')) pagePath = pagePath.substring(6, pagePath.indexOf('}'))
@ -52,6 +29,42 @@ function converter(html) {
html = html.replace(stringIndex, pageHTML) html = html.replace(stringIndex, pageHTML)
} }
var statusText = ""
if (lanyardData) {
var statusData = config.discStatuses[lanyardData.discord_status]
var username = lanyardData.discord_user.username
if (lanyardData.activities[0] && lanyardData.activities[0].type == 4) {
var statusText = `<hr><p>${lanyardData.activities[0].state}</p>`
}
} else {
var statusData = config.discStatuses.offline
var username = "bingus_violet"
}
var replacers = {
"COMMIT_COUNT": commitCount,
"RANDOM_QUOTE": quotes[Math.floor(Math.random() * quotes.length)],
"QUOTE_COUNT": quotes.length,
"RANDOM_TITLE": titles[Math.floor(Math.random() * titles.length)],
"DISCORD_STATUS":
`<span style="color: ${statusData.color};">${statusData.text}</span>` +
`<style>.pfp { border-color: ${statusData.color} }</style>`,
"UPTIME": uptime,
"TOPBAR": `<div id="topbar"><h3><a href="/socials">Socials</a></h3></div>`,
"DISCORD_USER": username,
"CUSTOM_STATUS": statusText,
"ACTIVITIES": activityToHTML.activitiesToHTML(lanyardData, cachedImages)
}
var rpTable = Object.keys(replacers)
for (let index = 0; index < rpTable.length; index++) {
const text = rpTable[index];
html = html.replaceAll(`{${text}}`, replacers[text])
}
var bodyHTML = html.substring(html.indexOf("<body>") + 6, html.lastIndexOf("</body>")) var bodyHTML = html.substring(html.indexOf("<body>") + 6, html.lastIndexOf("</body>"))
var highTable = Object.keys(highlightedWords) var highTable = Object.keys(highlightedWords)
for (let index = 0; index < highTable.length; index++) { for (let index = 0; index < highTable.length; index++) {
@ -73,6 +86,14 @@ module.exports = {
var filePath = (req.baseUrl + req.path).trim() var filePath = (req.baseUrl + req.path).trim()
if (filePath.includes("cached") || filePath.includes("imgs")) {
filePath = path.join(__dirname, 'static', filePath)
console.log(filePath)
res.send(fs.readFileSync(filePath))
return
}
if (filePath.includes(".")) { if (filePath.includes(".")) {
} else { } else {

BIN
static/imgs/notFound.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View file

@ -25,7 +25,7 @@
<main class="animatedMain"> <main class="animatedMain">
<p>{RANDOM_QUOTE}</p> <p>{RANDOM_QUOTE}</p>
<div id="card"> <div id="card">
<h2>Violet</h2> <h2>{Violet}</h2>
<div style="display: flex; justify-content: center; align-items: center;"> <div style="display: flex; justify-content: center; align-items: center;">
<img src="https://api.violets-purgatory.dev/v1/pfp" class="pfp"> <img src="https://api.violets-purgatory.dev/v1/pfp" class="pfp">
<div> <div>
@ -34,23 +34,19 @@
<p>{DISCORD_STATUS}</p> <p>{DISCORD_STATUS}</p>
</div> </div>
</div> </div>
<a class="chip" href="https://https://ko-fi.com/bingus_violet">Donate (Ko-fi)</a> <hr>
<div> <div>
<p style="padding: 10px;">Hi! I'm Violet, a 15 year old web and game developer. <br> I aspire to make fast and Javascript free websites! I'm currently learning the Godot Engine, and have been becoming quite fluent in NodeJS.</p> <p style="padding: 10px;">Hi! I'm Violet, a 15 year old web and game developer. <br> I aspire to make fast and Javascript free websites! I'm currently learning the Godot Engine, but most of my time recently has been spent learning NodeJS.</p>
<a class="chip" href="https://beta.violets-purgatory.dev">Beta site</a> <a class="chip" href="https://beta.violets-purgatory.dev">Beta site</a>
<a class="chip" href="https://blog.violets-purgatory.dev">Blog</a> <a class="chip" href="https://blog.violets-purgatory.dev">Blog</a>
<a class="chip" href="https://fs.violets-purgatory.dev">Clipdump</a> <a class="chip" href="https://fs.violets-purgatory.dev">Clipdump</a>
{CUSTOM_STATUS}
</div> </div>
</div> </div>
{ACTIVITIES}
<div style="padding-bottom: 20px;"> <hr>
<h3>Main Projects</h3> <h1>Socials</h1>
<a class="chip" href="https://univerter.dev">Univerter</a>
<a class="chip" href="https://codeberg.org/bingus_violet/steamrpc">{Steam}RPC</a>
</div>
<h2>Socials</h2>
{PATH_SOCIALS} {PATH_SOCIALS}
</main> </main>
</body> </body>

View file

@ -11,8 +11,8 @@
} }
#card { #card {
background-color: rgb(75, 25, 100); background-color: rgb(25, 5, 80);
padding: 15px; padding: 15px 5px;
border: 2px white solid; border: 2px white solid;
margin: 20px auto; margin: 20px auto;
width: 95%; width: 95%;
@ -43,6 +43,90 @@
border-radius: 50%; border-radius: 50%;
} }
.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;
padding: 5px;
justify-content: center;
}
.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);
}
img:not(.project-inner > div > img) {
width: 100%;
max-width: 135px;
transition: all 2s cubic-bezier(0.075, 0.82, 0.165, 1);
}
@media screen and (min-width: 750px) {
.activity-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 10px;
}
.activity {
margin: auto;
width: 100%;
align-content: center;
/* border: 2px white solid; */
}
}
.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;
}
@keyframes mainText { @keyframes mainText {
0% { 0% {
transform: translateY(calc(50vh - 6rem)) scale(1.5); transform: translateY(calc(50vh - 6rem)) scale(1.5);

View file

@ -23,44 +23,41 @@
<body> <body>
<h1>Socials</h1> <h1>Socials</h1>
<main> <main>
<p>Here's most of the sites you can find me on- if you needed that for some reason?</p>
<div class="grid-container"> <div class="grid-container">
<div class="grid-child"> <div class="grid-child">
<div> <div>
<h3>Social Media</h3> <h3>Social Media</h3>
<a class="chip" href="https://www.youtube.com/channel/UChcrBJNJLZucy3TPyGyAY2g">Youtube: <span <a class="chip" href="https://www.youtube.com/channel/UChcrBJNJLZucy3TPyGyAY2g">Youtube: {Violet}'s Fiasco</a>
style="color: white;">{Violet}'s Fiasco</span></a> <a class="chip" href="https://ko-fi.com/bingus_violet">Ko-fi: Bingus_{Violet}</a>
<a class="chip" href="https://ko-fi.com/bingus_violet">Ko-fi: <span <a class="chip" href="https://void.lgbt/bingus_violet" rel="me">Fedi: bingus_violet&ZeroWidthSpace;@void.lgbt</a>
style="color: white;">Bingus_{Violet}</span></a>
<a class="chip" href="https://void.lgbt/bingus_violet" rel="me">Fedi: <span
style="color: white;">bingus_violet&ZeroWidthSpace;@void.lgbt</span></a>
</div> </div>
</div> </div>
<div class="grid-child"> <div class="grid-child">
<div> <div>
<h3>Chat</h3> <h3>Chat</h3>
<a class="chip" href="https://matrix.to/#/@bingus_violet:catgirl.cloud">Matrix: <span <a class="chip" href="https://matrix.to/#/@bingus_violet:catgirl.cloud">Matrix: @bingus_violet:&ZeroWidthSpace;catgirl.cloud</a>
style="color: white;">@bingus_violet:&ZeroWidthSpace;catgirl.cloud</span></a> <p class="chip">Discord: {DISCORD_USER}</p>
<p class="chip">Revolt: Bingus{Violet}#5573</p>
</div> </div>
</div> </div>
<div class="grid-child"> <div class="grid-child">
<div> <div>
<h3>Coding</h3> <h3>Coding</h3>
<a class="chip" href="https://codeberg.org/Bingus_violet">Codeberg: <span <a class="chip" href="https://codeberg.org/Bingus_violet">Codeberg: bingus_violet</a>
style="color: white;">bingus_violet</span></a> <a class="chip" href="https://hub.docker.com/u/bingusviolet">Docker: bingusviolet</a>
<a class="chip" href="https://hub.docker.com/u/bingusviolet">Docker: <span <a class="chip" href="https://github.com/violets-puragtory">Github: violets-puragtory</a>
style="color: white;">bingusviolet</span></a>
<a class="chip" href="https://github.com/violets-puragtory">Github: <span
style="color: white;">violets-puragtory</span></a>
</div> </div>
</div> </div>
<div class="grid-child"> <div class="grid-child">
<div> <div>
<h3>Games</h3> <h3>Games</h3>
<a class="chip" href="https://steamcommunity.com/id/violet-The-Thigh-high-obtainer/">Steam: <span <a class="chip" href="https://steamcommunity.com/id/violet-The-Thigh-high-obtainer/">Steam: {Violet}</a>
style="color: white;">{Violet}</span></a>
</div> </div>
</div> </div>
</div> </div>
<br>
<p class="note">Please note I am extremely unhinged and gay on Fedi, I don't use Github, and I barely understand Docker.</p>
</main> </main>
</body> </body>

View file

@ -40,7 +40,7 @@
transform: scale(1.05); transform: scale(1.05);
} }
#topbar > * { #topbar>* {
display: inline-block; display: inline-block;
font-size: 1.5rem; font-size: 1.5rem;
} }
@ -83,7 +83,7 @@ h3 {
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
grid-gap: 10px; grid-gap: 10px;
} }
.grid-child { .grid-child {
margin: auto; margin: auto;
align-content: center; align-content: center;
@ -91,8 +91,6 @@ h3 {
} }
} }
.chip { .chip {
position: relative; position: relative;
z-index: 3; z-index: 3;
@ -129,8 +127,12 @@ h3 {
} }
hr { hr {
border: 2px gray solid; color: white;
margin: 20px; border: white solid;
opacity: 0.25;
border-width: 2px;
margin: 15px 10%;
/* background-color: none; */
} }
p { p {