diff options
author | Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> | 2021-08-29 00:03:58 +0200 |
---|---|---|
committer | Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> | 2021-08-29 00:03:58 +0200 |
commit | 227a4e47f1ec9bca9b039c7c6761a335bcf622c2 (patch) | |
tree | 356056aa999e2b7b2d8b2e5094c98e63fa1bd2d2 /util/src/entities/Member.ts | |
parent | :sparkles: typeorm api rewrite done (diff) | |
download | server-227a4e47f1ec9bca9b039c7c6761a335bcf622c2.tar.xz |
:sparkles: update util
Diffstat (limited to 'util/src/entities/Member.ts')
-rw-r--r-- | util/src/entities/Member.ts | 234 |
1 files changed, 214 insertions, 20 deletions
diff --git a/util/src/entities/Member.ts b/util/src/entities/Member.ts index 01634d9e..5b588d70 100644 --- a/util/src/entities/Member.ts +++ b/util/src/entities/Member.ts @@ -1,7 +1,17 @@ import { PublicUser, User } from "./User"; import { BaseClass } from "./BaseClass"; -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, RelationId } from "typeorm"; import { Guild } from "./Guild"; +import { Config, emitEvent } from "../util"; +import { + GuildCreateEvent, + GuildDeleteEvent, + GuildMemberAddEvent, + GuildMemberRemoveEvent, + GuildMemberUpdateEvent, +} from "../interfaces"; +import { HTTPError } from "lambert-server"; +import { Role } from "./Role"; @Entity("members") export class Member extends BaseClass { @@ -19,16 +29,20 @@ export class Member extends BaseClass { @ManyToOne(() => Guild, (guild: Guild) => guild.id) guild: Guild; - @Column() + @Column({ nullable: true }) nick?: string; - @Column("simple-array") - roles: string[]; + @RelationId((member: Member) => member.roles) + role_ids: string[]; + + @JoinColumn({ name: "role_ids" }) + @ManyToMany(() => Role) + roles: Role[]; @Column() joined_at: Date; - @Column() + @Column({ nullable: true }) premium_since?: number; @Column() @@ -40,12 +54,180 @@ export class Member extends BaseClass { @Column() pending: boolean; - @Column("simple-json") + @Column({ type: "simple-json" }) settings: UserGuildSettings; // TODO: update - @Column("simple-json") + @Column({ type: "simple-json" }) read_state: Record<string, string | null>; + + static async IsInGuildOrFail(user_id: string, guild_id: string) { + if (await Member.count({ id: user_id, guild_id })) return true; + throw new HTTPError("You are not member of this guild", 403); + } + + static async removeFromGuild(user_id: string, guild_id: string) { + const guild = await Guild.findOneOrFail({ select: ["owner_id"], where: { id: guild_id } }); + if (guild.owner_id === user_id) throw new Error("The owner cannot be removed of the guild"); + const member = await Member.findOneOrFail({ where: { id: user_id, guild_id }, relations: ["user"] }); + + // use promise all to execute all promises at the same time -> save time + return Promise.all([ + Member.delete({ + id: user_id, + guild_id: guild_id, + }), + Guild.decrement({ id: guild_id }, "member_count", -1), + + emitEvent({ + event: "GUILD_DELETE", + data: { + id: guild_id, + }, + user_id: user_id, + } as GuildDeleteEvent), + emitEvent({ + event: "GUILD_MEMBER_REMOVE", + data: { + guild_id: guild_id, + user: member.user, + }, + guild_id: guild_id, + } as GuildMemberRemoveEvent), + ]); + } + + static async addRole(user_id: string, guild_id: string, role_id: string) { + const [member] = await Promise.all([ + Member.findOneOrFail({ + where: { id: user_id, guild_id: guild_id }, + relations: ["user"], // we don't want to load the role objects just the ids + }), + await Role.findOneOrFail({ id: role_id, guild_id: guild_id }), + ]); + member.role_ids.push(role_id); + member.save(); + + await emitEvent({ + event: "GUILD_MEMBER_UPDATE", + data: { + guild_id: guild_id, + user: member.user, + roles: member.role_ids, + }, + guild_id: guild_id, + } as GuildMemberUpdateEvent); + } + + static async removeRole(user_id: string, guild_id: string, role_id: string) { + const [member] = await Promise.all([ + Member.findOneOrFail({ + where: { id: user_id, guild_id: guild_id }, + relations: ["user"], // we don't want to load the role objects just the ids + }), + await Role.findOneOrFail({ id: role_id, guild_id: guild_id }), + ]); + member.role_ids.remove(role_id); + member.save(); + + await emitEvent({ + event: "GUILD_MEMBER_UPDATE", + data: { + guild_id: guild_id, + user: member.user, + roles: member.role_ids, + }, + guild_id: guild_id, + } as GuildMemberUpdateEvent); + } + + static async changeNickname(user_id: string, guild_id: string, nickname: string) { + const member = await Member.findOneOrFail({ + where: { + id: user_id, + guild_id: guild_id, + }, + relations: ["user"], + }); + member.nick = nickname; + + await Promise.all([ + member.save(), + + emitEvent({ + event: "GUILD_MEMBER_UPDATE", + data: { + guild_id: guild_id, + user: member.user, + nick: nickname, + }, + guild_id: guild_id, + } as GuildMemberUpdateEvent), + ]); + } + + static async addToGuild(user_id: string, guild_id: string) { + const user = await User.getPublicUser(user_id); + + const { maxGuilds } = Config.get().limits.user; + const guild_count = await Member.count({ id: user_id }); + if (guild_count >= maxGuilds) { + throw new HTTPError(`You are at the ${maxGuilds} server limit.`, 403); + } + + const guild = await Guild.findOneOrFail(guild_id, { + relations: ["channels", "emojis", "members", "roles", "stickers"], + }); + + if (await Member.count({ id: user.id, guild_id })) + throw new HTTPError("You are already a member of this guild", 400); + + const member = { + id: user_id, + guild_id: guild_id, + nick: undefined, + roles: [guild_id], // @everyone role + joined_at: new Date(), + premium_since: undefined, + deaf: false, + mute: false, + pending: false, + }; + // @ts-ignore + guild.joined_at = member.joined_at; + + await Promise.all([ + new Member({ + ...member, + read_state: {}, + settings: { + channel_overrides: [], + message_notifications: 0, + mobile_push: true, + mute_config: null, + muted: false, + suppress_everyone: false, + suppress_roles: false, + version: 0, + }, + }).save(), + Guild.increment({ id: guild_id }, "member_count", 1), + emitEvent({ + event: "GUILD_MEMBER_ADD", + data: { + ...member, + user, + guild_id: guild_id, + }, + guild_id: guild_id, + } as GuildMemberAddEvent), + emitEvent({ + event: "GUILD_CREATE", + data: guild, + user_id, + } as GuildCreateEvent), + ]); + } } export interface UserGuildSettings { @@ -69,19 +251,31 @@ export interface MuteConfig { selected_time_window: number; } +export type PublicMemberKeys = + | "id" + | "guild_id" + | "nick" + | "roles" + | "joined_at" + | "pending" + | "deaf" + | "mute" + | "premium_since"; + +export const PublicMemberProjection: PublicMemberKeys[] = [ + "id", + "guild_id", + "nick", + "roles", + "joined_at", + "pending", + "deaf", + "mute", + "premium_since", +]; + // @ts-ignore -export interface PublicMember extends Omit<Member, "settings" | "id" | "read_state"> { +export type PublicMember = Pick<Member, Omit<PublicMemberKeys, "roles">> & { user: PublicUser; -} - -export const PublicMemberProjection = { - id: true, - guild_id: true, - nick: true, - roles: true, - joined_at: true, - pending: true, - deaf: true, - mute: true, - premium_since: true, + roles: string[]; // only role ids not objects }; |