2024-06-01 13:19:36 -05:00
|
|
|
const express = require("express"),
|
|
|
|
fs = require("fs"),
|
|
|
|
path = require("path"),
|
2024-06-10 15:40:44 -05:00
|
|
|
WebSocket = require('ws'),
|
|
|
|
{ Station } = require("@fridgefm/radio-core")
|
|
|
|
|
|
|
|
const station = new Station({})
|
2024-06-01 13:19:36 -05:00
|
|
|
|
|
|
|
const PORT = process.env.PORT || 8080
|
|
|
|
|
|
|
|
const cachePath = path.join(__dirname, "cache"),
|
2024-06-08 19:14:16 -05:00
|
|
|
cacheFile = path.join(__dirname, "cache.json"),
|
|
|
|
configFile = path.join(__dirname, "config.json")
|
2024-06-01 13:19:36 -05:00
|
|
|
|
2024-06-10 15:40:44 -05:00
|
|
|
var lanyardData
|
|
|
|
|
2024-06-01 13:19:36 -05:00
|
|
|
if (!fs.existsSync(cachePath)) { fs.mkdirSync(cachePath) }
|
2024-06-08 16:52:20 -05:00
|
|
|
if (!fs.existsSync(cacheFile) || !JSON.parse(fs.readFileSync(cacheFile)).songs) {
|
|
|
|
fs.writeFileSync(cacheFile, fs.readFileSync(path.join(__dirname, "defaults/cache.json")))
|
|
|
|
}
|
2024-06-08 19:14:16 -05:00
|
|
|
if (!fs.existsSync(configFile)) { fs.writeFileSync(configFile, fs.readFileSync(path.join(__dirname, "defaults/config.json")))}
|
2024-06-08 16:52:20 -05:00
|
|
|
|
|
|
|
var cacheDirs = ["songs", "imgs"]
|
|
|
|
for (var i = 0; i < cacheDirs.length; i++) {
|
|
|
|
if (!fs.existsSync(path.join(cachePath, cacheDirs[i]))) {
|
|
|
|
fs.mkdirSync(path.join(cachePath, cacheDirs[i]))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-08 19:14:16 -05:00
|
|
|
var conf = JSON.parse(fs.readFileSync(path.join(__dirname, "config.json")))
|
|
|
|
|
|
|
|
const Spotify = require("spotifydl-core").default
|
|
|
|
const spotifydl = new Spotify({
|
|
|
|
clientId: "5420a0e8fae24101ac6ad57278bde694",
|
|
|
|
clientSecret: conf.Spotify.client_secret
|
|
|
|
})
|
|
|
|
|
2024-06-08 16:52:20 -05:00
|
|
|
const songCache = path.join(cachePath, "songs"),
|
|
|
|
imgCache = path.join(cachePath, "imgs")
|
2024-06-01 13:19:36 -05:00
|
|
|
|
|
|
|
var app = express()
|
|
|
|
|
2024-06-08 16:13:57 -05:00
|
|
|
const imgWaitMax = 2
|
2024-06-03 00:04:34 -05:00
|
|
|
|
2024-06-08 19:14:16 -05:00
|
|
|
app.use("/songs", express.static(songCache))
|
|
|
|
|
2024-06-10 15:40:44 -05:00
|
|
|
app.get("/spotify/stream", (req, res) => {
|
|
|
|
station.connectListener(req, res)
|
|
|
|
})
|
|
|
|
|
|
|
|
var lastSong = undefined
|
|
|
|
|
2024-06-01 13:19:36 -05:00
|
|
|
app.get("/cached/*", (req, res) => {
|
|
|
|
var imgURL = req.originalUrl
|
|
|
|
imgURL = imgURL.substring(imgURL.indexOf("/", 2) + 1)
|
2024-06-08 16:52:20 -05:00
|
|
|
var imgData = cachedImages.imgs[imgURL]
|
2024-06-03 00:04:34 -05:00
|
|
|
|
|
|
|
var imgWait = 0
|
|
|
|
function waitForImage() {
|
|
|
|
if (imgWait < imgWaitMax) {
|
2024-06-03 00:07:36 -05:00
|
|
|
imgWait += 0.1
|
2024-06-03 00:04:34 -05:00
|
|
|
setTimeout(() => {
|
2024-06-08 16:52:20 -05:00
|
|
|
imgData = cachedImages.imgs[imgURL]
|
2024-06-10 18:30:24 -05:00
|
|
|
console.log(imgData)
|
2024-06-03 00:04:34 -05:00
|
|
|
if (imgData) {
|
2024-06-08 16:52:20 -05:00
|
|
|
fs.createReadStream(path.join(imgCache, imgData.file)).pipe(res)
|
2024-06-03 00:04:34 -05:00
|
|
|
} else {
|
|
|
|
waitForImage()
|
|
|
|
}
|
2024-06-03 00:07:36 -05:00
|
|
|
}, 100);
|
2024-06-03 00:04:34 -05:00
|
|
|
} else {
|
|
|
|
fs.createReadStream(path.join(__dirname, "/imgs/notFound.png")).pipe(res)
|
|
|
|
}
|
|
|
|
}
|
2024-06-01 13:19:36 -05:00
|
|
|
if (imgData) {
|
2024-06-08 16:52:20 -05:00
|
|
|
fs.createReadStream(path.join(imgCache, imgData.file)).pipe(res)
|
2024-06-01 13:19:36 -05:00
|
|
|
} else {
|
2024-06-03 00:04:34 -05:00
|
|
|
waitForImage()
|
2024-06-01 13:19:36 -05:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
app.listen(PORT, () => {
|
|
|
|
console.log("Violet's cache is now listening on port: " + PORT)
|
|
|
|
})
|
|
|
|
|
|
|
|
var cachedImages = JSON.parse(fs.readFileSync(cacheFile))
|
|
|
|
|
|
|
|
var constants = JSON.parse(fs.readFileSync(path.join(__dirname, "constants.json")))
|
|
|
|
var activityImages = constants.activityImages
|
|
|
|
|
2024-06-10 18:32:11 -05:00
|
|
|
var thumborURL = "https://thumbor-production-0e82.up.railway.app/unsafe/"
|
2024-06-01 13:19:36 -05:00
|
|
|
var imgExtension = "png"
|
|
|
|
var thumborArgs = `filters:format(${imgExtension})/`
|
|
|
|
|
|
|
|
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 && size == "large_image") {
|
|
|
|
if (activity.name in activityImages) {
|
|
|
|
return decodeURIComponent(activityImages[activity.name])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
|
|
|
function socketeer() {
|
|
|
|
var lanyard = new WebSocket('https://api.violets-purgatory.dev')
|
|
|
|
|
|
|
|
lanyard.on("error", (error) => {
|
|
|
|
console.log(error)
|
|
|
|
})
|
|
|
|
|
|
|
|
lanyard.on("close", () => {
|
|
|
|
console.log("Connection Closed. Attempting Reconnect in 30 seconds.")
|
|
|
|
setTimeout(() => {
|
|
|
|
socketeer()
|
|
|
|
}, 30000);
|
|
|
|
})
|
|
|
|
|
|
|
|
function ping(dur) {
|
|
|
|
lanyard.send(JSON.stringify({
|
|
|
|
op: 3
|
|
|
|
}))
|
|
|
|
setTimeout(() => {
|
|
|
|
ping(dur)
|
|
|
|
if (Date.now() - lastPong > 120000) {
|
|
|
|
lanyard.close()
|
|
|
|
console.log("Max duration since last pong exceeded- Closing socket.")
|
|
|
|
}
|
|
|
|
}, dur);
|
|
|
|
}
|
|
|
|
|
|
|
|
lanyard.addEventListener("message", async (res) => {
|
|
|
|
var data = JSON.parse(res.data)
|
|
|
|
// console.log(data.op)
|
|
|
|
if (data.op == 1) {
|
|
|
|
console.log("Connected to API Websocket!")
|
|
|
|
ping(30000)
|
|
|
|
lastPong = Date.now()
|
|
|
|
} else if (data.op == 3) {
|
|
|
|
lastPong = Date.now()
|
|
|
|
} else if (data.op == 0) {
|
2024-06-10 15:40:44 -05:00
|
|
|
lanyardData = data.d
|
2024-06-01 13:19:36 -05:00
|
|
|
|
2024-06-08 19:14:16 -05:00
|
|
|
var spotify = lanyardData.spotify
|
|
|
|
|
|
|
|
if (conf.Spotify.client_secret && spotify) {
|
|
|
|
var trackURL = "https://open.spotify.com/track/" + spotify.track_id
|
|
|
|
|
|
|
|
var songPath = path.join(cachePath, "/songs/", spotify.track_id + ".mp3")
|
|
|
|
if (!fs.existsSync(songPath)) {
|
|
|
|
await spotifydl.downloadTrack(trackURL, songPath)
|
|
|
|
}
|
2024-06-10 15:40:44 -05:00
|
|
|
|
|
|
|
if (lastSong != spotify.track_id) {
|
|
|
|
lastSong = spotify.track_id
|
|
|
|
station.addFolder(songPath)
|
2024-06-10 15:50:41 -05:00
|
|
|
const removeSongs = (list) => list
|
|
|
|
.filter(track => track.fsStats.fullPath !== songPath);
|
|
|
|
|
|
|
|
station.reorderPlaylist(removeSongs)
|
|
|
|
|
2024-06-10 15:40:44 -05:00
|
|
|
station.start()
|
2024-06-10 15:50:41 -05:00
|
|
|
station.next()
|
2024-06-10 15:40:44 -05:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
console.log(spotify)
|
2024-06-08 19:14:16 -05:00
|
|
|
}
|
|
|
|
|
2024-06-01 13:19:36 -05:00
|
|
|
for (let index = 0; index < lanyardData.activities.length; index++) {
|
|
|
|
const activity = lanyardData.activities[index];
|
|
|
|
|
|
|
|
var imgType = undefined
|
2024-06-08 16:52:20 -05:00
|
|
|
var imgRes = "512x512/"
|
2024-06-01 13:19:36 -05:00
|
|
|
for (var i = 0; i < 2; i++) {
|
|
|
|
if (get_img_url(activity, imgType)) {
|
|
|
|
var url = get_img_url(activity, imgType)
|
2024-06-08 16:52:20 -05:00
|
|
|
var fn = Object.keys(cachedImages.imgs).length + "." + imgExtension
|
|
|
|
var fp = path.join(imgCache, fn)
|
2024-06-01 13:19:36 -05:00
|
|
|
|
2024-06-08 16:52:20 -05:00
|
|
|
if (!cachedImages.imgs[url]) {
|
2024-06-10 18:27:49 -05:00
|
|
|
const response = await (await fetch(thumborURL + imgRes + thumborArgs + url)).arrayBuffer()
|
2024-06-01 13:19:36 -05:00
|
|
|
|
|
|
|
fs.writeFileSync(fp, Buffer.from(response))
|
2024-06-08 16:52:20 -05:00
|
|
|
cachedImages.imgs[url] = {
|
2024-06-01 13:19:36 -05:00
|
|
|
"file": fn,
|
|
|
|
"lastUpdated": Date.now()
|
|
|
|
}
|
|
|
|
fs.writeFileSync(cacheFile, JSON.stringify(cachedImages))
|
|
|
|
}
|
|
|
|
imgType = "small_image"
|
2024-06-08 16:52:20 -05:00
|
|
|
imgRes = "128x128/"
|
2024-06-01 13:19:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
socketeer()
|