// probably the messiest code i've ever written but it works so :) import { Badges } from "../public/assets/badges/BadgesEncoded"; import { getFlags } from "./getFlags"; import * as LanyardTypes from "./LanyardTypes"; import { encodeBase64 } from "./toBase64"; import escape from "escape-html"; type Parameters = { theme?: string; bg?: string; animated?: string; hideDiscrim?: string; hideStatus?: string; hideTimestamp?: string; hideBadges?: string; hideProfile?: string; hideActivity?: string; ignoreAppId?: string; showDisplayName?: string; borderRadius?: string; idleMessage?: string; }; const parseBool = (string: string | undefined): boolean => string === "true" ? true : false; const parseAppId = (string: string | undefined): Array => { if (string === undefined) return []; return string.split(","); } const elapsedTime = (timestamp: any) => { let startTime = timestamp; let endTime = Number(new Date()); let difference = (endTime - startTime) / 1000; // we only calculate them, but we don't display them. // this fixes a bug in the Discord API that does not send the correct timestamp to presence. let daysDifference = Math.floor(difference / 60 / 60 / 24); difference -= daysDifference * 60 * 60 * 24; let hoursDifference = Math.floor(difference / 60 / 60); difference -= hoursDifference * 60 * 60; let minutesDifference = Math.floor(difference / 60); difference -= minutesDifference * 60; let secondsDifference = Math.floor(difference); return `${hoursDifference >= 1 ? ("0" + hoursDifference).slice(-2) + ":" : ""}${("0" + minutesDifference).slice( -2 )}:${("0" + secondsDifference).slice(-2)}`; }; const renderCard = async (body: LanyardTypes.Root, params: Parameters): Promise => { let { data } = body; let avatarBorderColor: string = "#747F8D", avatarExtension: string = "webp", statusExtension: string = "webp", activity: any = false, backgroundColor: string = "1a1c1f", theme = "dark", borderRadius = "10px", idleMessage = "I'm not currently doing anything!"; let hideStatus = parseBool(params.hideStatus); let hideTimestamp = parseBool(params.hideTimestamp); let hideBadges = parseBool(params.hideBadges); let hideProfile = parseBool(params.hideProfile); let hideActivity = params.hideActivity ?? "false"; let ignoreAppId = parseAppId(params.ignoreAppId); let hideDiscrim = parseBool(params.hideDiscrim); let showDisplayName = parseBool(params.showDisplayName); if (parseBool(params.hideDiscrim) || body.data.discord_user.discriminator === "0") hideDiscrim = true; if (data.activities[0]?.emoji?.animated) statusExtension = "gif"; if (data.discord_user.avatar && data.discord_user.avatar.startsWith("a_")) avatarExtension = "gif"; if (params.animated === "false") avatarExtension = "webp"; if (params.theme === "light") { backgroundColor = "#eee"; theme = "light"; } if (params.bg) backgroundColor = params.bg; if (params.idleMessage) idleMessage = params.idleMessage; if (params.borderRadius) borderRadius = params.borderRadius; let avatar: string; if (data.discord_user.avatar) { avatar = await encodeBase64( `https://cdn.discordapp.com/avatars/${data.discord_user.id}/${ data.discord_user.avatar }.${avatarExtension}?size=${avatarExtension === "gif" ? "64" : "256"}` ); } else { avatar = await encodeBase64( `https://cdn.discordapp.com/embed/avatars/${data.discord_user.discriminator === "0" ? ((Number(BigInt(data.discord_user.id) >> BigInt(22))) % 6) : Number(data.discord_user.discriminator) % 5}.png` ); } switch (data.discord_status) { case "online": avatarBorderColor = "#43B581"; break; case "idle": avatarBorderColor = "#FAA61A"; break; case "dnd": avatarBorderColor = "#F04747"; break; case "offline": avatarBorderColor = "#747F8D"; break; } let flags: string[] = getFlags(data.discord_user.public_flags); if (data.discord_user.avatar && data.discord_user.avatar.includes("a_")) flags.push("Nitro"); let userStatus: Record | null = null; if (data.activities[0] && data.activities[0].type === 4) userStatus = data.activities[0]; const activities = data.activities // Filter only type 0 .filter(activity => activity.type === 0) // Filter ignored app ID .filter(activity => !ignoreAppId.includes(activity.application_id ?? "")); // Take the highest one activity = Array.isArray(activities) ? activities[0] : activities; // Calculate height of parent SVG element const svgHeight = (): string => { if (hideProfile) return "130"; if (hideActivity === "true") return "91"; if (hideActivity === "whenNotUsed" && !activity && !data.listening_to_spotify) return "91"; return "210"; } // Calculate height of main div element const divHeight = (): string => { if (hideProfile) return "120"; if (hideActivity === "true") return "81"; if (hideActivity === "whenNotUsed" && !activity && !data.listening_to_spotify) return "81"; return "200"; } return `
${ hideProfile ? "" : `

${escape(showDisplayName ? data.discord_user.global_name : data.discord_user.username)}${ !hideDiscrim && !showDisplayName ? `#${ data.discord_user.discriminator }` : "" }

${hideBadges ? "" : flags.map(v => ` `).join("") }
${showDisplayName ? `

${escape(data.discord_user.username)}

` : `` } ${ userStatus && !hideStatus ? `

${ userStatus.emoji?.id ? ` ` : '' } ${ userStatus.state && userStatus.emoji?.name && !userStatus.emoji.id ? `${userStatus.emoji.name} ${escape(userStatus.state)}` : userStatus.state ? escape(userStatus.state) : !userStatus.state && userStatus.emoji?.name && !userStatus.emoji.id ? escape(userStatus.emoji.name) : '' }

` : `` }
` } ${ activity ? `
${ activity.assets?.large_image ? ` ` : ` `} ${ activity.assets?.small_image ? ` ` : `` }

${escape(activity.name)}

${ activity.details ? `

${escape(activity.details)}

` : `` } ${ activity.state ? `

${escape(activity.state)}${ activity.party?.size ? ` (${activity.party.size[0]} of ${activity.party.size[1]})` : "" }

` : `` } ${ activity.timestamps?.start && !hideTimestamp ? `

${elapsedTime(new Date(activity.timestamps.start).getTime())} elapsed

` : `` }
` : `` } ${ data.listening_to_spotify && !activity && data.activities[Object.keys(data.activities).length - 1].type === 2 ? `

LISTENING TO SPOTIFY...

${escape(data.spotify.song)}

By ${escape(data.spotify.artist)}

` : `` } ${ !activity && !data.listening_to_spotify && hideActivity === "false" ? `

${escape(idleMessage)}

` : `` }
`; }; export default renderCard;