Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • dev
  • main
2 results

Target

Select target project
  • creations/profilePage
1 result
Select Git revision
Loading items
Show changes

Commits on Source 0

    {
    "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
    "vcs": {
    "enabled": true,
    "clientKind": "git",
    "useIgnoreFile": false
    },
    "files": {
    "ignoreUnknown": false,
    "ignore": []
    },
    "formatter": {
    "enabled": true,
    "indentStyle": "tab",
    "lineEnding": "lf"
    },
    "organizeImports": {
    "enabled": true
    },
    "linter": {
    "enabled": true,
    "rules": {
    "recommended": true
    }
    },
    "javascript": {
    "formatter": {
    "quoteStyle": "double",
    "indentStyle": "tab",
    "lineEnding": "lf",
    "jsxQuoteStyle": "double",
    "semicolons": "always"
    }
    }
    }
    export const environment: Environment = {
    port: Number.parseInt(process.env.PORT || "8080", 10),
    port: parseInt(process.env.PORT || "8080", 10),
    host: process.env.HOST || "0.0.0.0",
    development:
    process.env.NODE_ENV === "development" || process.argv.includes("--dev"),
    process.env.NODE_ENV === "development" ||
    process.argv.includes("--dev"),
    };
    export const lanyardConfig: LanyardConfig = {
    ......
    import pluginJs from "@eslint/js";
    import tseslintPlugin from "@typescript-eslint/eslint-plugin";
    import tsParser from "@typescript-eslint/parser";
    import prettier from "eslint-plugin-prettier";
    import promisePlugin from "eslint-plugin-promise";
    import simpleImportSort from "eslint-plugin-simple-import-sort";
    import unicorn from "eslint-plugin-unicorn";
    import unusedImports from "eslint-plugin-unused-imports";
    import globals from "globals";
    /** @type {import('eslint').Linter.FlatConfig[]} */
    export default [
    {
    files: ["**/*.{js,mjs,cjs}"],
    languageOptions: {
    globals: globals.node,
    },
    ...pluginJs.configs.recommended,
    plugins: {
    "simple-import-sort": simpleImportSort,
    "unused-imports": unusedImports,
    promise: promisePlugin,
    prettier: prettier,
    unicorn: unicorn,
    },
    rules: {
    "eol-last": ["error", "always"],
    "no-multiple-empty-lines": ["error", { max: 1, maxEOF: 1 }],
    "no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
    "simple-import-sort/imports": "error",
    "simple-import-sort/exports": "error",
    "unused-imports/no-unused-imports": "error",
    "unused-imports/no-unused-vars": [
    "warn",
    {
    vars: "all",
    varsIgnorePattern: "^_",
    args: "after-used",
    argsIgnorePattern: "^_",
    },
    ],
    "promise/always-return": "error",
    "promise/no-return-wrap": "error",
    "promise/param-names": "error",
    "promise/catch-or-return": "error",
    "promise/no-nesting": "warn",
    "promise/no-promise-in-callback": "warn",
    "promise/no-callback-in-promise": "warn",
    "prettier/prettier": [
    "error",
    {
    useTabs: true,
    tabWidth: 4,
    },
    ],
    indent: ["error", "tab", { SwitchCase: 1 }],
    "unicorn/filename-case": [
    "error",
    {
    case: "camelCase",
    },
    ],
    },
    },
    {
    files: ["**/*.{ts,tsx}"],
    languageOptions: {
    parser: tsParser,
    globals: globals.node,
    },
    plugins: {
    "@typescript-eslint": tseslintPlugin,
    "simple-import-sort": simpleImportSort,
    "unused-imports": unusedImports,
    promise: promisePlugin,
    prettier: prettier,
    unicorn: unicorn,
    },
    rules: {
    ...tseslintPlugin.configs.recommended.rules,
    quotes: ["error", "double"],
    "eol-last": ["error", "always"],
    "no-multiple-empty-lines": ["error", { max: 1, maxEOF: 1 }],
    "no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
    "simple-import-sort/imports": "error",
    "simple-import-sort/exports": "error",
    "unused-imports/no-unused-imports": "error",
    "unused-imports/no-unused-vars": [
    "warn",
    {
    vars: "all",
    varsIgnorePattern: "^_",
    args: "after-used",
    argsIgnorePattern: "^_",
    },
    ],
    "promise/always-return": "error",
    "promise/no-return-wrap": "error",
    "promise/param-names": "error",
    "promise/catch-or-return": "error",
    "promise/no-nesting": "warn",
    "promise/no-promise-in-callback": "warn",
    "promise/no-callback-in-promise": "warn",
    "prettier/prettier": [
    "error",
    {
    useTabs: true,
    tabWidth: 4,
    },
    ],
    indent: ["error", "tab", { SwitchCase: 1 }],
    "unicorn/filename-case": [
    "error",
    {
    case: "camelCase",
    },
    ],
    "@typescript-eslint/explicit-function-return-type": ["error"],
    "@typescript-eslint/explicit-module-boundary-types": ["error"],
    "@typescript-eslint/typedef": [
    "error",
    {
    arrowParameter: true,
    variableDeclaration: true,
    propertyDeclaration: true,
    memberVariableDeclaration: true,
    parameter: true,
    },
    ],
    },
    },
    ];
    ......@@ -5,15 +5,24 @@
    "scripts": {
    "start": "bun run src/index.ts",
    "dev": "bun run --hot src/index.ts --dev",
    "lint": "bunx biome check",
    "lint:fix": "bunx biome check --fix",
    "lint": "eslint",
    "lint:fix": "bun lint --fix",
    "cleanup": "rm -rf logs node_modules bun.lockdb"
    },
    "devDependencies": {
    "@biomejs/biome": "^1.9.4",
    "@eslint/js": "^9.24.0",
    "@types/bun": "^1.2.8",
    "@types/ejs": "^3.1.5",
    "globals": "^16.0.0"
    "@typescript-eslint/eslint-plugin": "^8.29.0",
    "@typescript-eslint/parser": "^8.29.0",
    "eslint": "^9.24.0",
    "eslint-plugin-prettier": "^5.2.6",
    "eslint-plugin-promise": "^7.2.1",
    "eslint-plugin-simple-import-sort": "^12.1.1",
    "eslint-plugin-unicorn": "^58.0.0",
    "eslint-plugin-unused-imports": "^4.1.4",
    "globals": "^16.0.0",
    "prettier": "^3.5.3"
    },
    "peerDependencies": {
    "typescript": "^5.8.3"
    ......
    :root {
    --background: #0e0e10;
    --card-bg: #1e1f22;
    --card-hover-bg: #2a2a2d;
    --border-color: #2e2e30;
    --text-color: #ffffff;
    --text-subtle: #bbb;
    --text-secondary: #b5bac1;
    --text-muted: #888;
    --link-color: #00b0f4;
    --status-online: #23a55a;
    --status-idle: #f0b232;
    --status-dnd: #e03e3e;
    --status-offline: #747f8d;
    --status-streaming: #b700ff;
    --progress-bg: #f23f43;
    --progress-fill: #5865f2;
    --button-bg: #5865f2;
    --button-hover-bg: #4752c4;
    --button-disabled-bg: #2d2e31;
    --blockquote-color: #aaa;
    --code-bg: #2e2e30;
    --readme-bg: #1a1a1d;
    }
    body {
    font-family: system-ui, sans-serif;
    background-color: var(--background);
    color: var(--text-color);
    background-color: #0e0e10;
    color: #ffffff;
    margin: 0;
    padding: 2rem;
    display: flex;
    ......@@ -83,30 +52,26 @@ body {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 4px solid var(--background);
    border: 4px solid #0e0e10;
    display: flex;
    align-items: center;
    justify-content: center;
    }
    .status-indicator.online {
    background-color: var(--status-online);
    background-color: #23a55a;
    }
    .status-indicator.idle {
    background-color: var(--status-idle);
    background-color: #f0b232;
    }
    .status-indicator.dnd {
    background-color: var(--status-dnd);
    background-color: #f23f43;
    }
    .status-indicator.offline {
    background-color: var(--status-offline);
    }
    .status-indicator.streaming {
    background-color: var(--status-streaming);
    background-color: #747f8d;
    }
    .platform-icon.mobile-only {
    ......@@ -126,12 +91,12 @@ body {
    h1 {
    font-size: 2.5rem;
    margin: 0;
    color: var(--link-color);
    color: #00b0f4;
    }
    .custom-status {
    font-size: 1.2rem;
    color: var(--text-subtle);
    color: #bbb;
    margin-top: 0.25rem;
    word-break: break-word;
    overflow-wrap: anywhere;
    ......@@ -142,6 +107,7 @@ h1 {
    flex-wrap: wrap;
    }
    .custom-status .custom-emoji {
    width: 20px;
    height: 20px;
    ......@@ -176,14 +142,14 @@ ul {
    display: flex;
    flex-direction: row;
    gap: 1rem;
    background-color: var(--card-bg);
    background-color: #1e1f22;
    padding: 0.75rem 1rem;
    border-radius: 10px;
    border: 1px solid var(--border-color);
    box-shadow: 0 1px 0 0 #2e2e30;
    }
    .activity:hover {
    background: var(--card-hover-bg);
    background: #2a2a2d;
    }
    .activity-wrapper {
    ......@@ -198,28 +164,7 @@ ul {
    gap: 1rem;
    }
    .activity-image-wrapper {
    position: relative;
    width: 80px;
    height: 80px;
    }
    .activity-image-small {
    width: 25px;
    height: 25px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    border-color: var(--card-bg);
    border-width: 2px;
    border-style: solid;
    position: absolute;
    bottom: -6px;
    right: -10px;
    }
    .activity-image {
    .activity-art {
    width: 80px;
    height: 80px;
    border-radius: 6px;
    ......@@ -257,17 +202,17 @@ ul {
    .activity-name {
    font-weight: 600;
    font-size: 1rem;
    color: var(--text-color);
    color: #fff;
    }
    .activity-detail {
    font-size: 0.875rem;
    color: var(--text-secondary);
    color: #b5bac1;
    }
    .activity-timestamp {
    font-size: 0.75rem;
    color: var(--text-secondary);
    color: #b5bac1;
    text-align: right;
    margin-left: auto;
    white-space: nowrap;
    ......@@ -275,14 +220,14 @@ ul {
    .progress-bar {
    height: 4px;
    background-color: var(--border-color);
    background-color: #2e2e30;
    border-radius: 2px;
    margin-top: 1rem;
    margin-top: 0.5rem;
    overflow: hidden;
    }
    .progress-fill {
    background-color: var(--progress-fill);
    background-color: #5865f2;
    transition: width 0.4s ease;
    height: 100%;
    }
    ......@@ -290,13 +235,14 @@ ul {
    .progress-bar,
    .progress-time-labels {
    width: 100%;
    margin-top: 0.5rem;
    }
    .progress-time-labels {
    display: flex;
    justify-content: space-between;
    font-size: 0.75rem;
    color: var(--text-muted);
    color: #888;
    margin-top: 0.25rem;
    }
    ......@@ -310,7 +256,7 @@ ul {
    font-size: 0.75rem;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--blockquote-color);
    color: #aaa;
    margin-bottom: 0.50rem;
    display: block;
    }
    ......@@ -321,7 +267,7 @@ ul {
    .progress-time-labels.paused .progress-current::after {
    content: " ⏸";
    color: var(--status-idle);
    color: #f0b232;
    }
    .activity-buttons {
    ......@@ -332,7 +278,7 @@ ul {
    }
    .activity-button {
    background-color: var(--progress-fill);
    background-color: #5865f2;
    color: white;
    border: none;
    border-radius: 3px;
    ......@@ -345,12 +291,12 @@ ul {
    }
    .activity-button:hover {
    background-color: var(--button-hover-bg);
    background-color: #4752c4;
    text-decoration: none;
    }
    .activity-button:disabled {
    background-color: var(--button-disabled-bg);
    background-color: #2d2e31;
    cursor: not-allowed;
    opacity: 0.8;
    }
    ......@@ -379,13 +325,6 @@ ul {
    width: 100%;
    }
    .activity-image-wrapper {
    max-width: 100%;
    max-height: 100%;
    width: 100%;
    height: 100%;
    }
    .avatar-wrapper {
    width: 96px;
    height: 96px;
    ......@@ -443,28 +382,18 @@ ul {
    border-radius:0;
    }
    .activity-image {
    .activity-art {
    width: 100%;
    max-width: 100%;
    max-width: 300px;
    height: auto;
    border-radius: 8px;
    }
    .activity-image-small {
    width: 40px;
    height: 40px;
    }
    .activity-content {
    width: 100%;
    align-items: center;
    }
    .activity-wrapper-inner {
    flex-direction: column;
    align-items: center;
    }
    .activity-header {
    flex-direction: column;
    align-items: center;
    ......@@ -501,12 +430,12 @@ ul {
    /* readme :p */
    .readme {
    max-width: 700px;
    max-width: 600px;
    width: 100%;
    background: var(--readme-bg);
    background: #1a1a1d;
    padding: 1.5rem;
    border-radius: 8px;
    border: 1px solid var(--border-color);
    box-shadow: 0 0 0 1px #2e2e30;
    margin-top: 2rem;
    ......@@ -517,13 +446,13 @@ ul {
    .readme h2 {
    margin-top: 0;
    color: var(--link-color);
    color: #00b0f4;
    }
    .markdown-body {
    font-size: 1rem;
    line-height: 1.6;
    color: var(--text-color);
    color: #ddd;
    }
    .markdown-body h1,
    ......@@ -532,7 +461,7 @@ ul {
    .markdown-body h4,
    .markdown-body h5,
    .markdown-body h6 {
    color: var(--text-color);
    color: #ffffff;
    margin-top: 1.25rem;
    margin-bottom: 0.5rem;
    }
    ......@@ -542,7 +471,7 @@ ul {
    }
    .markdown-body a {
    color: var(--link-color);
    color: #00b0f4;
    text-decoration: none;
    }
    ......@@ -551,7 +480,7 @@ ul {
    }
    .markdown-body code {
    background: var(--border-color);
    background: #2e2e30;
    padding: 0.2em 0.4em;
    border-radius: 4px;
    font-family: monospace;
    ......@@ -559,7 +488,7 @@ ul {
    }
    .markdown-body pre {
    background: var(--border-color);
    background: #2e2e30;
    padding: 1rem;
    border-radius: 6px;
    overflow-x: auto;
    ......@@ -574,9 +503,9 @@ ul {
    }
    .markdown-body blockquote {
    border-left: 4px solid var(--link-color);
    border-left: 4px solid #00b0f4;
    padding-left: 1rem;
    color: var(--blockquote-color);
    color: #aaa;
    margin: 1rem 0;
    }
    ......
    /* eslint-disable indent */
    const activityProgressMap = new Map();
    function formatTime(ms) {
    ......@@ -21,19 +23,19 @@ function formatVerbose(ms) {
    function updateElapsedAndProgress() {
    const now = Date.now();
    for (const el of document.querySelectorAll(".activity-timestamp")) {
    document.querySelectorAll(".activity-timestamp").forEach((el) => {
    const start = Number(el.dataset.start);
    if (!start) continue;
    if (!start) return;
    const elapsed = now - start;
    const display = el.querySelector(".elapsed");
    if (display) display.textContent = `(${formatVerbose(elapsed)} ago)`;
    }
    });
    for (const bar of document.querySelectorAll(".progress-bar")) {
    document.querySelectorAll(".progress-bar").forEach((bar) => {
    const start = Number(bar.dataset.start);
    const end = Number(bar.dataset.end);
    if (!start || !end || end <= start) continue;
    if (!start || !end || end <= start) return;
    const duration = end - start;
    const elapsed = Math.min(now - start, duration);
    ......@@ -44,12 +46,12 @@ function updateElapsedAndProgress() {
    const fill = bar.querySelector(".progress-fill");
    if (fill) fill.style.width = `${progress}%`;
    }
    });
    for (const label of document.querySelectorAll(".progress-time-labels")) {
    document.querySelectorAll(".progress-time-labels").forEach((label) => {
    const start = Number(label.dataset.start);
    const end = Number(label.dataset.end);
    if (!start || !end || end <= start) continue;
    if (!start || !end || end <= start) return;
    const isPaused = now > end;
    const current = isPaused ? end - start : Math.max(0, now - start);
    ......@@ -75,14 +77,14 @@ function updateElapsedAndProgress() {
    : formatTime(current);
    }
    if (totalEl) totalEl.textContent = formatTime(total);
    }
    });
    }
    updateElapsedAndProgress();
    setInterval(updateElapsedAndProgress, 1000);
    const head = document.querySelector("head");
    const userId = head?.dataset.userId;
    let userId = head?.dataset.userId;
    let instanceUri = head?.dataset.instanceUri;
    if (userId && instanceUri) {
    ......@@ -130,25 +132,6 @@ if (userId && instanceUri) {
    });
    }
    function resolveActivityImage(img, applicationId) {
    if (!img) return null;
    if (img.startsWith("mp:external/")) {
    return `https://media.discordapp.net/external/${img.slice("mp:external/".length)}`;
    }
    if (img.includes("/https/")) {
    const clean = img.split("/https/")[1];
    return clean ? `https://${clean}` : null;
    }
    if (img.startsWith("spotify:")) {
    return `https://i.scdn.co/image/${img.split(":")[1]}`;
    }
    return `https://cdn.discordapp.com/app-assets/${applicationId}/${img}.png`;
    }
    function buildActivityHTML(activity) {
    const start = activity.timestamps?.start;
    const end = activity.timestamps?.end;
    ......@@ -160,18 +143,18 @@ function buildActivityHTML(activity) {
    ? Math.min(100, Math.floor((elapsed / total) * 100))
    : null;
    const img = activity.assets?.large_image;
    let art = null;
    let smallArt = null;
    if (activity.assets) {
    art = resolveActivityImage(
    activity.assets.large_image,
    activity.application_id,
    );
    smallArt = resolveActivityImage(
    activity.assets.small_image,
    activity.application_id,
    );
    if (img?.startsWith("mp:external/")) {
    art = `https://media.discordapp.net/external/${img.slice("mp:external/".length)}`;
    } else if (img?.includes("/https/")) {
    const clean = img.split("/https/")[1];
    if (clean) art = `https://${clean}`;
    } else if (img?.startsWith("spotify:")) {
    art = `https://i.scdn.co/image/${img.split(":")[1]}`;
    } else if (img) {
    art = `https://cdn.discordapp.com/app-assets/${activity.application_id}/${img}.png`;
    }
    const activityTypeMap = {
    ......@@ -206,7 +189,10 @@ function buildActivityHTML(activity) {
    ? `<div class="activity-buttons">
    ${activity.buttons
    .map((button, index) => {
    const label = typeof button === "string" ? button : button.label;
    const label =
    typeof button === "string"
    ? button
    : button.label;
    let url = null;
    if (typeof button === "object" && button.url) {
    url = button.url;
    ......@@ -239,13 +225,6 @@ function buildActivityHTML(activity) {
    const secondaryLine = isMusic ? activity.state : activity.details;
    const tertiaryLine = isMusic ? activity.assets?.large_text : activity.state;
    const activityArt = art
    ? `<div class="activity-image-wrapper">
    <img class="activity-image" src="${art}" alt="Art" ${activity.assets?.large_text ? `title="${activity.assets.large_text}"` : ""}>
    ${smallArt ? `<img class="activity-image-small" src="${smallArt}" alt="Small Art" ${activity.assets?.small_text ? `title="${activity.assets.small_text}"` : ""}>` : ""}
    </div>`
    : "";
    return `
    <li class="activity">
    <div class="activity-wrapper">
    ......@@ -254,7 +233,7 @@ function buildActivityHTML(activity) {
    ${activityTimestamp}
    </div>
    <div class="activity-wrapper-inner">
    ${activityArt}
    ${art ? `<img class="activity-art" src="${art}" alt="Art">` : ""}
    <div class="activity-content">
    <div class="inner-content">
    <div class="activity-top">
    ......@@ -279,7 +258,9 @@ function buildActivityHTML(activity) {
    function updatePresence(data) {
    const avatarWrapper = document.querySelector(".avatar-wrapper");
    const statusIndicator = avatarWrapper?.querySelector(".status-indicator");
    const mobileIcon = avatarWrapper?.querySelector(".platform-icon.mobile-only");
    const mobileIcon = avatarWrapper?.querySelector(
    ".platform-icon.mobile-only",
    );
    const userInfo = document.querySelector(".user-info");
    const customStatus = userInfo?.querySelector(".custom-status");
    ......@@ -290,16 +271,8 @@ function updatePresence(data) {
    desktop: data.active_on_discord_desktop,
    };
    let status = "offline";
    console.log(data.activities.some((activity) => activity.type === 1));
    if (data.activities.some((activity) => activity.type === 1)) {
    status = "streaming";
    } else {
    status = data.discord_status;
    }
    if (statusIndicator) {
    statusIndicator.className = `status-indicator ${status}`;
    statusIndicator.className = `status-indicator ${data.discord_status}`;
    }
    if (platform.mobile && !mobileIcon) {
    ......@@ -310,7 +283,7 @@ function updatePresence(data) {
    `;
    } else if (!platform.mobile && mobileIcon) {
    mobileIcon.remove();
    avatarWrapper.innerHTML += `<div class="status-indicator ${status}"></div>`;
    avatarWrapper.innerHTML += `<div class="status-indicator ${data.discord_status}"></div>`;
    }
    const custom = data.activities?.find((a) => a.type === 4);
    ......
    export function timestampToReadable(timestamp?: number): string {
    const date: Date =
    timestamp && !Number.isNaN(timestamp) ? new Date(timestamp) : new Date();
    if (Number.isNaN(date.getTime())) return "Invalid Date";
    timestamp && !isNaN(timestamp) ? new Date(timestamp) : new Date();
    if (isNaN(date.getTime())) return "Invalid Date";
    return date.toISOString().replace("T", " ").replace("Z", "");
    }
    import { resolve } from "node:path";
    import { renderFile } from "ejs";
    import { resolve } from "path";
    export async function renderEjsTemplate(
    viewName: string | string[],
    ......
    ......@@ -76,7 +76,7 @@ export async function handleReadMe(data: LanyardData): Promise<string | null> {
    return null;
    if (res.headers.has("content-length")) {
    const size: number = Number.parseInt(
    const size: number = parseInt(
    res.headers.get("content-length") || "0",
    10,
    );
    ......
    import type { Stats } from "node:fs";
    import { environment } from "@config/environment";
    import { timestampToReadable } from "@helpers/char";
    import type { Stats } from "fs";
    import {
    type WriteStream,
    createWriteStream,
    existsSync,
    mkdirSync,
    statSync,
    } from "node:fs";
    import { EOL } from "node:os";
    import { basename, join } from "node:path";
    import { environment } from "@config/environment";
    import { timestampToReadable } from "@helpers/char";
    WriteStream,
    } from "fs";
    import { EOL } from "os";
    import { basename, join } from "path";
    class Logger {
    private static instance: Logger;
    ......@@ -37,7 +37,7 @@ class Logger {
    mkdirSync(logDir, { recursive: true });
    }
    let addSeparator = false;
    let addSeparator: boolean = false;
    if (existsSync(logFile)) {
    const fileStats: Stats = statSync(logFile);
    ......@@ -66,9 +66,9 @@ class Logger {
    private extractFileName(stack: string): string {
    const stackLines: string[] = stack.split("\n");
    let callerFile = "";
    let callerFile: string = "";
    for (let i = 2; i < stackLines.length; i++) {
    for (let i: number = 2; i < stackLines.length; i++) {
    const line: string = stackLines[i].trim();
    if (line && !line.includes("Logger.") && line.includes("(")) {
    callerFile = line.split("(")[1]?.split(")")[0] || "";
    ......@@ -91,7 +91,7 @@ class Logger {
    return { filename, timestamp: readableTimestamp };
    }
    public info(message: string | string[], breakLine = false): void {
    public info(message: string | string[], breakLine: boolean = false): void {
    const stack: string = new Error().stack || "";
    const { filename, timestamp } = this.getCallerInfo(stack);
    ......@@ -110,7 +110,7 @@ class Logger {
    this.writeConsoleMessageColored(logMessageParts, breakLine);
    }
    public warn(message: string | string[], breakLine = false): void {
    public warn(message: string | string[], breakLine: boolean = false): void {
    const stack: string = new Error().stack || "";
    const { filename, timestamp } = this.getCallerInfo(stack);
    ......@@ -131,7 +131,7 @@ class Logger {
    public error(
    message: string | Error | (string | Error)[],
    breakLine = false,
    breakLine: boolean = false,
    ): void {
    const stack: string = new Error().stack || "";
    const { filename, timestamp } = this.getCallerInfo(stack);
    ......@@ -161,7 +161,7 @@ class Logger {
    bracketMessage2: string,
    message: string | string[],
    color: string,
    breakLine = false,
    breakLine: boolean = false,
    ): void {
    const stack: string = new Error().stack || "";
    const { timestamp } = this.getCallerInfo(stack);
    ......@@ -189,7 +189,7 @@ class Logger {
    private writeConsoleMessageColored(
    logMessageParts: ILogMessageParts,
    breakLine = false,
    breakLine: boolean = false,
    ): void {
    const logMessage: string = Object.keys(logMessageParts)
    .map((key: string) => {
    ......
    ......@@ -3,7 +3,11 @@ import { logger } from "@helpers/logger";
    import { serverHandler } from "@/server";
    async function main(): Promise<void> {
    try {
    serverHandler.initialize();
    } catch (error) {
    throw error;
    }
    }
    main().catch((error: Error) => {
    ......
    ......@@ -29,20 +29,13 @@ async function handler(request: ExtendedRequest): Promise<Response> {
    }
    const presence: LanyardData = data.data;
    const readme: string | Promise<string> | null = await handleReadMe(presence);
    let status: string;
    if (presence.activities.some((activity) => activity.type === 1)) {
    status = "streaming";
    } else {
    status = presence.discord_status;
    }
    const readme: string | Promise<string> | null =
    await handleReadMe(presence);
    const ejsTemplateData: EjsTemplateData = {
    title: presence.discord_user.global_name || presence.discord_user.username,
    username:
    presence.discord_user.global_name || presence.discord_user.username,
    status: status,
    title: `${presence.discord_user.username || "Unknown"}`,
    username: presence.discord_user.username,
    status: presence.discord_status,
    activities: presence.activities,
    user: presence.discord_user,
    platform: {
    ......
    ......@@ -24,7 +24,10 @@ async function handler(request: ExtendedRequest): Promise<Response> {
    try {
    res = await fetch(url);
    } catch {
    return Response.json({ error: "Failed to fetch image" }, { status: 500 });
    return Response.json(
    { error: "Failed to fetch image" },
    { status: 500 },
    );
    }
    if (!res.ok) {
    ......
    ......@@ -28,20 +28,15 @@ async function handler(): Promise<Response> {
    }
    const presence: LanyardData = data.data;
    const readme: string | Promise<string> | null = await handleReadMe(presence);
    let status: string;
    if (presence.activities.some((activity) => activity.type === 1)) {
    status = "streaming";
    } else {
    status = presence.discord_status;
    }
    const readme: string | Promise<string> | null =
    await handleReadMe(presence);
    const ejsTemplateData: EjsTemplateData = {
    title: presence.discord_user.global_name || presence.discord_user.username,
    title:
    presence.discord_user.global_name || presence.discord_user.username,
    username:
    presence.discord_user.global_name || presence.discord_user.username,
    status: status,
    status: presence.discord_status,
    activities: presence.activities,
    user: presence.discord_user,
    platform: {
    ......
    import { resolve } from "node:path";
    import { environment } from "@config/environment";
    import { logger } from "@helpers/logger";
    import {
    ......@@ -7,6 +6,7 @@ import {
    type MatchedRoute,
    type Serve,
    } from "bun";
    import { resolve } from "path";
    import { webSocketHandler } from "@/websocket";
    ......@@ -77,16 +77,21 @@ class ServerHandler {
    if (await file.exists()) {
    const fileContent: ArrayBuffer = await file.arrayBuffer();
    const contentType: string = file.type || "application/octet-stream";
    const contentType: string =
    file.type || "application/octet-stream";
    return new Response(fileContent, {
    headers: { "Content-Type": contentType },
    });
    }
    } else {
    logger.warn(`File not found: ${filePath}`);
    return new Response("Not Found", { status: 404 });
    }
    } catch (error) {
    logger.error([`Error serving static file: ${pathname}`, error as Error]);
    logger.error([
    `Error serving static file: ${pathname}`,
    error as Error,
    ]);
    return new Response("Internal Server Error", { status: 500 });
    }
    }
    ......@@ -112,7 +117,8 @@ class ServerHandler {
    try {
    const routeModule: RouteModule = await import(filePath);
    const contentType: string | null = request.headers.get("Content-Type");
    const contentType: string | null =
    request.headers.get("Content-Type");
    const actualContentType: string | null = contentType
    ? contentType.split(";")[0].trim()
    : null;
    ......@@ -139,7 +145,9 @@ class ServerHandler {
    if (
    (Array.isArray(routeModule.routeDef.method) &&
    !routeModule.routeDef.method.includes(request.method)) ||
    !routeModule.routeDef.method.includes(
    request.method,
    )) ||
    (!Array.isArray(routeModule.routeDef.method) &&
    routeModule.routeDef.method !== request.method)
    ) {
    ......@@ -164,7 +172,9 @@ class ServerHandler {
    if (Array.isArray(expectedContentType)) {
    matchesAccepts =
    expectedContentType.includes("*/*") ||
    expectedContentType.includes(actualContentType || "");
    expectedContentType.includes(
    actualContentType || "",
    );
    } else {
    matchesAccepts =
    expectedContentType === "*/*" ||
    ......@@ -203,7 +213,10 @@ class ServerHandler {
    }
    }
    } catch (error: unknown) {
    logger.error([`Error handling route ${request.url}:`, error as Error]);
    logger.error([
    `Error handling route ${request.url}:`,
    error as Error,
    ]);
    response = Response.json(
    {
    ......
    ......@@ -76,32 +76,20 @@
    const total = (start && end) ? end - start : null;
    const progress = (total && elapsed > 0) ? Math.min(100, Math.floor((elapsed / total) * 100)) : null;
    const img = activity.assets?.large_image;
    let art = null;
    let smallArt = null;
    function resolveActivityImage(img, applicationId) {
    if (!img) return null;
    if (img.startsWith("mp:external/")) {
    return `https://media.discordapp.net/external/${img.slice("mp:external/".length)}`;
    }
    if (img.includes("/https/")) {
    if (img?.startsWith("mp:external/")) {
    art = `https://media.discordapp.net/external/${img.slice("mp:external/".length)}`;
    } else if (img?.includes("/https/")) {
    const clean = img.split("/https/")[1];
    return clean ? `https://${clean}` : null;
    }
    if (img.startsWith("spotify:")) {
    return `https://i.scdn.co/image/${img.split(":")[1]}`;
    if (clean) art = `https://${clean}`;
    } else if (img?.startsWith("spotify:")) {
    art = `https://i.scdn.co/image/${img.split(":")[1]}`;
    } else if (img) {
    art = `https://cdn.discordapp.com/app-assets/${activity.application_id}/${img}.png`;
    }
    return `https://cdn.discordapp.com/app-assets/${applicationId}/${img}.png`;
    }
    if (activity.assets) {
    art = resolveActivityImage(activity.assets.large_image, activity.application_id);
    smallArt = resolveActivityImage(activity.assets.small_image, activity.application_id);
    }
    const activityTypeMap = {
    0: "Playing",
    ......@@ -136,12 +124,7 @@
    <div class="activity-wrapper-inner">
    <% if (art) { %>
    <div class="activity-image-wrapper">
    <img class="activity-image" src="<%= art %>" alt="Art" <% activity.assets?.large_text ? `title="${activity.assets.large_text}"` : '' %>>
    <% if (smallArt) { %>
    <img class="activity-image-small" src="<%= smallArt %>" alt="Small Art" <% activity.assets?.small_text ? `title="${activity.assets.small_text}"` : '' %>>
    <% } %>
    </div>
    <img class="activity-art" src="<%= art %>" alt="Art">
    <% } %>
    <div class="activity-content">
    ......
    import { logger } from "@helpers/logger";
    import type { ServerWebSocket } from "bun";
    import { type ServerWebSocket } from "bun";
    class WebSocketHandler {
    public handleMessage(ws: ServerWebSocket, message: string): void {
    ......@@ -20,7 +20,11 @@ class WebSocketHandler {
    }
    }
    public handleClose(ws: ServerWebSocket, code: number, reason: string): void {
    public handleClose(
    ws: ServerWebSocket,
    code: number,
    reason: string,
    ): void {
    logger.warn(`WebSocket closed with code ${code}, reason: ${reason}`);
    }
    }
    ......
    ......@@ -2,14 +2,28 @@
    "compilerOptions": {
    "baseUrl": "./",
    "paths": {
    "@/*": ["src/*"],
    "@config/*": ["config/*"],
    "@types/*": ["types/*"],
    "@helpers/*": ["src/helpers/*"]
    "@/*": [
    "src/*"
    ],
    "@config/*": [
    "config/*"
    ],
    "@types/*": [
    "types/*"
    ],
    "@helpers/*": [
    "src/helpers/*"
    ]
    },
    "typeRoots": ["./src/types", "./node_modules/@types"],
    "typeRoots": [
    "./src/types",
    "./node_modules/@types"
    ],
    // Enable latest features
    "lib": ["ESNext", "DOM"],
    "lib": [
    "ESNext",
    "DOM"
    ],
    "target": "ESNext",
    "module": "ESNext",
    "moduleDetection": "force",
    ......@@ -27,7 +41,11 @@
    // Some stricter flags (disabled by default)
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "noPropertyAccessFromIndexSignature": false
    "noPropertyAccessFromIndexSignature": false,
    },
    "include": ["src", "types", "config"]
    "include": [
    "src",
    "types",
    "config"
    ],
    }