Rewrite website as a Hyprland desktop
This commit is contained in:
1 parent
7c52779cf6
commit
3065ad6092
197 files changed
+5609
-17779
No files matched your search
@@ -1,149 +0,0 @@
|
||||
export enum ImageSize {
|
||||
USER_AVATAR = 32,
|
||||
USER_DECORATION = 64,
|
||||
SERVER_TAG = 32,
|
||||
ACTIVITY_LARGE = 128,
|
||||
ACTIVITY_SMALL = 64,
|
||||
EMOJI = 32,
|
||||
}
|
||||
|
||||
export type Activity = {
|
||||
name?: string;
|
||||
type?: number;
|
||||
details?: string | null;
|
||||
url?: string | null;
|
||||
application_id?: string | null;
|
||||
assets?: { large_image?: string | null; small_image?: string | null };
|
||||
emoji?: { id?: string; animated?: boolean } | null;
|
||||
app_icon?: string | null;
|
||||
};
|
||||
|
||||
export type Data = {
|
||||
discord_user: {
|
||||
id: string;
|
||||
avatar?: string | null;
|
||||
discriminator?: string | null;
|
||||
primary_guild?: { identity_guild_id?: string; badge?: string } | null;
|
||||
avatar_decoration_data?: { asset?: string } | null;
|
||||
};
|
||||
activities: Activity[];
|
||||
spotify?: { album_art_url?: string } | null;
|
||||
};
|
||||
|
||||
export type ProfileSettings = {
|
||||
optimized?: boolean;
|
||||
animatedDecoration?: string | boolean;
|
||||
ignoreAppId?: string[];
|
||||
theme?: string | null;
|
||||
};
|
||||
|
||||
async function encodeBase64(url: string, _size?: ImageSize, _theme?: string | null) {
|
||||
try {
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) return url;
|
||||
const buf = await res.arrayBuffer();
|
||||
const bytes = new Uint8Array(buf);
|
||||
let binary = "";
|
||||
const chunk = 0x8000;
|
||||
for (let i = 0; i < bytes.length; i += chunk) {
|
||||
binary += String.fromCharCode.apply(null, Array.from(bytes.subarray(i, i + chunk)) as unknown as number[]);
|
||||
}
|
||||
const b64 = typeof globalThis.btoa === "function" ? globalThis.btoa(binary) : Buffer.from(binary, "binary").toString("base64");
|
||||
// try to infer mime
|
||||
const ext = url.split("?")[0].split(".").pop()?.toLowerCase() ?? "png";
|
||||
const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : ext === "gif" ? "image/gif" : ext === "webp" ? "image/webp" : "image/png";
|
||||
return `data:${mime};base64,${b64}`;
|
||||
} catch (err) {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchUserImages(data: Data, settings: ProfileSettings) {
|
||||
let avatar: string;
|
||||
let avatarDecoration: string | null = null;
|
||||
let clanBadge: string | null = null;
|
||||
let assetLargeImage: string | null = null;
|
||||
let assetSmallImage: string | null = null;
|
||||
let userEmoji: string | null = null;
|
||||
let albumCover: string | null = null;
|
||||
|
||||
const avatarExtension =
|
||||
data.discord_user.avatar && data.discord_user.avatar.startsWith("a_") && !settings.optimized
|
||||
? "gif"
|
||||
: "webp";
|
||||
|
||||
const statusExtension: string = data.activities[0]?.emoji?.animated && !settings.optimized ? "gif" : "webp";
|
||||
|
||||
const userStatus: Activity | undefined = data.activities[0] && data.activities[0].type === 4 ? data.activities[0] : undefined;
|
||||
|
||||
const activities = data.activities
|
||||
.filter((activity) => activity.type === 0)
|
||||
.filter((activity) => !settings.ignoreAppId?.includes(activity.application_id ?? ""));
|
||||
const activity: Activity | undefined = activities.length > 0 ? activities[0] : undefined;
|
||||
|
||||
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"}`,
|
||||
ImageSize.USER_AVATAR
|
||||
);
|
||||
} 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 ?? "0") % 5}.png?size=128`,
|
||||
ImageSize.USER_AVATAR
|
||||
);
|
||||
}
|
||||
|
||||
if (data.discord_user.primary_guild && data.discord_user.primary_guild.identity_guild_id && data.discord_user.primary_guild.badge) {
|
||||
clanBadge = await encodeBase64(
|
||||
`https://cdn.discordapp.com/clan-badges/${data.discord_user.primary_guild.identity_guild_id}/${data.discord_user.primary_guild.badge}.png?size=32`,
|
||||
ImageSize.SERVER_TAG
|
||||
);
|
||||
}
|
||||
|
||||
if (data.discord_user.avatar_decoration_data?.asset) {
|
||||
avatarDecoration = await encodeBase64(
|
||||
`https://cdn.discordapp.com/avatar-decoration-presets/${data.discord_user.avatar_decoration_data.asset}.png?size=64&passthrough=${settings.animatedDecoration || "false"}`,
|
||||
ImageSize.USER_DECORATION
|
||||
);
|
||||
}
|
||||
|
||||
if (activity?.assets?.large_image)
|
||||
assetLargeImage = await encodeBase64(
|
||||
activity.assets?.large_image!.startsWith("mp:external/")
|
||||
? `https://media.discordapp.net/${activity.assets!.large_image!.replace("mp:", "")}`
|
||||
: `https://cdn.discordapp.com/app-assets/${activity.application_id}/${activity.assets!.large_image}.webp`,
|
||||
ImageSize.ACTIVITY_LARGE,
|
||||
settings.theme || null
|
||||
);
|
||||
else if (activity?.app_icon)
|
||||
assetLargeImage = await encodeBase64(activity.app_icon, ImageSize.ACTIVITY_LARGE);
|
||||
|
||||
if (activity?.assets?.small_image)
|
||||
assetSmallImage = await encodeBase64(
|
||||
activity.assets.small_image!.startsWith("mp:external/")
|
||||
? `https://media.discordapp.net/${activity.assets.small_image!.replace("mp:", "")}`
|
||||
: `https://cdn.discordapp.com/app-assets/${activity.application_id}/${activity.assets.small_image}.webp`,
|
||||
ImageSize.ACTIVITY_SMALL,
|
||||
settings.theme || null
|
||||
);
|
||||
|
||||
if (userStatus?.emoji?.id)
|
||||
userEmoji = await encodeBase64(
|
||||
`https://cdn.discordapp.com/emojis/${userStatus.emoji.id}.${statusExtension}?size=32`,
|
||||
ImageSize.EMOJI
|
||||
);
|
||||
|
||||
if (data.spotify?.album_art_url) albumCover = await encodeBase64(data.spotify.album_art_url, ImageSize.ACTIVITY_LARGE);
|
||||
|
||||
return {
|
||||
avatar,
|
||||
clanBadge,
|
||||
avatarDecoration,
|
||||
assetLargeImage,
|
||||
assetSmallImage,
|
||||
userEmoji,
|
||||
albumCover,
|
||||
};
|
||||
}
|
||||
|
||||
export default fetchUserImages;
|
||||
@@ -0,0 +1,35 @@
|
||||
export type DiscordStatus = 'online' | 'idle' | 'dnd' | 'offline';
|
||||
|
||||
export interface DiscordActivity {
|
||||
name: string;
|
||||
type: number;
|
||||
details: string | null;
|
||||
largeImage: string | null;
|
||||
smallImage: string | null;
|
||||
}
|
||||
|
||||
export interface DiscordPresence {
|
||||
status: DiscordStatus;
|
||||
displayName: string | null;
|
||||
avatarUrl: string | null;
|
||||
guildTag: string | null;
|
||||
guildTagBadgeUrl: string | null;
|
||||
activities: DiscordActivity[];
|
||||
}
|
||||
|
||||
export const offlinePresence: DiscordPresence = {
|
||||
status: 'offline',
|
||||
displayName: null,
|
||||
avatarUrl: null,
|
||||
guildTag: null,
|
||||
guildTagBadgeUrl: null,
|
||||
activities: []
|
||||
};
|
||||
|
||||
export const activityLabels: Record<number, string> = {
|
||||
0: 'Playing',
|
||||
1: 'Streaming',
|
||||
2: 'Listening to',
|
||||
3: 'Watching',
|
||||
5: 'Competing in'
|
||||
};
|
||||
Reference in new issue
Block a user