summary refs log tree commit diff
path: root/util/src/entities/Member.ts
diff options
context:
space:
mode:
Diffstat (limited to 'util/src/entities/Member.ts')
-rw-r--r--util/src/entities/Member.ts360
1 files changed, 0 insertions, 360 deletions
diff --git a/util/src/entities/Member.ts b/util/src/entities/Member.ts
deleted file mode 100644

index baac58ed..00000000 --- a/util/src/entities/Member.ts +++ /dev/null
@@ -1,360 +0,0 @@ -import { PublicUser, User } from "./User"; -import { BaseClass } from "./BaseClass"; -import { - Column, - Entity, - Index, - JoinColumn, - JoinTable, - ManyToMany, - ManyToOne, - PrimaryGeneratedColumn, - RelationId, -} from "typeorm"; -import { Guild } from "./Guild"; -import { Config, emitEvent } from "../util"; -import { - GuildCreateEvent, - GuildDeleteEvent, - GuildMemberAddEvent, - GuildMemberRemoveEvent, - GuildMemberUpdateEvent, -} from "../interfaces"; -import { HTTPError } from "../util/imports/HTTPError"; -import { Role } from "./Role"; -import { BaseClassWithoutId } from "./BaseClass"; -import { Ban, PublicGuildRelations } from "."; -import { DiscordApiErrors } from "../util/Constants"; -import { OrmUtils } from "../util/imports/OrmUtils"; - -export const MemberPrivateProjection: (keyof Member)[] = [ - "id", - "guild", - "guild_id", - "deaf", - "joined_at", - "last_message_id", - "mute", - "nick", - "pending", - "premium_since", - "roles", - "settings", - "user", -]; - -@Entity("members") -@Index(["id", "guild_id"], { unique: true }) -export class Member extends BaseClassWithoutId { - @PrimaryGeneratedColumn() - index: string; - - @Column() - @RelationId((member: Member) => member.user) - id: string; - - @JoinColumn({ name: "id" }) - @ManyToOne(() => User, { - onDelete: "CASCADE", - }) - user: User; - - @Column() - @RelationId((member: Member) => member.guild) - guild_id: string; - - @JoinColumn({ name: "guild_id" }) - @ManyToOne(() => Guild, { - onDelete: "CASCADE", - }) - guild: Guild; - - @Column({ nullable: true }) - nick?: string; - - @JoinTable({ - name: "member_roles", - joinColumn: { name: "index", referencedColumnName: "index" }, - inverseJoinColumn: { - name: "role_id", - referencedColumnName: "id", - }, - }) - @ManyToMany(() => Role, { cascade: true }) - roles: Role[]; - - @Column() - joined_at: Date; - - @Column({ nullable: true }) - premium_since?: Date; - - @Column() - deaf: boolean; - - @Column() - mute: boolean; - - @Column() - pending: boolean; - - @Column({ type: "simple-json", select: false }) - settings: UserGuildSettings; - - @Column({ nullable: true }) - last_message_id?: string; - - /** - @JoinColumn({ name: "id" }) - @ManyToOne(() => User, { - onDelete: "DO NOTHING", - // do not auto-kick force-joined members just because their joiners left the server - }) **/ - @Column({ nullable: true }) - joined_by?: string; - - // TODO: add this when we have proper read receipts - // @Column({ type: "simple-json" }) - // read_state: ReadState; - - static async IsInGuildOrFail(user_id: string, guild_id: string) { - if (await Member.count({ where: { id: user_id, guild: { 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", "member_count"], 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 - //TODO: check for bugs - if (guild.member_count) guild.member_count--; - return Promise.all([ - Member.delete({ - id: user_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, user: member.user }, - guild_id, - } as GuildMemberRemoveEvent), - ]); - } - - static async addRole(user_id: string, guild_id: string, role_id: string) { - const [member, role] = await Promise.all([ - // @ts-ignore - Member.findOneOrFail({ - where: { id: user_id, guild_id }, - relations: ["user", "roles"], // we don't want to load the role objects just the ids - select: ["index"], - }), - Role.findOneOrFail({ where: { id: role_id, guild_id }, select: ["id"] }), - ]); - member.roles.push(OrmUtils.mergeDeep(new Role(), { id: role_id })); - - await Promise.all([ - member.save(), - emitEvent({ - event: "GUILD_MEMBER_UPDATE", - data: { - guild_id, - user: member.user, - roles: member.roles.map((x) => x.id), - }, - guild_id, - } as GuildMemberUpdateEvent), - ]); - } - - static async removeRole(user_id: string, guild_id: string, role_id: string) { - const [member] = await Promise.all([ - // @ts-ignore - Member.findOneOrFail({ - where: { id: user_id, guild_id }, - relations: ["user", "roles"], // we don't want to load the role objects just the ids - select: ["index"], - }), - await Role.findOneOrFail({ where: { id: role_id, guild_id } }), - ]); - member.roles = member.roles.filter((x) => x.id == role_id); - - await Promise.all([ - member.save(), - emitEvent({ - event: "GUILD_MEMBER_UPDATE", - data: { - guild_id, - user: member.user, - roles: member.roles.map((x) => x.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, - }, - relations: ["user"], - }); - member.nick = nickname; - - await Promise.all([ - member.save(), - - emitEvent({ - event: "GUILD_MEMBER_UPDATE", - data: { - guild_id, - user: member.user, - nick: nickname, - }, - guild_id, - } as GuildMemberUpdateEvent), - ]); - } - - static async addToGuild(user_id: string, guild_id: string) { - const user = await User.getPublicUser(user_id); - const isBanned = await Ban.count({ where: { guild_id, user_id } }); - if (isBanned) { - throw DiscordApiErrors.USER_BANNED; - } - const { maxGuilds } = Config.get().limits.user; - const guild_count = await Member.count({ where: { id: user_id } }); - if (guild_count >= maxGuilds) { - throw new HTTPError(`You are at the ${maxGuilds} server limit.`, 403); - } - - const guild = await Guild.findOneOrFail({ - where: { - id: guild_id, - }, - relations: PublicGuildRelations, - }); - - if (await Member.count({ where: { id: user.id, guild: { id: guild_id } } })) - throw new HTTPError("You are already a member of this guild", 400); - - const member = { - id: user_id, - guild_id, - nick: undefined, - roles: [guild_id], // @everyone role - joined_at: new Date(), - premium_since: null, - deaf: false, - mute: false, - pending: false, - }; - //TODO: check for bugs - if (guild.member_count) guild.member_count++; - await Promise.all([ - OrmUtils.mergeDeep(new Member(), { - ...member, - roles: [OrmUtils.mergeDeep(new Role(), { id: guild_id })], - // read_state: {}, - settings: { - channel_overrides: [], - message_notifications: 0, - mobile_push: true, - muted: false, - suppress_everyone: false, - suppress_roles: false, - version: 0, - }, - // Member.save is needed because else the roles relations wouldn't be updated - }).save(), - //Guild.increment({ id: guild_id }, "member_count", 1), - emitEvent({ - event: "GUILD_MEMBER_ADD", - data: { - ...member, - user, - guild_id, - }, - guild_id, - } as GuildMemberAddEvent), - emitEvent({ - event: "GUILD_CREATE", - data: { - ...guild, - members: [...guild.members, { ...member, user }], - member_count: (guild.member_count || 0) + 1, - guild_hashes: {}, - guild_scheduled_events: [], - joined_at: member.joined_at, - presences: [], - stage_instances: [], - threads: [], - }, - user_id, - } as GuildCreateEvent), - ]); - } -} - -export interface UserGuildSettings { - channel_overrides: { - channel_id: string; - message_notifications: number; - mute_config: MuteConfig; - muted: boolean; - }[]; - message_notifications: number; - mobile_push: boolean; - mute_config: MuteConfig; - muted: boolean; - suppress_everyone: boolean; - suppress_roles: boolean; - version: number; -} - -export interface MuteConfig { - end_time: number; - 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 type PublicMember = Pick<Member, Omit<PublicMemberKeys, "roles">> & { - user: PublicUser; - roles: string[]; // only role ids not objects -};