convert hashes to big ints + bools

This commit is contained in:
Skillz4Killz
2021-05-07 12:57:36 +00:00
committed by GitHub
parent d645b99287
commit a32f5b5ece
7 changed files with 173 additions and 29 deletions
+19 -5
View File
@@ -1,16 +1,30 @@
import type { DiscordImageFormat } from "../../types/misc/image_format.ts";
import type { DiscordImageSize } from "../../types/misc/image_size.ts";
import { endpoints } from "../../util/constants.ts";
import { iconBigintToHash } from "../../util/hash.ts";
import { formatImageURL } from "../../util/utils.ts";
/** The full URL of the banner from Discords CDN. Undefined if no banner is set. */
export function guildBannerURL(
id: bigint,
banner?: string,
size: DiscordImageSize = 128,
format?: DiscordImageFormat,
options: {
banner?: string | bigint;
size?: DiscordImageSize;
format?: DiscordImageFormat;
animated?: boolean;
},
) {
return banner
? formatImageURL(endpoints.GUILD_BANNER(id, banner), size, format)
return options.banner
? formatImageURL(
endpoints.GUILD_BANNER(
id,
typeof options.banner === "string" ? options.banner : iconBigintToHash(
options.banner,
options.animated ?? true,
),
),
options.size || 128,
options.format,
)
: undefined;
}
+19 -5
View File
@@ -1,16 +1,30 @@
import type { DiscordImageFormat } from "../../types/misc/image_format.ts";
import type { DiscordImageSize } from "../../types/misc/image_size.ts";
import { endpoints } from "../../util/constants.ts";
import { iconBigintToHash } from "../../util/hash.ts";
import { formatImageURL } from "../../util/utils.ts";
/** The full URL of the icon from Discords CDN. Undefined when no icon is set. */
export function guildIconURL(
id: bigint,
icon?: string,
size: DiscordImageSize = 128,
format?: DiscordImageFormat,
options: {
icon?: string | bigint;
size?: DiscordImageSize;
format?: DiscordImageFormat;
animated?: boolean;
},
) {
return icon
? formatImageURL(endpoints.GUILD_ICON(id, icon), size, format)
return options.icon
? formatImageURL(
endpoints.GUILD_ICON(
id,
typeof options.icon === "string" ? options.icon : iconBigintToHash(
options.icon,
options.animated ?? true,
),
),
options.size || 128,
options.format,
)
: undefined;
}
+17 -7
View File
@@ -1,20 +1,30 @@
import type { DiscordImageFormat } from "../../types/misc/image_format.ts";
import type { DiscordImageSize } from "../../types/misc/image_size.ts";
import { endpoints } from "../../util/constants.ts";
import { iconBigintToHash } from "../../util/hash.ts";
import { formatImageURL } from "../../util/utils.ts";
/** The full URL of the splash from Discords CDN. Undefined if no splash is set. */
export function guildSplashURL(
id: bigint,
splash?: string,
size: DiscordImageSize = 128,
format?: DiscordImageFormat,
options: {
splash?: string | bigint;
size?: DiscordImageSize;
format?: DiscordImageFormat;
animated?: boolean;
},
) {
return splash
return options.splash
? formatImageURL(
endpoints.GUILD_SPLASH(id, splash),
size,
format,
endpoints.GUILD_SPLASH(
id,
typeof options.splash === "string" ? options.splash : iconBigintToHash(
options.splash,
options.animated ?? true,
),
),
options.size || 128,
options.format,
)
: undefined;
}
+19 -5
View File
@@ -1,17 +1,31 @@
import type { DiscordImageFormat } from "../../types/misc/image_format.ts";
import type { DiscordImageSize } from "../../types/misc/image_size.ts";
import { endpoints } from "../../util/constants.ts";
import { iconBigintToHash } from "../../util/hash.ts";
import { formatImageURL } from "../../util/utils.ts";
/** The users custom avatar or the default avatar if you don't have a member object. */
export function avatarURL(
userId: bigint,
discriminator: bigint,
avatar?: string | null,
size: DiscordImageSize = 128,
format?: DiscordImageFormat,
options: {
avatar?: string | bigint;
size?: DiscordImageSize;
format?: DiscordImageFormat;
animated?: boolean;
},
) {
return avatar
? formatImageURL(endpoints.USER_AVATAR(userId, avatar), size, format)
return options.avatar
? formatImageURL(
endpoints.USER_AVATAR(
userId,
typeof options.avatar === "string" ? options.avatar : iconBigintToHash(
options.avatar,
options.animated ?? true,
),
),
options.size || 128,
options.format,
)
: endpoints.USER_DEFAULT_AVATAR(Number(discriminator) % 5);
}
+57 -3
View File
@@ -28,6 +28,7 @@ import type { DiscordImageSize } from "../types/misc/image_size.ts";
import { snowflakeToBigint } from "../util/bigint.ts";
import { cacheMembers } from "../util/cache_members.ts";
import { Collection } from "../util/collection.ts";
import { iconHashToBigInt } from "../util/hash.ts";
import { createNewProp } from "../util/utils.ts";
import { DiscordenoChannel } from "./channel.ts";
import { DiscordenoMember } from "./member.ts";
@@ -58,6 +59,12 @@ export const guildToggles = {
unavailable: 8n,
/** Whether this server is an nsfw guild */
nsfw: 16n,
/** Whether this server's icon is animated */
animatedIcon: 32n,
/** Whether this server's banner is animated. */
animatedBanner: 64n,
/** Whether this server's splash is animated. */
animatedSplash: 128n,
};
const baseGuild: Partial<DiscordenoGuild> = {
@@ -98,10 +105,20 @@ const baseGuild: Partial<DiscordenoGuild> = {
return Boolean(this.features?.includes(DiscordGuildFeatures.Verified));
},
bannerURL(size, format) {
return guildBannerURL(this.id!, this.banner!, size, format);
return guildBannerURL(this.id!, {
banner: this.banner!,
size,
format,
animated: this.animatedBanner!,
});
},
splashURL(size, format) {
return guildSplashURL(this.id!, this.splash!, size, format);
return guildSplashURL(this.id!, {
splash: this.splash!,
size,
format,
animated: this.animatedSplash,
});
},
delete() {
return deleteGuild(this.id!);
@@ -128,7 +145,12 @@ const baseGuild: Partial<DiscordenoGuild> = {
return getInvites(this.id!);
},
iconURL(size, format) {
return guildIconURL(this.id!, this.icon!, size, format);
return guildIconURL(this.id!, {
icon: this.icon!,
size,
format,
animated: this.animatedIcon!,
});
},
leave() {
return leaveGuild(this.id!);
@@ -148,6 +170,15 @@ const baseGuild: Partial<DiscordenoGuild> = {
get nsfw() {
return Boolean(this.bitfield! & guildToggles.nsfw);
},
get animatedIcon() {
return Boolean(this.bitfield! & guildToggles.animatedIcon);
},
get animatedBanner() {
return Boolean(this.bitfield! & guildToggles.animatedBanner);
},
get animatedSplash() {
return Boolean(this.bitfield! & guildToggles.animatedSplash);
},
};
export async function createDiscordenoGuild(
@@ -163,6 +194,9 @@ export async function createDiscordenoGuild(
joinedAt = "",
emojis,
members = [],
icon,
splash,
banner,
...rest
} = data;
@@ -215,6 +249,20 @@ export async function createDiscordenoGuild(
);
}
const hashes = [
{ name: "icon", toggle: guildToggles.animatedIcon, value: icon },
{ name: "banner", toggle: guildToggles.animatedBanner, value: banner },
{ name: "splash", toggle: guildToggles.animatedSplash, value: splash },
];
for (const hash of hashes) {
const transformed = hash.value ? iconHashToBigInt(hash.value) : undefined;
if (transformed) {
props.icon = createNewProp(hash.value);
if (transformed.animated) bitfield |= hash.toggle;
}
}
const guild: DiscordenoGuild = Object.create(baseGuild, {
...props,
shardId: createNewProp(shardId),
@@ -285,6 +333,12 @@ export interface DiscordenoGuild extends
rulesChannelId?: bigint;
/** The id of the channel where admins and moderators of Community guilds receive notices from Discord */
publicUpdatesChannelId?: bigint;
/** Whether this server's icon is animated */
animatedIcon: boolean;
/** Whether this server's banner is animated. */
animatedBanner: boolean;
/** Whether this server's splash is animated. */
animatedSplash: boolean;
/** The id of the shard this guild is bound to */
shardId: number;
/** Total number of members in this guild */
+24 -4
View File
@@ -19,6 +19,7 @@ import type { DiscordImageSize } from "../types/misc/image_size.ts";
import type { User } from "../types/users/user.ts";
import { snowflakeToBigint } from "../util/bigint.ts";
import { Collection } from "../util/collection.ts";
import { iconHashToBigInt } from "../util/hash.ts";
import { createNewProp } from "../util/utils.ts";
import { DiscordenoGuild } from "./guild.ts";
@@ -36,11 +37,16 @@ export const memberToggles = {
mfaEnabled: 4n,
/** Whether the email on this account has been verified */
verified: 8n,
/** Whether the users avatar is animated. */
animatedAvatar: 16n,
};
const baseMember: Partial<DiscordenoMember> = {
get avatarURL() {
return avatarURL(this.id!, this.discriminator!, this.avatar!);
return avatarURL(this.id!, this.discriminator!, {
avatar: this.avatar!,
animated: this.animatedAvatar,
});
},
get mention() {
return `<@!${this.id!}>`;
@@ -54,9 +60,12 @@ const baseMember: Partial<DiscordenoMember> = {
return avatarURL(
this.id!,
this.discriminator!,
this.avatar!,
options.size,
options.format,
{
avatar: this.avatar!,
size: options.size,
format: options.format,
animated: this.animatedAvatar!,
},
);
},
guild(guildId) {
@@ -98,6 +107,9 @@ const baseMember: Partial<DiscordenoMember> = {
get verified() {
return Boolean(this.bitfield! & memberToggles.verified);
},
get animatedAvatar() {
return Boolean(this.bitfield! & memberToggles.animatedAvatar);
},
};
export async function createDiscordenoMember(
@@ -126,6 +138,12 @@ export async function createDiscordenoMember(
continue;
}
if (key === "icon") {
const transformed = value ? iconHashToBigInt(value) : undefined;
if (transformed?.animated) bitfield |= memberToggles.animatedAvatar;
props.icon = createNewProp(transformed?.bigint);
}
props[key] = createNewProp(
MEMBER_SNOWFLAKES.includes(key)
? value ? snowflakeToBigint(value) : undefined
@@ -193,6 +211,8 @@ export interface DiscordenoMember extends
mention: string;
/** The username#discriminator tag for this member */
tag: string;
/** Whether or not the avatar is animated. */
animatedAvatar: boolean;
// METHODS
+18
View File
@@ -0,0 +1,18 @@
export function iconHashToBigInt(hash: string) {
let animated = false;
if (hash.startsWith("a_")) {
animated = true;
hash = hash.substring(2);
}
return {
animated,
bigint: BigInt(`0x${hash}`),
};
}
export function iconBigintToHash(icon: bigint, animated = true) {
const hash = icon.toString(16);
return `${animated ? "a_" : ""}${hash}`;
}