Merge pull request #61 from hexaaagon/main

feat: add support of avatar decoration
This commit is contained in:
Conrad Crawford
2024-10-06 21:53:20 -04:00
committed by GitHub
3 changed files with 63 additions and 1 deletions

View File

@@ -49,6 +49,14 @@ If you don't want the default "`I'm not currently doing anything!`" as your idle
If you'd like to show your global display name as well as your username, append the query param `showDisplayName=true` to the end of the URL. This is set to `false` by default. If you'd like to show your global display name as well as your username, append the query param `showDisplayName=true` to the end of the URL. This is set to `false` by default.
### ___Avatar Decoration___
#### ___Hide Avatar Decoration___
If you don't want people seeing your Avatar Decoration, append the query param `hideDecoration=true` to the end of the URL. Your Avatar Decoration is shown by default if you have one.
#### ___Toogle Animated Avatar Decoration___
If you have an Animated Avatar Decoration, append the query param `animatedDecoration=:bool` to the end of the URL, replacing `:bool` with `true` or `false`. This is set to `true` by default.
### ___Hide Status___ ### ___Hide Status___
If you don't want people seeing your status, append the query param `hideStatus=true` to the end of the URL. Your status is shown by default if you have one. If you don't want people seeing your status, append the query param `hideStatus=true` to the end of the URL. Your status is shown by default if you have one.

View File

@@ -38,6 +38,7 @@ export interface DiscordUser {
global_name: string; global_name: string;
display_name: string; display_name: string;
clan: ClanTag | null; clan: ClanTag | null;
avatar_decoration_data: AvatarDecoration | null;
} }
export interface ClanTag { export interface ClanTag {
@@ -47,6 +48,12 @@ export interface ClanTag {
identity_guild_id: number; identity_guild_id: number;
} }
export interface AvatarDecoration {
sku_id: string;
asset: string;
expires_at: number;
}
export interface Activity { export interface Activity {
type: number; type: number;
state: string; state: string;

View File

@@ -11,6 +11,7 @@ type Parameters = {
bg?: string; bg?: string;
clanbg?: string; clanbg?: string;
animated?: string; animated?: string;
animatedDecoration?: string;
hideDiscrim?: string; hideDiscrim?: string;
hideStatus?: string; hideStatus?: string;
hideTimestamp?: string; hideTimestamp?: string;
@@ -19,6 +20,7 @@ type Parameters = {
hideActivity?: string; hideActivity?: string;
hideSpotify?: string; hideSpotify?: string;
hideClan?: string; hideClan?: string;
hideDecoration?: string;
ignoreAppId?: string; ignoreAppId?: string;
showDisplayName?: string; showDisplayName?: string;
borderRadius?: string; borderRadius?: string;
@@ -74,10 +76,12 @@ const renderCard = async (body: LanyardTypes.Root, params: Parameters): Promise<
let hideActivity = params.hideActivity ?? "false"; let hideActivity = params.hideActivity ?? "false";
let hideSpotify = parseBool(params.hideSpotify); let hideSpotify = parseBool(params.hideSpotify);
let hideClan = parseBool(params.hideClan); let hideClan = parseBool(params.hideClan);
let hideDecoration = parseBool(params.hideDecoration);
let ignoreAppId = parseAppId(params.ignoreAppId); let ignoreAppId = parseAppId(params.ignoreAppId);
let hideDiscrim = parseBool(params.hideDiscrim); let hideDiscrim = parseBool(params.hideDiscrim);
let showDisplayName = parseBool(params.showDisplayName); let showDisplayName = parseBool(params.showDisplayName);
if (!data.discord_user.avatar_decoration_data) hideDecoration = true;
if (parseBool(params.hideDiscrim) || body.data.discord_user.discriminator === "0") hideDiscrim = true; if (parseBool(params.hideDiscrim) || body.data.discord_user.discriminator === "0") hideDiscrim = true;
if (!body.data.discord_user.clan) hideClan = true; if (!body.data.discord_user.clan) hideClan = true;
if (data.activities[0]?.emoji?.animated) statusExtension = "gif"; if (data.activities[0]?.emoji?.animated) statusExtension = "gif";
@@ -115,6 +119,13 @@ const renderCard = async (body: LanyardTypes.Root, params: Parameters): Promise<
); );
} }
let avatarDecoration: string;
if (data.discord_user.avatar_decoration_data) {
avatarDecoration = await encodeBase64(
`https://cdn.discordapp.com/avatar-decoration-presets/${data.discord_user.avatar_decoration_data.asset}.png?size=64&passthrough=${params.animatedDecoration || "true"}`
);
}
switch (data.discord_status) { switch (data.discord_status) {
case "online": case "online":
avatarBorderColor = "#43B581"; avatarBorderColor = "#43B581";
@@ -165,6 +176,19 @@ const renderCard = async (body: LanyardTypes.Root, params: Parameters): Promise<
return ` return `
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xhtml="http://www.w3.org/1999/xhtml" width="410px" height="${svgHeight()}px"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xhtml="http://www.w3.org/1999/xhtml" width="410px" height="${svgHeight()}px">
<defs>
<style>
.hover-opacity:hover {
opacity: 0.25;
}
.transition {
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 200ms;
}
</style>
</defs>
<foreignObject x="0" y="0" width="410" height="${svgHeight()}"> <foreignObject x="0" y="0" width="410" height="${svgHeight()}">
<div xmlns="http://www.w3.org/1999/xhtml" style=" <div xmlns="http://www.w3.org/1999/xhtml" style="
position: absolute; position: absolute;
@@ -200,13 +224,13 @@ const renderCard = async (body: LanyardTypes.Root, params: Parameters): Promise<
"> ">
<div style=" <div style="
display: flex; display: flex;
position: relative;
flex-direction: row; flex-direction: row;
height: 80px; height: 80px;
width: 80px; width: 80px;
"> ">
<img src="data:image/png;base64,${avatar}" <img src="data:image/png;base64,${avatar}"
style=" style="
border: solid 3px ${avatarBorderColor};
border-radius: 50%; border-radius: 50%;
width: 50px; width: 50px;
height: 50px; height: 50px;
@@ -215,6 +239,29 @@ const renderCard = async (body: LanyardTypes.Root, params: Parameters): Promise<
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
"/> "/>
${hideDecoration || !data.discord_user.avatar_decoration_data ? "" : `
<img src="data:image/png;base64,${avatarDecoration!}"
class="hover-opacity transition"
style="
display: block;
width: 64px;
height: 64px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
"/>
`}
<span style="
position: absolute;
bottom: 14px;
right: 14px;
height: 13px;
width: 13px;
background-color: ${avatarBorderColor};
border-radius: 50%;
border: 3px solid #${backgroundColor};
" />
</div> </div>
<div style=" <div style="
height: 80px; height: 80px;