From 55a1c04774af1041fa3ff4970bf35cb06ff907d1 Mon Sep 17 00:00:00 2001 From: ITOH <72305210+itohatweb@users.noreply.github.com> Date: Tue, 6 Apr 2021 10:22:19 +0200 Subject: [PATCH] fix(structures/member): use new types & add MemberStruct interface (#739) * Update member.ts * Update member.ts * Update member.ts * better type * cast * this better * add comment --- src/structures/member.ts | 116 ++++++++++++++++++++++++++++++--------- 1 file changed, 89 insertions(+), 27 deletions(-) diff --git a/src/structures/member.ts b/src/structures/member.ts index bb893164d..9bf687d06 100644 --- a/src/structures/member.ts +++ b/src/structures/member.ts @@ -6,10 +6,21 @@ import { kickMember } from "../helpers/members/kick_member.ts"; import { sendDirectMessage } from "../helpers/members/send_direct_message.ts"; import { addRole } from "../helpers/roles/add_role.ts"; import { removeRole } from "../helpers/roles/remove_role.ts"; +import { CreateMessage } from "../types/channels/create_message.ts"; +import { CreateGuildBan } from "../types/guilds/create_guild_ban.ts"; +import { + DiscordGuildMember, + GuildMember, +} from "../types/guilds/guild_member.ts"; +import { ModifyGuildMember } from "../types/guilds/modify_guild_member.ts"; +import { DiscordImageFormat } from "../types/misc/image_format.ts"; +import { DiscordImageSize } from "../types/misc/image_size.ts"; +import { DiscordUser, User } from "../types/users/user.ts"; import { Collection } from "../util/collection.ts"; -import { createNewProp } from "../util/utils.ts"; +import { createNewProp, snakeKeysToCamelCase } from "../util/utils.ts"; +import { GuildStruct } from "./guild.ts"; -const baseMember: Partial = { +const baseMember: Partial = { get avatarURL() { return avatarURL(this.id!, this.discriminator!, this.avatar!); }, @@ -22,7 +33,7 @@ const baseMember: Partial = { // METHODS makeAvatarURL(options) { - return rawAvatarURL( + return avatarURL( this.id!, this.discriminator!, this.avatar!, @@ -60,39 +71,33 @@ const baseMember: Partial = { }; export async function createMemberStruct( - data: MemberCreatePayload, + // The `user` param in `DiscordGuildMember` is optional since discord does not send it in `MESSAGE_CREATE` and `MESSAGE_UPDATE` events. But this data in there is required to build this structure so it is required in this case + data: Omit & { user: DiscordUser }, guildId: string, ) { const { - joined_at: joinedAt, - premium_since: premiumSince, - user: userData, - roles, - deaf, - mute, - nick, + user, + joinedAt, + premiumSince, ...rest - } = data; + } = snakeKeysToCamelCase(data) as Omit & { + user: DiscordUser; + }; - const { mfa_enabled: mfaEnabled, premium_type: premiumType, ...user } = - data.user || {}; - - const restProps: Record> = {}; + const props: Record> = {}; for (const key of Object.keys(rest)) { // @ts-ignore index signature - restProps[key] = createNewProp(rest[key]); + props[key] = createNewProp(rest[key]); } for (const key of Object.keys(user)) { // @ts-ignore index signature - restProps[key] = createNewProp(user[key]); + props[key] = createNewProp(user[key]); } - const member = Object.create(baseMember, { - ...restProps, - mfaEnabled: createNewProp(mfaEnabled), - premiumType: createNewProp(premiumType), + const member: MemberStruct = Object.create(baseMember, { + ...props, /** The guild related data mapped by guild id */ guilds: createNewProp(new Collection()), }); @@ -106,13 +111,70 @@ export async function createMemberStruct( // User was never cached before member.guilds.set(guildId, { - nick: nick, - roles: roles, + nick: rest.nick, + roles: rest.roles, joinedAt: Date.parse(joinedAt), premiumSince: premiumSince ? Date.parse(premiumSince) : undefined, - deaf: deaf, - mute: mute, + deaf: rest.deaf, + mute: rest.mute, }); - return member as Member; + return member; +} + +export interface MemberStruct extends GuildMember, User { + /** The guild related data mapped by guild id */ + guilds: Collection< + string, + Omit & { + joinedAt: number; + premiumSince?: number; + } + >; + + // GETTERS + /** The avatar url using the default format and size. */ + avatarURL: string; + /** The mention string for this member */ + mention: string; + /** The username#discriminator tag for this member */ + tag: string; + + // METHODS + + /** Returns the avatar url for this member and can be dynamically modified with a size or format */ + makeAvatarURL( + options: { size?: DiscordImageSize; format?: DiscordImageFormat }, + ): string; + /** Returns the guild for this guildID */ + guild(guildID: string): GuildStruct | undefined; + /** Get the nickname or the username if no nickname */ + name(guildID: string): string; + /** Get the guild member object for the specified guild */ + guildMember(guildID: string): GuildMember | undefined; + /** Send a direct message to the user is possible */ + sendDM( + content: string | CreateMessage, + ): ReturnType; + /** Kick the member from a guild */ + kick(guildID: string, reason?: string): ReturnType; + /** Edit the member in a guild */ + edit( + guildID: string, + options: ModifyGuildMember, + ): ReturnType; + /** Ban a member in a guild */ + ban(guildID: string, options: CreateGuildBan): ReturnType; + /** Add a role to the member */ + addRole( + guildID: string, + roleID: string, + reason?: string, + ): ReturnType; + /** Remove a role from the member */ + removeRole( + guildID: string, + roleID: string, + reason?: string, + ): ReturnType; }