From 1020e3ee2663e990e604bc32909049e0606bf9b8 Mon Sep 17 00:00:00 2001 From: creations <creations@creations.works> Date: Sat, 26 Apr 2025 07:29:56 -0400 Subject: [PATCH] fix issue with badge loading, profile indef loading if no user, remove unused files, organize the js --- public/js/index.js | 294 +++++++++++++++++++++++--------------------- src/views/error.ejs | 17 --- src/views/index.ejs | 2 +- types/lanyard.d.ts | 72 ----------- types/logger.d.ts | 9 -- 5 files changed, 158 insertions(+), 236 deletions(-) delete mode 100644 src/views/error.ejs delete mode 100644 types/lanyard.d.ts delete mode 100644 types/logger.d.ts diff --git a/public/js/index.js b/public/js/index.js index c492bf3..b9235e8 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -1,5 +1,12 @@ +const head = document.querySelector("head"); +const userId = head?.dataset.userId; const activityProgressMap = new Map(); +let instanceUri = head?.dataset.instanceUri; +let badgeURL = head?.dataset.badgeUrl; +let socket; +let badgesLoaded = false; + function formatTime(ms) { const totalSecs = Math.floor(ms / 1000); const hours = Math.floor(totalSecs / 3600); @@ -78,57 +85,14 @@ function updateElapsedAndProgress() { } } -updateElapsedAndProgress(); -setInterval(updateElapsedAndProgress, 1000); +function loadEffectScript(effect) { + const existing = document.querySelector(`script[data-effect="${effect}"]`); + if (existing) return; -const head = document.querySelector("head"); -const userId = head?.dataset.userId; -let instanceUri = head?.dataset.instanceUri; -let badgeURL = head?.dataset.badgeUrl; - -if (userId && instanceUri) { - if (!instanceUri.startsWith("http")) { - instanceUri = `https://${instanceUri}`; - } - - const wsUri = instanceUri - .replace(/^http:/, "ws:") - .replace(/^https:/, "wss:") - .replace(/\/$/, ""); - - const socket = new WebSocket(`${wsUri}/socket`); - - let heartbeatInterval = null; - - socket.addEventListener("open", () => {}); - - socket.addEventListener("message", (event) => { - const payload = JSON.parse(event.data); - - if (payload.op === 1 && payload.d?.heartbeat_interval) { - heartbeatInterval = setInterval(() => { - socket.send(JSON.stringify({ op: 3 })); - }, payload.d.heartbeat_interval); - - socket.send( - JSON.stringify({ - op: 2, - d: { - subscribe_to_id: userId, - }, - }), - ); - } - - if (payload.t === "INIT_STATE" || payload.t === "PRESENCE_UPDATE") { - updatePresence(payload.d); - requestAnimationFrame(() => updateElapsedAndProgress()); - } - }); - - socket.addEventListener("close", () => { - if (heartbeatInterval) clearInterval(heartbeatInterval); - }); + const script = document.createElement("script"); + script.src = `/public/js/${effect}.js`; + script.dataset.effect = effect; + document.head.appendChild(script); } function resolveActivityImage(img, applicationId) { @@ -280,95 +244,76 @@ function buildActivityHTML(activity) { `; } -if (badgeURL && badgeURL !== "null" && userId) { - if (!badgeURL.startsWith("http")) { - badgeURL = `https://${badgeURL}`; - } +async function loadBadges(userId, options = {}) { + const { + services = [], + seperated = false, + cache = true, + targetId = "badges", + serviceOrder = [], + } = options; - if (!badgeURL.endsWith("/")) { - badgeURL += "/"; - } + const params = new URLSearchParams(); + if (services.length) params.set("services", services.join(",")); + if (seperated) params.set("seperated", "true"); + if (!cache) params.set("cache", "false"); - async function loadBadges(userId, options = {}) { - const { - services = [], - seperated = false, - cache = true, - targetId = "badges", - serviceOrder = [], - } = options; + const url = `${badgeURL}${userId}?${params.toString()}`; + const target = document.getElementById(targetId); + if (!target) return; - const params = new URLSearchParams(); - if (services.length) params.set("services", services.join(",")); - if (seperated) params.set("seperated", "true"); - if (!cache) params.set("cache", "false"); + target.classList.add("hidden"); - const url = `${badgeURL}${userId}?${params.toString()}`; - const target = document.getElementById(targetId); - if (!target) return; + try { + const res = await fetch(url); + const json = await res.json(); - target.classList.add("hidden"); - - try { - const res = await fetch(url); - const json = await res.json(); - - if (!res.ok || !json.badges) { - target.textContent = "Failed to load badges."; - return; - } - - target.innerHTML = ""; - - const badgesByService = json.badges; - const renderedServices = new Set(); - - const renderBadges = (badges) => { - for (const badge of badges) { - const img = document.createElement("img"); - img.src = badge.badge; - img.alt = badge.tooltip; - img.title = badge.tooltip; - img.className = "badge"; - target.appendChild(img); - } - }; - - for (const serviceName of serviceOrder) { - const badges = badgesByService[serviceName]; - if (Array.isArray(badges) && badges.length) { - renderBadges(badges); - renderedServices.add(serviceName); - } - } - - for (const [serviceName, badges] of Object.entries(badgesByService)) { - if (renderedServices.has(serviceName)) continue; - if (Array.isArray(badges) && badges.length) { - renderBadges(badges); - } - } - - target.classList.remove("hidden"); - } catch (err) { - console.error(err); - target.innerHTML = ""; - target.classList.add("hidden"); + if (!res.ok || !json.badges) { + target.textContent = "Failed to load badges."; + return; } - } - loadBadges(userId, { - services: [], - seperated: true, - cache: true, - targetId: "badges", - serviceOrder: ["discord", "equicord", "reviewdb", "vencord"], - }); + target.innerHTML = ""; + + const badgesByService = json.badges; + const renderedServices = new Set(); + + const renderBadges = (badges) => { + for (const badge of badges) { + const img = document.createElement("img"); + img.src = badge.badge; + img.alt = badge.tooltip; + img.title = badge.tooltip; + img.className = "badge"; + target.appendChild(img); + } + }; + + for (const serviceName of serviceOrder) { + const badges = badgesByService[serviceName]; + if (Array.isArray(badges) && badges.length) { + renderBadges(badges); + renderedServices.add(serviceName); + } + } + + for (const [serviceName, badges] of Object.entries(badgesByService)) { + if (renderedServices.has(serviceName)) continue; + if (Array.isArray(badges) && badges.length) { + renderBadges(badges); + } + } + + target.classList.remove("hidden"); + } catch (err) { + console.error(err); + target.innerHTML = ""; + target.classList.add("hidden"); + } } async function updatePresence(data) { const cssLink = data.kv?.css; - if (cssLink) { try { const res = await fetch(`/api/css?url=${encodeURIComponent(cssLink)}`); @@ -384,10 +329,37 @@ async function updatePresence(data) { } const avatarWrapper = document.querySelector(".avatar-wrapper"); - - const avatarImg = document.querySelector(".avatar-wrapper .avatar"); + const avatarImg = avatarWrapper?.querySelector(".avatar"); const usernameEl = document.querySelector(".username"); + if (!data.discord_user) { + const loadingOverlay = document.getElementById("loading-overlay"); + if (loadingOverlay) { + loadingOverlay.innerHTML = ` + <div class="error-message"> + <p>Failed to load user data.</p> + </div> + `; + loadingOverlay.style.opacity = "1"; + avatarWrapper.classList.add("hidden"); + avatarImg.classList.add("hidden"); + usernameEl.classList.add("hidden"); + document.title = "Error"; + } + return; + } + + if (!badgesLoaded) { + loadBadges(userId, { + services: [], + seperated: true, + cache: true, + targetId: "badges", + serviceOrder: ["discord", "equicord", "reviewdb", "vencord"], + }); + badgesLoaded = true; + } + if (avatarImg && data.discord_user?.avatar) { const newAvatarUrl = `https://cdn.discordapp.com/avatars/${data.discord_user.id}/${data.discord_user.avatar}`; avatarImg.src = newAvatarUrl; @@ -582,12 +554,60 @@ async function getAllNoAsset() { } } -function loadEffectScript(effect) { - const existing = document.querySelector(`script[data-effect="${effect}"]`); - if (existing) return; +if (instanceUri) { + if (!instanceUri.startsWith("http")) { + instanceUri = `https://${instanceUri}`; + } - const script = document.createElement("script"); - script.src = `/public/js/${effect}.js`; - script.dataset.effect = effect; - document.head.appendChild(script); + const wsUri = instanceUri + .replace(/^http:/, "ws:") + .replace(/^https:/, "wss:") + .replace(/\/$/, ""); + + socket = new WebSocket(`${wsUri}/socket`); } + +if (badgeURL && badgeURL !== "null" && userId) { + if (!badgeURL.startsWith("http")) { + badgeURL = `https://${badgeURL}`; + } + + if (!badgeURL.endsWith("/")) { + badgeURL += "/"; + } +} + +if (userId && instanceUri) { + let heartbeatInterval = null; + + socket.addEventListener("message", (event) => { + const payload = JSON.parse(event.data); + + if (payload.op === 1 && payload.d?.heartbeat_interval) { + heartbeatInterval = setInterval(() => { + socket.send(JSON.stringify({ op: 3 })); + }, payload.d.heartbeat_interval); + + socket.send( + JSON.stringify({ + op: 2, + d: { + subscribe_to_id: userId, + }, + }), + ); + } + + if (payload.t === "INIT_STATE" || payload.t === "PRESENCE_UPDATE") { + updatePresence(payload.d); + requestAnimationFrame(() => updateElapsedAndProgress()); + } + }); + + socket.addEventListener("close", () => { + if (heartbeatInterval) clearInterval(heartbeatInterval); + }); +} + +updateElapsedAndProgress(); +setInterval(updateElapsedAndProgress, 1000); diff --git a/src/views/error.ejs b/src/views/error.ejs deleted file mode 100644 index 1a683f1..0000000 --- a/src/views/error.ejs +++ /dev/null @@ -1,17 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> -<head> - <meta charset="UTF-8"> - <title>Error</title> - <link rel="stylesheet" href="/public/css/error.css"> - <meta name="color-scheme" content="dark"> -</head> -<body> - <div class="error-container"> - <div class="error-title">Something went wrong</div> - <div class="error-message"> - <%= message || "An unexpected error occurred." %> - </div> - </div> -</body> -</html> diff --git a/src/views/index.ejs b/src/views/index.ejs index 8fff4b8..cb59ff0 100644 --- a/src/views/index.ejs +++ b/src/views/index.ejs @@ -27,7 +27,7 @@ <div class="avatar-status-wrapper"> <div class="avatar-wrapper"> <img class="avatar hidden" src=""> - <div class="status-indicator offline"></div> + <div class="status-indicator offline hidden"></div> </div> <div class="user-info"> <div class="user-info-inner"> diff --git a/types/lanyard.d.ts b/types/lanyard.d.ts deleted file mode 100644 index 9c0e136..0000000 --- a/types/lanyard.d.ts +++ /dev/null @@ -1,72 +0,0 @@ -interface DiscordUser { - id: string; - username: string; - avatar: string; - discriminator: string; - clan?: string | null; - avatar_decoration_data?: { - sku_id: string; - asset: string; - expires_at: string | null; - }; - bot: boolean; - global_name: string; - primary_guild?: string | null; - collectibles?: { - enabled: boolean; - disabled: boolean; - }; - display_name: string; - public_flags: number; -} - -interface Activity { - id: string; - name: string; - type: number; - state: string; - created_at: number; -} - -interface SpotifyData { - track_id: string; - album_id: string; - album_name: string; - artist_name: string; - track_name: string; -} - -interface Kv { - [key: string]: string; -} - -interface LanyardData { - kv: Kv; - discord_user: DiscordUser; - activities: Activity[]; - discord_status: string; - active_on_discord_web: boolean; - active_on_discord_desktop: boolean; - active_on_discord_mobile: boolean; - listening_to_spotify?: boolean; - spotify?: SpotifyData; - spotify_status: string; - active_on_spotify: boolean; - active_on_xbox: boolean; - active_on_playstation: boolean; -} - -type LanyardSuccess = { - success: true; - data: LanyardData; -}; - -type LanyardError = { - success: false; - error: { - code: string; - message: string; - }; -}; - -type LanyardResponse = LanyardSuccess | LanyardError; diff --git a/types/logger.d.ts b/types/logger.d.ts deleted file mode 100644 index ff6a601..0000000 --- a/types/logger.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -type ILogMessagePart = { value: string; color: string }; - -type ILogMessageParts = { - level: ILogMessagePart; - filename: ILogMessagePart; - readableTimestamp: ILogMessagePart; - message: ILogMessagePart; - [key: string]: ILogMessagePart; -};