diff options
Diffstat (limited to 'src/util/entities')
34 files changed, 716 insertions, 803 deletions
diff --git a/src/util/entities/Application.ts b/src/util/entities/Application.ts index 103f8e84..35fc496d 100644 --- a/src/util/entities/Application.ts +++ b/src/util/entities/Application.ts @@ -1,6 +1,5 @@ -import { Column, Entity, JoinColumn, ManyToOne, OneToOne, RelationId } from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, OneToOne } from "typeorm"; import { BaseClass } from "./BaseClass"; -import { Guild } from "./Guild"; import { Team } from "./Team"; import { User } from "./User"; @@ -8,77 +7,77 @@ import { User } from "./User"; export class Application extends BaseClass { @Column() name: string; - + @Column({ nullable: true }) icon?: string; - + @Column({ nullable: true }) description: string; - + @Column({ nullable: true }) summary: string = ""; - + @Column({ type: "simple-json", nullable: true }) type?: any; - + @Column() hook: boolean = true; - + @Column() bot_public?: boolean = true; - + @Column() bot_require_code_grant?: boolean = false; - + @Column() verify_key: string; - + @JoinColumn({ name: "owner_id" }) @ManyToOne(() => User) owner: User; - + @Column() flags: number = 0; - + @Column({ type: "simple-array", nullable: true }) redirect_uris: string[] = []; - + @Column({ nullable: true }) rpc_application_state: number = 0; - + @Column({ nullable: true }) store_application_state: number = 1; - + @Column({ nullable: true }) verification_state: number = 1; - + @Column({ nullable: true }) interactions_endpoint_url?: string; - + @Column({ nullable: true }) integration_public: boolean = true; - + @Column({ nullable: true }) integration_require_code_grant: boolean = false; - + @Column({ nullable: true }) discoverability_state: number = 1; - + @Column({ nullable: true }) discovery_eligibility_flags: number = 2240; - + @JoinColumn({ name: "bot_user_id" }) @OneToOne(() => User) bot?: User; - + @Column({ type: "simple-array", nullable: true }) tags?: string[]; - + @Column({ nullable: true }) cover_image?: string; // the application's default rich presence invite cover image hash - + @Column({ type: "simple-json", nullable: true }) - install_params?: {scopes: string[], permissions: string}; + install_params?: { scopes: string[]; permissions: string }; @Column({ nullable: true }) terms_of_service_url?: string; @@ -90,7 +89,7 @@ export class Application extends BaseClass { //@Column({ type: "simple-array", nullable: true }) //rpc_origins?: string[]; - + //@JoinColumn({ name: "guild_id" }) //@ManyToOne(() => Guild) //guild?: Guild; // if this application is a game sold, this field will be the guild to which it has been linked @@ -107,8 +106,7 @@ export class Application extends BaseClass { nullable: true }) team?: Team; - - } +} export interface ApplicationCommand { id: string; @@ -140,7 +138,7 @@ export enum ApplicationCommandOptionType { BOOLEAN = 5, USER = 6, CHANNEL = 7, - ROLE = 8, + ROLE = 8 } export interface ApplicationCommandInteractionData { diff --git a/src/util/entities/Attachment.ts b/src/util/entities/Attachment.ts index 7b4b17eb..8392f415 100644 --- a/src/util/entities/Attachment.ts +++ b/src/util/entities/Attachment.ts @@ -32,7 +32,7 @@ export class Attachment extends BaseClass { @JoinColumn({ name: "message_id" }) @ManyToOne(() => require("./Message").Message, (message: import("./Message").Message) => message.attachments, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) message: import("./Message").Message; diff --git a/src/util/entities/AuditLog.ts b/src/util/entities/AuditLog.ts index b003e7ba..6f394f42 100644 --- a/src/util/entities/AuditLog.ts +++ b/src/util/entities/AuditLog.ts @@ -5,24 +5,24 @@ import { User } from "./User"; export enum AuditLogEvents { // guild level - GUILD_UPDATE = 1, + GUILD_UPDATE = 1, GUILD_IMPORT = 2, GUILD_EXPORTED = 3, GUILD_ARCHIVE = 4, GUILD_UNARCHIVE = 5, // join-leave - USER_JOIN = 6, + USER_JOIN = 6, USER_LEAVE = 7, // channels - CHANNEL_CREATE = 10, + CHANNEL_CREATE = 10, CHANNEL_UPDATE = 11, CHANNEL_DELETE = 12, // permission overrides - CHANNEL_OVERWRITE_CREATE = 13, + CHANNEL_OVERWRITE_CREATE = 13, CHANNEL_OVERWRITE_UPDATE = 14, CHANNEL_OVERWRITE_DELETE = 15, // kick and ban - MEMBER_KICK = 20, + MEMBER_KICK = 20, MEMBER_PRUNE = 21, MEMBER_BAN_ADD = 22, MEMBER_BAN_REMOVE = 23, @@ -79,18 +79,18 @@ export enum AuditLogEvents { // application commands APPLICATION_COMMAND_PERMISSION_UPDATE = 121, // automod - POLICY_CREATE = 140, + POLICY_CREATE = 140, POLICY_UPDATE = 141, POLICY_DELETE = 142, - MESSAGE_BLOCKED_BY_POLICIES = 143, // in fosscord, blocked messages are stealth-dropped + MESSAGE_BLOCKED_BY_POLICIES = 143, // in fosscord, blocked messages are stealth-dropped // instance policies affecting the guild GUILD_AFFECTED_BY_POLICIES = 216, // message moves IN_GUILD_MESSAGE_MOVE = 223, CROSS_GUILD_MESSAGE_MOVE = 224, // message routing - ROUTE_CREATE = 225, - ROUTE_UPDATE = 226, + ROUTE_CREATE = 225, + ROUTE_UPDATE = 226 } @Entity("audit_logs") diff --git a/src/util/entities/BackupCodes.ts b/src/util/entities/BackupCodes.ts index 9092c14e..503b1dbd 100644 --- a/src/util/entities/BackupCodes.ts +++ b/src/util/entities/BackupCodes.ts @@ -1,4 +1,4 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne } from "typeorm"; import { BaseClass } from "./BaseClass"; import { User } from "./User"; @@ -16,4 +16,4 @@ export class BackupCode extends BaseClass { @Column() expired: boolean; -} \ No newline at end of file +} diff --git a/src/util/entities/Ban.ts b/src/util/entities/Ban.ts index 9504bd8e..27c75278 100644 --- a/src/util/entities/Ban.ts +++ b/src/util/entities/Ban.ts @@ -11,7 +11,7 @@ export class Ban extends BaseClass { @JoinColumn({ name: "user_id" }) @ManyToOne(() => User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) user: User; @@ -21,7 +21,7 @@ export class Ban extends BaseClass { @JoinColumn({ name: "guild_id" }) @ManyToOne(() => Guild, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) guild: Guild; diff --git a/src/util/entities/Categories.ts b/src/util/entities/Categories.ts index 81fbc303..08a79112 100644 --- a/src/util/entities/Categories.ts +++ b/src/util/entities/Categories.ts @@ -1,4 +1,4 @@ -import { PrimaryColumn, Column, Entity} from "typeorm"; +import { Column, Entity, PrimaryColumn } from "typeorm"; import { BaseClassWithoutId } from "./BaseClass"; // TODO: categories: @@ -16,18 +16,18 @@ import { BaseClassWithoutId } from "./BaseClass"; // Also populate discord default categories @Entity("categories") -export class Categories extends BaseClassWithoutId { // Not using snowflake - - @PrimaryColumn() - id: number; +export class Categories extends BaseClassWithoutId { + // Not using snowflake - @Column({ nullable: true }) - name: string; + @PrimaryColumn() + id: number; - @Column({ type: "simple-json" }) - localizations: string; + @Column({ nullable: true }) + name: string; - @Column({ nullable: true }) - is_primary: boolean; + @Column({ type: "simple-json" }) + localizations: string; -} \ No newline at end of file + @Column({ nullable: true }) + is_primary: boolean; +} diff --git a/src/util/entities/Channel.ts b/src/util/entities/Channel.ts index a576d7af..23fc6544 100644 --- a/src/util/entities/Channel.ts +++ b/src/util/entities/Channel.ts @@ -1,391 +1,383 @@ -import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; -import { OrmUtils } from "../util/imports/OrmUtils"; -import { BaseClass } from "./BaseClass"; -import { Guild } from "./Guild"; -import { PublicUserProjection, User } from "./User"; -import { HTTPError } from "../util/imports/HTTPError"; -import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial, InvisibleCharacters } from "../util"; -import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces"; -import { Recipient } from "./Recipient"; -import { Message } from "./Message"; -import { ReadState } from "./ReadState"; -import { Invite } from "./Invite"; -import { VoiceState } from "./VoiceState"; -import { Webhook } from "./Webhook"; -import { DmChannelDTO } from "../dtos"; - -export enum ChannelType { - GUILD_TEXT = 0, // a text channel within a guild - DM = 1, // a direct message between users - GUILD_VOICE = 2, // a voice channel within a guild - GROUP_DM = 3, // a direct message between multiple users - GUILD_CATEGORY = 4, // an organizational category that contains zero or more channels - GUILD_NEWS = 5, // a channel that users can follow and crosspost into a guild or route - GUILD_STORE = 6, // a channel in which game developers can sell their things - ENCRYPTED = 7, // end-to-end encrypted channel - ENCRYPTED_THREAD = 8, // end-to-end encrypted thread channel - TRANSACTIONAL = 9, // event chain style transactional channel - GUILD_NEWS_THREAD = 10, // a temporary sub-channel within a GUILD_NEWS channel - GUILD_PUBLIC_THREAD = 11, // a temporary sub-channel within a GUILD_TEXT channel - GUILD_PRIVATE_THREAD = 12, // a temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission - GUILD_STAGE_VOICE = 13, // a voice channel for hosting events with an audience - DIRECTORY = 14, // guild directory listing channel - GUILD_FORUM = 15, // forum composed of IM threads - TICKET_TRACKER = 33, // ticket tracker, individual ticket items shall have type 12 - KANBAN = 34, // confluence like kanban board - VOICELESS_WHITEBOARD = 35, // whiteboard but without voice (whiteboard + voice is the same as stage) - CUSTOM_START = 64, // start custom channel types from here - UNHANDLED = 255, // unhandled unowned pass-through channel type -} - -@Entity("channels") -export class Channel extends BaseClass { - @Column() - created_at: Date; - - @Column({ nullable: true }) - name?: string; - - @Column({ type: "text", nullable: true }) - icon?: string | null; - - @Column({ type: "int" }) - type: ChannelType; - - @OneToMany(() => Recipient, (recipient: Recipient) => recipient.channel, { - cascade: true, - orphanedRowAction: "delete", - }) - recipients?: Recipient[]; - - @Column({ nullable: true }) - last_message_id: string; - - @Column({ nullable: true }) - @RelationId((channel: Channel) => channel.guild) - guild_id?: string; - - @JoinColumn({ name: "guild_id" }) - @ManyToOne(() => Guild, { - onDelete: "CASCADE", - }) - guild: Guild; - - @Column({ nullable: true }) - @RelationId((channel: Channel) => channel.parent) - parent_id: string; - - @JoinColumn({ name: "parent_id" }) - @ManyToOne(() => Channel) - parent?: Channel; - - // for group DMs and owned custom channel types - @Column({ nullable: true }) - @RelationId((channel: Channel) => channel.owner) - owner_id: string; - - @JoinColumn({ name: "owner_id" }) - @ManyToOne(() => User) - owner: User; - - @Column({ nullable: true }) - last_pin_timestamp?: number; - - @Column({ nullable: true }) - default_auto_archive_duration?: number; - - @Column({ nullable: true }) - position?: number; - - @Column({ type: "simple-json", nullable: true }) - permission_overwrites?: ChannelPermissionOverwrite[]; - - @Column({ nullable: true }) - video_quality_mode?: number; - - @Column({ nullable: true }) - bitrate?: number; - - @Column({ nullable: true }) - user_limit?: number; - - @Column({ nullable: true }) - nsfw?: boolean; - - @Column({ nullable: true }) - rate_limit_per_user?: number; - - @Column({ nullable: true }) - topic?: string; - - @OneToMany(() => Invite, (invite: Invite) => invite.channel, { - cascade: true, - orphanedRowAction: "delete", - }) - invites?: Invite[]; - - @Column({ nullable: true }) - retention_policy_id?: string; - - @OneToMany(() => Message, (message: Message) => message.channel, { - cascade: true, - orphanedRowAction: "delete", - }) - messages?: Message[]; - - @OneToMany(() => VoiceState, (voice_state: VoiceState) => voice_state.channel, { - cascade: true, - orphanedRowAction: "delete", - }) - voice_states?: VoiceState[]; - - @OneToMany(() => ReadState, (read_state: ReadState) => read_state.channel, { - cascade: true, - orphanedRowAction: "delete", - }) - read_states?: ReadState[]; - - @OneToMany(() => Webhook, (webhook: Webhook) => webhook.channel, { - cascade: true, - orphanedRowAction: "delete", - }) - webhooks?: Webhook[]; - - @Column({ nullable: true }) - flags?: number = 0; - - @Column({ nullable: true }) - default_thread_rate_limit_per_user?: number = 0; - - - // TODO: DM channel - static async createChannel( - channel: Partial<Channel>, - user_id: string = "0", - opts?: { - keepId?: boolean; - skipExistsCheck?: boolean; - skipPermissionCheck?: boolean; - skipEventEmit?: boolean; - skipNameChecks?: boolean; - } - ) { - if (!opts?.skipPermissionCheck) { - // Always check if user has permission first - const permissions = await getPermission(user_id, channel.guild_id); - permissions.hasThrow("MANAGE_CHANNELS"); - } - - if (!opts?.skipNameChecks) { - const guild = await Guild.findOneOrFail({ where: { id: channel.guild_id } }); - if (!guild.features.includes("ALLOW_INVALID_CHANNEL_NAMES") && channel.name) { - for (let character of InvisibleCharacters) - if (channel.name.includes(character)) - throw new HTTPError("Channel name cannot include invalid characters", 403); - - if (channel.name.match(/\-\-+/g)) - throw new HTTPError("Channel name cannot include multiple adjacent dashes.", 403); - - if (channel.name.charAt(0) === "-" || channel.name.charAt(channel.name.length - 1) === "-") - throw new HTTPError("Channel name cannot start/end with dash.", 403); - } - - if (!guild.features.includes("ALLOW_UNNAMED_CHANNELS")) { - if (!channel.name) throw new HTTPError("Channel name cannot be empty.", 403); - } - } - - switch (channel.type) { - case ChannelType.GUILD_TEXT: - case ChannelType.GUILD_NEWS: - case ChannelType.GUILD_VOICE: - if (channel.parent_id && !opts?.skipExistsCheck) { - const exists = await Channel.findOneOrFail({ where: { id: channel.parent_id } }); - if (!exists) throw new HTTPError("Parent id channel doesn't exist", 400); - if (exists.guild_id !== channel.guild_id) - throw new HTTPError("The category channel needs to be in the guild"); - } - break; - case ChannelType.GUILD_CATEGORY: - case ChannelType.UNHANDLED: - break; - case ChannelType.DM: - case ChannelType.GROUP_DM: - throw new HTTPError("You can't create a dm channel in a guild"); - case ChannelType.GUILD_STORE: - default: - throw new HTTPError("Not yet supported"); - } - - if (!channel.permission_overwrites) channel.permission_overwrites = []; - // TODO: eagerly auto generate position of all guild channels - - channel = { - ...channel, - ...(!opts?.keepId && { id: Snowflake.generate() }), - created_at: new Date(), - position: (channel.type === ChannelType.UNHANDLED ? 0 : channel.position) || 0, - }; - - await Promise.all([ - OrmUtils.mergeDeep(new Channel(), channel).save(), - !opts?.skipEventEmit - ? emitEvent({ - event: "CHANNEL_CREATE", - data: channel, - guild_id: channel.guild_id, - } as ChannelCreateEvent) - : Promise.resolve(), - ]); - - return channel; - } - - static async createDMChannel(recipients: string[], creator_user_id: string, name?: string) { - recipients = recipients.unique().filter((x) => x !== creator_user_id); - const otherRecipientsUsers = await User.find({ where: recipients.map((x) => ({ id: x })) }); - - // TODO: check config for max number of recipients - /** if you want to disallow note to self channels, uncomment the conditional below - if (otherRecipientsUsers.length !== recipients.length) { - throw new HTTPError("Recipient/s not found"); - } - **/ - - const type = recipients.length > 1 ? ChannelType.GROUP_DM : ChannelType.DM; - - let channel = null; - - const channelRecipients = [...recipients, creator_user_id]; - - const userRecipients = await Recipient.find({ - where: { user_id: creator_user_id }, - relations: ["channel", "channel.recipients"], - }); - - for (let ur of userRecipients) { - let re = ur.channel.recipients!.map((r) => r.user_id); - if (re.length === channelRecipients.length) { - if (containsAll(re, channelRecipients)) { - if (channel == null) { - channel = ur.channel; - ur = OrmUtils.mergeDeep(ur, { closed: false }); - await ur.save(); - } - } - } - } - - if (channel == null) { - name = trimSpecial(name); - - channel = await ( - OrmUtils.mergeDeep(new Channel(), { - name, - type, - owner_id: type === ChannelType.DM ? undefined : null, // 1:1 DMs are ownerless in fosscord-server - created_at: new Date(), - last_message_id: null, - recipients: channelRecipients.map((x) => - OrmUtils.mergeDeep(new Recipient(), { - user_id: x, - closed: !(type === ChannelType.GROUP_DM || x === creator_user_id), - }) - ), - }) as Channel - ).save(); - } - - const channel_dto = await DmChannelDTO.from(channel); - - if (type === ChannelType.GROUP_DM) { - for (let recipient of channel.recipients!) { - await emitEvent({ - event: "CHANNEL_CREATE", - data: channel_dto.excludedRecipients([recipient.user_id]), - user_id: recipient.user_id, - }); - } - } else { - await emitEvent({ event: "CHANNEL_CREATE", data: channel_dto, user_id: creator_user_id }); - } - - if (recipients.length === 1) return channel_dto; - else return channel_dto.excludedRecipients([creator_user_id]); - } - - static async removeRecipientFromChannel(channel: Channel, user_id: string) { - await Recipient.delete({ channel_id: channel.id, user_id: user_id }); - channel.recipients = channel.recipients?.filter((r) => r.user_id !== user_id); - - if (channel.recipients?.length === 0) { - await Channel.deleteChannel(channel); - await emitEvent({ - event: "CHANNEL_DELETE", - data: await DmChannelDTO.from(channel, [user_id]), - user_id: user_id, - }); - return; - } - - await emitEvent({ - event: "CHANNEL_DELETE", - data: await DmChannelDTO.from(channel, [user_id]), - user_id: user_id, - }); - - //If the owner leave the server user is the new owner - if (channel.owner_id === user_id) { - channel.owner_id = "1"; // The channel is now owned by the server user - await emitEvent({ - event: "CHANNEL_UPDATE", - data: await DmChannelDTO.from(channel, [user_id]), - channel_id: channel.id, - }); - } - - await channel.save(); - - await emitEvent({ - event: "CHANNEL_RECIPIENT_REMOVE", - data: { - channel_id: channel.id, - user: await User.findOneOrFail({ where: { id: user_id }, select: PublicUserProjection }), - }, - channel_id: channel.id, - } as ChannelRecipientRemoveEvent); - } - - static async deleteChannel(channel: Channel) { - await Message.delete({ channel_id: channel.id }); //TODO we should also delete the attachments from the cdn but to do that we need to move cdn.ts in util - //TODO before deleting the channel we should check and delete other relations - await Channel.delete({ id: channel.id }); - } - - isDm() { - return this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM; - } - - // Does the channel support sending messages ( eg categories do not ) - isWritable() { - const disallowedChannelTypes = [ - ChannelType.GUILD_CATEGORY, - ChannelType.GUILD_STAGE_VOICE, - ChannelType.VOICELESS_WHITEBOARD, - ]; - return disallowedChannelTypes.indexOf(this.type) == -1; - } -} - -export interface ChannelPermissionOverwrite { - allow: string; - deny: string; - id: string; - type: ChannelPermissionOverwriteType; -} - -export enum ChannelPermissionOverwriteType { - role = 0, - member = 1, - group = 2, -} +import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; +import { DmChannelDTO } from "../dtos"; +import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces"; +import { containsAll, emitEvent, getPermission, InvisibleCharacters, Snowflake, trimSpecial } from "../util"; +import { HTTPError } from "../util/imports/HTTPError"; +import { OrmUtils } from "../util/imports/OrmUtils"; +import { BaseClass } from "./BaseClass"; +import { Guild } from "./Guild"; +import { Invite } from "./Invite"; +import { Message } from "./Message"; +import { ReadState } from "./ReadState"; +import { Recipient } from "./Recipient"; +import { PublicUserProjection, User } from "./User"; +import { VoiceState } from "./VoiceState"; +import { Webhook } from "./Webhook"; + +export enum ChannelType { + GUILD_TEXT = 0, // a text channel within a guild + DM = 1, // a direct message between users + GUILD_VOICE = 2, // a voice channel within a guild + GROUP_DM = 3, // a direct message between multiple users + GUILD_CATEGORY = 4, // an organizational category that contains zero or more channels + GUILD_NEWS = 5, // a channel that users can follow and crosspost into a guild or route + GUILD_STORE = 6, // a channel in which game developers can sell their things + ENCRYPTED = 7, // end-to-end encrypted channel + ENCRYPTED_THREAD = 8, // end-to-end encrypted thread channel + TRANSACTIONAL = 9, // event chain style transactional channel + GUILD_NEWS_THREAD = 10, // a temporary sub-channel within a GUILD_NEWS channel + GUILD_PUBLIC_THREAD = 11, // a temporary sub-channel within a GUILD_TEXT channel + GUILD_PRIVATE_THREAD = 12, // a temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission + GUILD_STAGE_VOICE = 13, // a voice channel for hosting events with an audience + DIRECTORY = 14, // guild directory listing channel + GUILD_FORUM = 15, // forum composed of IM threads + TICKET_TRACKER = 33, // ticket tracker, individual ticket items shall have type 12 + KANBAN = 34, // confluence like kanban board + VOICELESS_WHITEBOARD = 35, // whiteboard but without voice (whiteboard + voice is the same as stage) + CUSTOM_START = 64, // start custom channel types from here + UNHANDLED = 255 // unhandled unowned pass-through channel type +} + +@Entity("channels") +export class Channel extends BaseClass { + @Column() + created_at: Date; + + @Column({ nullable: true }) + name?: string; + + @Column({ type: "text", nullable: true }) + icon?: string | null; + + @Column({ type: "int" }) + type: ChannelType; + + @OneToMany(() => Recipient, (recipient: Recipient) => recipient.channel, { + cascade: true, + orphanedRowAction: "delete" + }) + recipients?: Recipient[]; + + @Column({ nullable: true }) + last_message_id: string; + + @Column({ nullable: true }) + @RelationId((channel: Channel) => channel.guild) + guild_id?: string; + + @JoinColumn({ name: "guild_id" }) + @ManyToOne(() => Guild, { + onDelete: "CASCADE" + }) + guild: Guild; + + @Column({ nullable: true }) + @RelationId((channel: Channel) => channel.parent) + parent_id: string; + + @JoinColumn({ name: "parent_id" }) + @ManyToOne(() => Channel) + parent?: Channel; + + // for group DMs and owned custom channel types + @Column({ nullable: true }) + @RelationId((channel: Channel) => channel.owner) + owner_id: string; + + @JoinColumn({ name: "owner_id" }) + @ManyToOne(() => User) + owner: User; + + @Column({ nullable: true }) + last_pin_timestamp?: number; + + @Column({ nullable: true }) + default_auto_archive_duration?: number; + + @Column({ nullable: true }) + position?: number; + + @Column({ type: "simple-json", nullable: true }) + permission_overwrites?: ChannelPermissionOverwrite[]; + + @Column({ nullable: true }) + video_quality_mode?: number; + + @Column({ nullable: true }) + bitrate?: number; + + @Column({ nullable: true }) + user_limit?: number; + + @Column({ nullable: true }) + nsfw?: boolean; + + @Column({ nullable: true }) + rate_limit_per_user?: number; + + @Column({ nullable: true }) + topic?: string; + + @OneToMany(() => Invite, (invite: Invite) => invite.channel, { + cascade: true, + orphanedRowAction: "delete" + }) + invites?: Invite[]; + + @Column({ nullable: true }) + retention_policy_id?: string; + + @OneToMany(() => Message, (message: Message) => message.channel, { + cascade: true, + orphanedRowAction: "delete" + }) + messages?: Message[]; + + @OneToMany(() => VoiceState, (voice_state: VoiceState) => voice_state.channel, { + cascade: true, + orphanedRowAction: "delete" + }) + voice_states?: VoiceState[]; + + @OneToMany(() => ReadState, (read_state: ReadState) => read_state.channel, { + cascade: true, + orphanedRowAction: "delete" + }) + read_states?: ReadState[]; + + @OneToMany(() => Webhook, (webhook: Webhook) => webhook.channel, { + cascade: true, + orphanedRowAction: "delete" + }) + webhooks?: Webhook[]; + + @Column({ nullable: true }) + flags?: number = 0; + + @Column({ nullable: true }) + default_thread_rate_limit_per_user?: number = 0; + + // TODO: DM channel + static async createChannel( + channel: Partial<Channel>, + user_id: string = "0", + opts?: { + keepId?: boolean; + skipExistsCheck?: boolean; + skipPermissionCheck?: boolean; + skipEventEmit?: boolean; + skipNameChecks?: boolean; + } + ) { + if (!opts?.skipPermissionCheck) { + // Always check if user has permission first + const permissions = await getPermission(user_id, channel.guild_id); + permissions.hasThrow("MANAGE_CHANNELS"); + } + + if (!opts?.skipNameChecks) { + const guild = await Guild.findOneOrFail({ where: { id: channel.guild_id } }); + if (!guild.features.includes("ALLOW_INVALID_CHANNEL_NAMES") && channel.name) { + for (let character of InvisibleCharacters) + if (channel.name.includes(character)) throw new HTTPError("Channel name cannot include invalid characters", 403); + + if (channel.name.match(/\-\-+/g)) throw new HTTPError("Channel name cannot include multiple adjacent dashes.", 403); + + if (channel.name.charAt(0) === "-" || channel.name.charAt(channel.name.length - 1) === "-") + throw new HTTPError("Channel name cannot start/end with dash.", 403); + } + + if (!guild.features.includes("ALLOW_UNNAMED_CHANNELS")) { + if (!channel.name) throw new HTTPError("Channel name cannot be empty.", 403); + } + } + + switch (channel.type) { + case ChannelType.GUILD_TEXT: + case ChannelType.GUILD_NEWS: + case ChannelType.GUILD_VOICE: + if (channel.parent_id && !opts?.skipExistsCheck) { + const exists = await Channel.findOneOrFail({ where: { id: channel.parent_id } }); + if (!exists) throw new HTTPError("Parent id channel doesn't exist", 400); + if (exists.guild_id !== channel.guild_id) throw new HTTPError("The category channel needs to be in the guild"); + } + break; + case ChannelType.GUILD_CATEGORY: + case ChannelType.UNHANDLED: + break; + case ChannelType.DM: + case ChannelType.GROUP_DM: + throw new HTTPError("You can't create a dm channel in a guild"); + case ChannelType.GUILD_STORE: + default: + throw new HTTPError("Not yet supported"); + } + + if (!channel.permission_overwrites) channel.permission_overwrites = []; + // TODO: eagerly auto generate position of all guild channels + + channel = { + ...channel, + ...(!opts?.keepId && { id: Snowflake.generate() }), + created_at: new Date(), + position: (channel.type === ChannelType.UNHANDLED ? 0 : channel.position) || 0 + }; + + await Promise.all([ + OrmUtils.mergeDeep(new Channel(), channel).save(), + !opts?.skipEventEmit + ? emitEvent({ + event: "CHANNEL_CREATE", + data: channel, + guild_id: channel.guild_id + } as ChannelCreateEvent) + : Promise.resolve() + ]); + + return channel; + } + + static async createDMChannel(recipients: string[], creator_user_id: string, name?: string) { + recipients = recipients.unique().filter((x) => x !== creator_user_id); + const otherRecipientsUsers = await User.find({ where: recipients.map((x) => ({ id: x })) }); + + // TODO: check config for max number of recipients + /** if you want to disallow note to self channels, uncomment the conditional below + if (otherRecipientsUsers.length !== recipients.length) { + throw new HTTPError("Recipient/s not found"); + } + **/ + + const type = recipients.length > 1 ? ChannelType.GROUP_DM : ChannelType.DM; + + let channel = null; + + const channelRecipients = [...recipients, creator_user_id]; + + const userRecipients = await Recipient.find({ + where: { user_id: creator_user_id }, + relations: ["channel", "channel.recipients"] + }); + + for (let ur of userRecipients) { + let re = ur.channel.recipients!.map((r) => r.user_id); + if (re.length === channelRecipients.length) { + if (containsAll(re, channelRecipients)) { + if (channel == null) { + channel = ur.channel; + ur = OrmUtils.mergeDeep(ur, { closed: false }); + await ur.save(); + } + } + } + } + + if (channel == null) { + name = trimSpecial(name); + + channel = await ( + OrmUtils.mergeDeep(new Channel(), { + name, + type, + owner_id: type === ChannelType.DM ? undefined : null, // 1:1 DMs are ownerless in fosscord-server + created_at: new Date(), + last_message_id: null, + recipients: channelRecipients.map((x) => + OrmUtils.mergeDeep(new Recipient(), { + user_id: x, + closed: !(type === ChannelType.GROUP_DM || x === creator_user_id) + }) + ) + }) as Channel + ).save(); + } + + const channel_dto = await DmChannelDTO.from(channel); + + if (type === ChannelType.GROUP_DM) { + for (let recipient of channel.recipients!) { + await emitEvent({ + event: "CHANNEL_CREATE", + data: channel_dto.excludedRecipients([recipient.user_id]), + user_id: recipient.user_id + }); + } + } else { + await emitEvent({ event: "CHANNEL_CREATE", data: channel_dto, user_id: creator_user_id }); + } + + if (recipients.length === 1) return channel_dto; + else return channel_dto.excludedRecipients([creator_user_id]); + } + + static async removeRecipientFromChannel(channel: Channel, user_id: string) { + await Recipient.delete({ channel_id: channel.id, user_id: user_id }); + channel.recipients = channel.recipients?.filter((r) => r.user_id !== user_id); + + if (channel.recipients?.length === 0) { + await Channel.deleteChannel(channel); + await emitEvent({ + event: "CHANNEL_DELETE", + data: await DmChannelDTO.from(channel, [user_id]), + user_id: user_id + }); + return; + } + + await emitEvent({ + event: "CHANNEL_DELETE", + data: await DmChannelDTO.from(channel, [user_id]), + user_id: user_id + }); + + //If the owner leave the server user is the new owner + if (channel.owner_id === user_id) { + channel.owner_id = "1"; // The channel is now owned by the server user + await emitEvent({ + event: "CHANNEL_UPDATE", + data: await DmChannelDTO.from(channel, [user_id]), + channel_id: channel.id + }); + } + + await channel.save(); + + await emitEvent({ + event: "CHANNEL_RECIPIENT_REMOVE", + data: { + channel_id: channel.id, + user: await User.findOneOrFail({ where: { id: user_id }, select: PublicUserProjection }) + }, + channel_id: channel.id + } as ChannelRecipientRemoveEvent); + } + + static async deleteChannel(channel: Channel) { + await Message.delete({ channel_id: channel.id }); //TODO we should also delete the attachments from the cdn but to do that we need to move cdn.ts in util + //TODO before deleting the channel we should check and delete other relations + await Channel.delete({ id: channel.id }); + } + + isDm() { + return this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM; + } + + // Does the channel support sending messages ( eg categories do not ) + isWritable() { + const disallowedChannelTypes = [ChannelType.GUILD_CATEGORY, ChannelType.GUILD_STAGE_VOICE, ChannelType.VOICELESS_WHITEBOARD]; + return disallowedChannelTypes.indexOf(this.type) == -1; + } +} + +export interface ChannelPermissionOverwrite { + allow: string; + deny: string; + id: string; + type: ChannelPermissionOverwriteType; +} + +export enum ChannelPermissionOverwriteType { + role = 0, + member = 1, + group = 2 +} diff --git a/src/util/entities/ClientRelease.ts b/src/util/entities/ClientRelease.ts index c5afd307..2723ab67 100644 --- a/src/util/entities/ClientRelease.ts +++ b/src/util/entities/ClientRelease.ts @@ -1,4 +1,4 @@ -import { Column, Entity} from "typeorm"; +import { Column, Entity } from "typeorm"; import { BaseClass } from "./BaseClass"; @Entity("client_release") diff --git a/src/util/entities/Config.ts b/src/util/entities/Config.ts index 606fe901..fc33bb65 100644 --- a/src/util/entities/Config.ts +++ b/src/util/entities/Config.ts @@ -8,4 +8,4 @@ export class ConfigEntity extends BaseClassWithoutId { @Column({ type: "simple-json", nullable: true }) value: number | boolean | null | string | undefined; -} \ No newline at end of file +} diff --git a/src/util/entities/ConnectedAccount.ts b/src/util/entities/ConnectedAccount.ts index 09ae30ab..018b3995 100644 --- a/src/util/entities/ConnectedAccount.ts +++ b/src/util/entities/ConnectedAccount.ts @@ -12,7 +12,7 @@ export class ConnectedAccount extends BaseClass { @JoinColumn({ name: "user_id" }) @ManyToOne(() => User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) user: User; diff --git a/src/util/entities/Emoji.ts b/src/util/entities/Emoji.ts index a3615b7d..a2552995 100644 --- a/src/util/entities/Emoji.ts +++ b/src/util/entities/Emoji.ts @@ -2,7 +2,6 @@ import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; import { User } from "."; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; -import { Role } from "./Role"; @Entity("emojis") export class Emoji extends BaseClass { @@ -17,7 +16,7 @@ export class Emoji extends BaseClass { @JoinColumn({ name: "guild_id" }) @ManyToOne(() => Guild, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) guild: Guild; @@ -40,7 +39,7 @@ export class Emoji extends BaseClass { @Column({ type: "simple-array" }) roles: string[]; // roles this emoji is whitelisted to (new discord feature?) - + @Column({ type: "simple-array", nullable: true }) groups: string[]; // user groups this emoji is whitelisted to (Fosscord extension) } diff --git a/src/util/entities/Encryption.ts b/src/util/entities/Encryption.ts index 6b578d15..43f02962 100644 --- a/src/util/entities/Encryption.ts +++ b/src/util/entities/Encryption.ts @@ -1,35 +1,25 @@ -import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; +import { Column, Entity } from "typeorm"; +import { Snowflake } from "../util"; +import { BitField } from "../util/BitField"; import { BaseClass } from "./BaseClass"; -import { Guild } from "./Guild"; -import { PublicUserProjection, User } from "./User"; -import { HTTPError } from ".."; -import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial, InvisibleCharacters } from "../util"; -import { BitField, BitFieldResolvable, BitFlag } from "../util/BitField"; -import { Recipient } from "./Recipient"; -import { Message } from "./Message"; -import { ReadState } from "./ReadState"; -import { Invite } from "./Invite"; -import { DmChannelDTO } from "../dtos"; @Entity("security_settings") export class SecuritySettings extends BaseClass { + @Column({ nullable: true }) + guild_id: Snowflake; - @Column({nullable: true}) - guild_id: Snowflake; + @Column({ nullable: true }) + channel_id: Snowflake; - @Column({nullable: true}) - channel_id: Snowflake; + @Column() + encryption_permission_mask: BitField; - @Column() - encryption_permission_mask: BitField; + @Column() + allowed_algorithms: string[]; - @Column() - allowed_algorithms: string[]; - - @Column() - current_algorithm: string; - - @Column({nullable: true}) - used_since_message: Snowflake; + @Column() + current_algorithm: string; + @Column({ nullable: true }) + used_since_message: Snowflake; } diff --git a/src/util/entities/Group.ts b/src/util/entities/Group.ts index b24d38cf..23aaabf2 100644 --- a/src/util/entities/Group.ts +++ b/src/util/entities/Group.ts @@ -1,11 +1,11 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import { Column, Entity } from "typeorm"; import { BaseClass } from "./BaseClass"; @Entity("groups") export class UserGroup extends BaseClass { - @Column({ nullable: true }) - parent?: BigInt; + @Column({ nullable: true }) + parent?: BigInt; @Column() color: number; @@ -13,7 +13,7 @@ export class UserGroup extends BaseClass { @Column() hoist: boolean; - @Column() + @Column() mentionable: boolean; @Column() diff --git a/src/util/entities/Guild.ts b/src/util/entities/Guild.ts index d146e577..015c6d04 100644 --- a/src/util/entities/Guild.ts +++ b/src/util/entities/Guild.ts @@ -1,6 +1,6 @@ -import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, OneToMany, OneToOne, RelationId } from "typeorm"; -import { OrmUtils } from "../util/imports/OrmUtils"; +import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; import { Config, handleFile, Snowflake } from ".."; +import { OrmUtils } from "../util/imports/OrmUtils"; import { Ban } from "./Ban"; import { BaseClass } from "./BaseClass"; import { Channel } from "./Channel"; @@ -32,15 +32,7 @@ import { Webhook } from "./Webhook"; // "Gacha" // ], -export const PublicGuildRelations = [ - "channels", - "emojis", - "members", - "roles", - "stickers", - "voice_states", - "members.user", -]; +export const PublicGuildRelations = ["channels", "emojis", "members", "roles", "stickers", "voice_states", "members.user"]; @Entity("guilds") export class Guild extends BaseClass { @@ -63,7 +55,7 @@ export class Guild extends BaseClass { @JoinColumn({ name: "ban_ids" }) @OneToMany(() => Ban, (ban: Ban) => ban.guild, { cascade: true, - orphanedRowAction: "delete", + orphanedRowAction: "delete" }) bans: Ban[]; @@ -113,7 +105,7 @@ export class Guild extends BaseClass { @OneToMany(() => Member, (member: Member) => member.guild, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", + onDelete: "CASCADE" }) members: Member[]; @@ -121,14 +113,14 @@ export class Guild extends BaseClass { @OneToMany(() => Role, (role: Role) => role.guild, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", + onDelete: "CASCADE" }) roles: Role[]; @JoinColumn({ name: "channel_ids" }) @OneToMany(() => Channel, (channel: Channel) => channel.guild, { cascade: true, - orphanedRowAction: "delete", + orphanedRowAction: "delete" }) channels: Channel[]; @@ -144,7 +136,7 @@ export class Guild extends BaseClass { @OneToMany(() => Emoji, (emoji: Emoji) => emoji.guild, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", + onDelete: "CASCADE" }) emojis: Emoji[]; @@ -152,7 +144,7 @@ export class Guild extends BaseClass { @OneToMany(() => Sticker, (sticker: Sticker) => sticker.guild, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", + onDelete: "CASCADE" }) stickers: Sticker[]; @@ -160,7 +152,7 @@ export class Guild extends BaseClass { @OneToMany(() => Invite, (invite: Invite) => invite.guild, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", + onDelete: "CASCADE" }) invites: Invite[]; @@ -168,7 +160,7 @@ export class Guild extends BaseClass { @OneToMany(() => VoiceState, (voicestate: VoiceState) => voicestate.guild, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", + onDelete: "CASCADE" }) voice_states: VoiceState[]; @@ -176,7 +168,7 @@ export class Guild extends BaseClass { @OneToMany(() => Webhook, (webhook: Webhook) => webhook.guild, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", + onDelete: "CASCADE" }) webhooks: Webhook[]; @@ -282,12 +274,7 @@ export class Guild extends BaseClass { @Column({ nullable: true }) premium_progress_bar_enabled: boolean = false; - static async createGuild(body: { - name?: string; - icon?: string | null; - owner_id?: string; - channels?: Partial<Channel>[]; - }) { + static async createGuild(body: { name?: string; icon?: string | null; owner_id?: string; channels?: Partial<Channel>[] }) { const guild_id = Snowflake.generate(); const guild: Guild = OrmUtils.mergeDeep(new Guild(), { @@ -318,9 +305,9 @@ export class Guild extends BaseClass { welcome_screen: { enabled: false, description: "Fill in your description", - welcome_channels: [], + welcome_channels: [] }, - widget_enabled: true, // NB: don't set it as false to prevent artificial restrictions + widget_enabled: true // NB: don't set it as false to prevent artificial restrictions }); await guild.save(); @@ -338,7 +325,7 @@ export class Guild extends BaseClass { permissions: String("2251804225"), position: 0, icon: null, - unicode_emoji: null, + unicode_emoji: null }); await role.save(); @@ -361,7 +348,7 @@ export class Guild extends BaseClass { keepId: true, skipExistsCheck: true, skipPermissionCheck: true, - skipEventEmit: true, + skipEventEmit: true }); } diff --git a/src/util/entities/Invite.ts b/src/util/entities/Invite.ts index 1e0ebe52..f6ba85d7 100644 --- a/src/util/entities/Invite.ts +++ b/src/util/entities/Invite.ts @@ -1,10 +1,10 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId, PrimaryColumn } from "typeorm"; -import { Member } from "./Member"; +import { random } from "@fosscord/api"; +import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn, RelationId } from "typeorm"; import { BaseClassWithoutId } from "./BaseClass"; import { Channel } from "./Channel"; import { Guild } from "./Guild"; +import { Member } from "./Member"; import { User } from "./User"; -import { random } from "@fosscord/api"; export const PublicInviteRelation = ["inviter", "guild", "channel"]; @@ -37,7 +37,7 @@ export class Invite extends BaseClassWithoutId { @JoinColumn({ name: "guild_id" }) @ManyToOne(() => Guild, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) guild: Guild; @@ -47,7 +47,7 @@ export class Invite extends BaseClassWithoutId { @JoinColumn({ name: "channel_id" }) @ManyToOne(() => Channel, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) channel: Channel; @@ -67,7 +67,7 @@ export class Invite extends BaseClassWithoutId { @JoinColumn({ name: "target_user_id" }) @ManyToOne(() => User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) target_user?: string; // could be used for "User specific invites" https://github.com/fosscord/fosscord/issues/62 diff --git a/src/util/entities/Member.ts b/src/util/entities/Member.ts index baac58ed..42a014d4 100644 --- a/src/util/entities/Member.ts +++ b/src/util/entities/Member.ts @@ -1,31 +1,14 @@ -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 { Column, Entity, Index, JoinColumn, JoinTable, ManyToMany, ManyToOne, PrimaryGeneratedColumn, RelationId } from "typeorm"; import { Ban, PublicGuildRelations } from "."; +import { GuildCreateEvent, GuildDeleteEvent, GuildMemberAddEvent, GuildMemberRemoveEvent, GuildMemberUpdateEvent } from "../interfaces"; +import { Config, emitEvent } from "../util"; import { DiscordApiErrors } from "../util/Constants"; +import { HTTPError } from "../util/imports/HTTPError"; import { OrmUtils } from "../util/imports/OrmUtils"; +import { BaseClassWithoutId } from "./BaseClass"; +import { Guild } from "./Guild"; +import { Role } from "./Role"; +import { PublicUser, User } from "./User"; export const MemberPrivateProjection: (keyof Member)[] = [ "id", @@ -40,7 +23,7 @@ export const MemberPrivateProjection: (keyof Member)[] = [ "premium_since", "roles", "settings", - "user", + "user" ]; @Entity("members") @@ -55,7 +38,7 @@ export class Member extends BaseClassWithoutId { @JoinColumn({ name: "id" }) @ManyToOne(() => User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) user: User; @@ -65,7 +48,7 @@ export class Member extends BaseClassWithoutId { @JoinColumn({ name: "guild_id" }) @ManyToOne(() => Guild, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) guild: Guild; @@ -77,8 +60,8 @@ export class Member extends BaseClassWithoutId { joinColumn: { name: "index", referencedColumnName: "index" }, inverseJoinColumn: { name: "role_id", - referencedColumnName: "id", - }, + referencedColumnName: "id" + } }) @ManyToMany(() => Role, { cascade: true }) roles: Role[]; @@ -133,22 +116,22 @@ export class Member extends BaseClassWithoutId { 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, + id: guild_id }, - user_id: user_id, + user_id: user_id } as GuildDeleteEvent), emitEvent({ event: "GUILD_MEMBER_REMOVE", data: { guild_id, user: member.user }, - guild_id, - } as GuildMemberRemoveEvent), + guild_id + } as GuildMemberRemoveEvent) ]); } @@ -158,9 +141,9 @@ export class Member extends BaseClassWithoutId { 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"], + select: ["index"] }), - Role.findOneOrFail({ where: { id: role_id, guild_id }, select: ["id"] }), + Role.findOneOrFail({ where: { id: role_id, guild_id }, select: ["id"] }) ]); member.roles.push(OrmUtils.mergeDeep(new Role(), { id: role_id })); @@ -171,10 +154,10 @@ export class Member extends BaseClassWithoutId { data: { guild_id, user: member.user, - roles: member.roles.map((x) => x.id), + roles: member.roles.map((x) => x.id) }, - guild_id, - } as GuildMemberUpdateEvent), + guild_id + } as GuildMemberUpdateEvent) ]); } @@ -184,9 +167,9 @@ export class Member extends BaseClassWithoutId { 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"], + select: ["index"] }), - await Role.findOneOrFail({ where: { id: role_id, guild_id } }), + await Role.findOneOrFail({ where: { id: role_id, guild_id } }) ]); member.roles = member.roles.filter((x) => x.id == role_id); @@ -197,10 +180,10 @@ export class Member extends BaseClassWithoutId { data: { guild_id, user: member.user, - roles: member.roles.map((x) => x.id), + roles: member.roles.map((x) => x.id) }, - guild_id, - } as GuildMemberUpdateEvent), + guild_id + } as GuildMemberUpdateEvent) ]); } @@ -208,9 +191,9 @@ export class Member extends BaseClassWithoutId { const member = await Member.findOneOrFail({ where: { id: user_id, - guild_id, + guild_id }, - relations: ["user"], + relations: ["user"] }); member.nick = nickname; @@ -222,10 +205,10 @@ export class Member extends BaseClassWithoutId { data: { guild_id, user: member.user, - nick: nickname, + nick: nickname }, - guild_id, - } as GuildMemberUpdateEvent), + guild_id + } as GuildMemberUpdateEvent) ]); } @@ -243,9 +226,9 @@ export class Member extends BaseClassWithoutId { const guild = await Guild.findOneOrFail({ where: { - id: guild_id, + id: guild_id }, - relations: PublicGuildRelations, + relations: PublicGuildRelations }); if (await Member.count({ where: { id: user.id, guild: { id: guild_id } } })) @@ -260,7 +243,7 @@ export class Member extends BaseClassWithoutId { premium_since: null, deaf: false, mute: false, - pending: false, + pending: false }; //TODO: check for bugs if (guild.member_count) guild.member_count++; @@ -276,8 +259,8 @@ export class Member extends BaseClassWithoutId { muted: false, suppress_everyone: false, suppress_roles: false, - version: 0, - }, + version: 0 + } // Member.save is needed because else the roles relations wouldn't be updated }).save(), //Guild.increment({ id: guild_id }, "member_count", 1), @@ -286,9 +269,9 @@ export class Member extends BaseClassWithoutId { data: { ...member, user, - guild_id, + guild_id }, - guild_id, + guild_id } as GuildMemberAddEvent), emitEvent({ event: "GUILD_CREATE", @@ -301,10 +284,10 @@ export class Member extends BaseClassWithoutId { joined_at: member.joined_at, presences: [], stage_instances: [], - threads: [], + threads: [] }, - user_id, - } as GuildCreateEvent), + user_id + } as GuildCreateEvent) ]); } } @@ -330,16 +313,7 @@ export interface MuteConfig { selected_time_window: number; } -export type PublicMemberKeys = - | "id" - | "guild_id" - | "nick" - | "roles" - | "joined_at" - | "pending" - | "deaf" - | "mute" - | "premium_since"; +export type PublicMemberKeys = "id" | "guild_id" | "nick" | "roles" | "joined_at" | "pending" | "deaf" | "mute" | "premium_since"; export const PublicMemberProjection: PublicMemberKeys[] = [ "id", @@ -350,7 +324,7 @@ export const PublicMemberProjection: PublicMemberKeys[] = [ "pending", "deaf", "mute", - "premium_since", + "premium_since" ]; // @ts-ignore diff --git a/src/util/entities/Message.ts b/src/util/entities/Message.ts index ba3d4f2d..8122b532 100644 --- a/src/util/entities/Message.ts +++ b/src/util/entities/Message.ts @@ -1,28 +1,15 @@ -import { User } from "./User"; -import { Member } from "./Member"; -import { Role } from "./Role"; -import { Channel } from "./Channel"; +import { Column, CreateDateColumn, Entity, Index, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToMany, RelationId } from "typeorm"; import { InteractionType } from "../interfaces/Interaction"; import { Application } from "./Application"; -import { - Column, - CreateDateColumn, - Entity, - Index, - JoinColumn, - JoinTable, - ManyToMany, - ManyToOne, - OneToMany, - RelationId, - RemoveOptions, - UpdateDateColumn, -} from "typeorm"; +import { Attachment } from "./Attachment"; import { BaseClass } from "./BaseClass"; +import { Channel } from "./Channel"; import { Guild } from "./Guild"; -import { Webhook } from "./Webhook"; +import { Member } from "./Member"; +import { Role } from "./Role"; import { Sticker } from "./Sticker"; -import { Attachment } from "./Attachment"; +import { User } from "./User"; +import { Webhook } from "./Webhook"; export enum MessageType { DEFAULT = 0, @@ -62,7 +49,7 @@ export class Message extends BaseClass { @JoinColumn({ name: "channel_id" }) @ManyToOne(() => Channel, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) channel: Channel; @@ -72,7 +59,7 @@ export class Message extends BaseClass { @JoinColumn({ name: "guild_id" }) @ManyToOne(() => Guild, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) guild?: Guild; @@ -83,7 +70,7 @@ export class Message extends BaseClass { @JoinColumn({ name: "author_id", referencedColumnName: "id" }) @ManyToOne(() => User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) author?: User; @@ -93,7 +80,7 @@ export class Message extends BaseClass { @JoinColumn({ name: "member_id", referencedColumnName: "id" }) @ManyToOne(() => User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) member?: Member; @@ -147,7 +134,7 @@ export class Message extends BaseClass { @OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, { cascade: true, - orphanedRowAction: "delete", + orphanedRowAction: "delete" }) attachments?: Attachment[]; @@ -212,7 +199,7 @@ export interface MessageComponent { export enum MessageComponentType { Script = 0, // self command script ActionRow = 1, - Button = 2, + Button = 2 } export interface Embed { @@ -253,7 +240,7 @@ export enum EmbedType { video = "video", gifv = "gifv", article = "article", - link = "link", + link = "link" } export interface EmbedImage { diff --git a/src/util/entities/Migration.ts b/src/util/entities/Migration.ts index 3f39ae72..626ec429 100644 --- a/src/util/entities/Migration.ts +++ b/src/util/entities/Migration.ts @@ -1,9 +1,7 @@ import { Column, Entity, ObjectIdColumn, PrimaryGeneratedColumn } from "typeorm"; import { BaseClassWithoutId } from "."; -export const PrimaryIdAutoGenerated = process.env.DATABASE?.startsWith("mongodb") - ? ObjectIdColumn - : PrimaryGeneratedColumn; +export const PrimaryIdAutoGenerated = process.env.DATABASE?.startsWith("mongodb") ? ObjectIdColumn : PrimaryGeneratedColumn; @Entity("migrations") export class Migration extends BaseClassWithoutId { diff --git a/src/util/entities/Note.ts b/src/util/entities/Note.ts index 36017c5e..b3ac45ee 100644 --- a/src/util/entities/Note.ts +++ b/src/util/entities/Note.ts @@ -15,4 +15,4 @@ export class Note extends BaseClass { @Column() content: string; -} \ No newline at end of file +} diff --git a/src/util/entities/ReadState.ts b/src/util/entities/ReadState.ts index b915573b..77d2c08a 100644 --- a/src/util/entities/ReadState.ts +++ b/src/util/entities/ReadState.ts @@ -1,7 +1,6 @@ import { Column, Entity, Index, JoinColumn, ManyToOne, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Channel } from "./Channel"; -import { Message } from "./Message"; import { User } from "./User"; // for read receipts @@ -17,7 +16,7 @@ export class ReadState extends BaseClass { @JoinColumn({ name: "channel_id" }) @ManyToOne(() => Channel, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) channel: Channel; @@ -27,14 +26,14 @@ export class ReadState extends BaseClass { @JoinColumn({ name: "user_id" }) @ManyToOne(() => User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) user: User; // fully read marker @Column({ nullable: true }) - last_message_id: string; - + last_message_id: string; + // public read receipt @Column({ nullable: true }) public_ack: string; diff --git a/src/util/entities/Recipient.ts b/src/util/entities/Recipient.ts index a945f938..fc9e629b 100644 --- a/src/util/entities/Recipient.ts +++ b/src/util/entities/Recipient.ts @@ -9,7 +9,7 @@ export class Recipient extends BaseClass { @JoinColumn({ name: "channel_id" }) @ManyToOne(() => require("./Channel").Channel, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) channel: import("./Channel").Channel; @@ -19,7 +19,7 @@ export class Recipient extends BaseClass { @JoinColumn({ name: "user_id" }) @ManyToOne(() => require("./User").User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) user: import("./User").User; diff --git a/src/util/entities/Relationship.ts b/src/util/entities/Relationship.ts index c3592c76..b55d9e64 100644 --- a/src/util/entities/Relationship.ts +++ b/src/util/entities/Relationship.ts @@ -6,7 +6,7 @@ export enum RelationshipType { outgoing = 4, incoming = 3, blocked = 2, - friends = 1, + friends = 1 } @Entity("relationships") @@ -18,7 +18,7 @@ export class Relationship extends BaseClass { @JoinColumn({ name: "from_id" }) @ManyToOne(() => User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) from: User; @@ -28,7 +28,7 @@ export class Relationship extends BaseClass { @JoinColumn({ name: "to_id" }) @ManyToOne(() => User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) to: User; @@ -43,7 +43,7 @@ export class Relationship extends BaseClass { id: this.to?.id || this.to_id, type: this.type, nickname: this.nickname, - user: this.to?.toPublicUser(), + user: this.to?.toPublicUser() }; } } diff --git a/src/util/entities/Role.ts b/src/util/entities/Role.ts index 4b721b5b..b1fd9bb1 100644 --- a/src/util/entities/Role.ts +++ b/src/util/entities/Role.ts @@ -11,7 +11,7 @@ export class Role extends BaseClass { @JoinColumn({ name: "guild_id" }) @ManyToOne(() => Guild, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) guild: Guild; diff --git a/src/util/entities/Session.ts b/src/util/entities/Session.ts index 969efa89..0cb4c309 100644 --- a/src/util/entities/Session.ts +++ b/src/util/entities/Session.ts @@ -1,8 +1,8 @@ -import { User } from "./User"; -import { BaseClass } from "./BaseClass"; import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; -import { Status } from "../interfaces/Status"; import { Activity } from "../interfaces/Activity"; +import { Status } from "../interfaces/Status"; +import { BaseClass } from "./BaseClass"; +import { User } from "./User"; //TODO we need to remove all sessions on server start because if the server crashes without closing websockets it won't delete them @@ -14,7 +14,7 @@ export class Session extends BaseClass { @JoinColumn({ name: "user_id" }) @ManyToOne(() => User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) user: User; @@ -37,10 +37,4 @@ export class Session extends BaseClass { status: Status; //TODO enum } -export const PrivateSessionProjection: (keyof Session)[] = [ - "user_id", - "session_id", - "activities", - "client_info", - "status", -]; +export const PrivateSessionProjection: (keyof Session)[] = ["user_id", "session_id", "activities", "client_info", "status"]; diff --git a/src/util/entities/Sticker.ts b/src/util/entities/Sticker.ts index 37bc6fbe..69836e62 100644 --- a/src/util/entities/Sticker.ts +++ b/src/util/entities/Sticker.ts @@ -1,18 +1,18 @@ import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; -import { User } from "./User"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; +import { User } from "./User"; export enum StickerType { STANDARD = 1, - GUILD = 2, + GUILD = 2 } export enum StickerFormatType { GIF = 0, // gif is a custom format type and not in discord spec PNG = 1, APNG = 2, - LOTTIE = 3, + LOTTIE = 3 } @Entity("stickers") @@ -36,7 +36,7 @@ export class Sticker extends BaseClass { @JoinColumn({ name: "pack_id" }) @ManyToOne(() => require("./StickerPack").StickerPack, { onDelete: "CASCADE", - nullable: true, + nullable: true }) pack: import("./StickerPack").StickerPack; @@ -45,7 +45,7 @@ export class Sticker extends BaseClass { @JoinColumn({ name: "guild_id" }) @ManyToOne(() => Guild, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) guild?: Guild; @@ -54,7 +54,7 @@ export class Sticker extends BaseClass { @JoinColumn({ name: "user_id" }) @ManyToOne(() => User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) user?: User; diff --git a/src/util/entities/StickerPack.ts b/src/util/entities/StickerPack.ts index ec8c69a2..4619af34 100644 --- a/src/util/entities/StickerPack.ts +++ b/src/util/entities/StickerPack.ts @@ -1,4 +1,4 @@ -import { Column, Entity, JoinColumn, ManyToOne, OneToMany, OneToOne, RelationId } from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; import { Sticker } from "."; import { BaseClass } from "./BaseClass"; @@ -15,7 +15,7 @@ export class StickerPack extends BaseClass { @OneToMany(() => Sticker, (sticker: Sticker) => sticker.pack, { cascade: true, - orphanedRowAction: "delete", + orphanedRowAction: "delete" }) stickers: Sticker[]; diff --git a/src/util/entities/Team.ts b/src/util/entities/Team.ts index 22140b7f..1d2d7002 100644 --- a/src/util/entities/Team.ts +++ b/src/util/entities/Team.ts @@ -1,4 +1,4 @@ -import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, OneToMany, RelationId } from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { TeamMember } from "./TeamMember"; import { User } from "./User"; @@ -10,7 +10,7 @@ export class Team extends BaseClass { @JoinColumn({ name: "member_ids" }) @OneToMany(() => TeamMember, (member: TeamMember) => member.team, { - orphanedRowAction: "delete", + orphanedRowAction: "delete" }) members: TeamMember[]; diff --git a/src/util/entities/TeamMember.ts b/src/util/entities/TeamMember.ts index b726e1e8..d11ebf95 100644 --- a/src/util/entities/TeamMember.ts +++ b/src/util/entities/TeamMember.ts @@ -4,7 +4,7 @@ import { User } from "./User"; export enum TeamMemberState { INVITED = 1, - ACCEPTED = 2, + ACCEPTED = 2 } @Entity("team_members") @@ -21,7 +21,7 @@ export class TeamMember extends BaseClass { @JoinColumn({ name: "team_id" }) @ManyToOne(() => require("./Team").Team, (team: import("./Team").Team) => team.members, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) team: import("./Team").Team; @@ -31,7 +31,7 @@ export class TeamMember extends BaseClass { @JoinColumn({ name: "user_id" }) @ManyToOne(() => User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) user: User; } diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts index 5432f298..1237b676 100644 --- a/src/util/entities/User.ts +++ b/src/util/entities/User.ts @@ -1,11 +1,11 @@ import { Column, Entity, FindOneOptions, FindOptionsSelectByString, JoinColumn, OneToMany, OneToOne } from "typeorm"; +import { Member, Session, UserSettings } from "."; +import { Config, FieldErrors, Snowflake, trimSpecial } from ".."; +import { BitField } from "../util/BitField"; import { OrmUtils } from "../util/imports/OrmUtils"; import { BaseClass } from "./BaseClass"; -import { BitField } from "../util/BitField"; -import { Relationship } from "./Relationship"; import { ConnectedAccount } from "./ConnectedAccount"; -import { Config, FieldErrors, Snowflake, trimSpecial } from ".."; -import { Member, Session, UserSettings } from "."; +import { Relationship } from "./Relationship"; export enum PublicUserEnum { username, @@ -17,7 +17,7 @@ export enum PublicUserEnum { banner, bio, bot, - premium_since, + premium_since } export type PublicUserKeys = keyof typeof PublicUserEnum; @@ -31,17 +31,15 @@ export enum PrivateUserEnum { premium, premium_type, disabled, - settings, + settings // locale } export type PrivateUserKeys = keyof typeof PrivateUserEnum | PublicUserKeys; -export const PublicUserProjection = Object.values(PublicUserEnum).filter( - (x) => typeof x === "string" -) as PublicUserKeys[]; +export const PublicUserProjection = Object.values(PublicUserEnum).filter((x) => typeof x === "string") as PublicUserKeys[]; export const PrivateUserProjection = [ ...PublicUserProjection, - ...Object.values(PrivateUserEnum).filter((x) => typeof x === "string"), + ...Object.values(PrivateUserEnum).filter((x) => typeof x === "string") ] as PrivateUserKeys[]; // Private user data that should never get sent to the client @@ -148,14 +146,14 @@ export class User extends BaseClass { @JoinColumn({ name: "relationship_ids" }) @OneToMany(() => Relationship, (relationship: Relationship) => relationship.from, { cascade: true, - orphanedRowAction: "delete", + orphanedRowAction: "delete" }) relationships: Relationship[]; @JoinColumn({ name: "connected_account_ids" }) @OneToMany(() => ConnectedAccount, (account: ConnectedAccount) => account.user, { cascade: true, - orphanedRowAction: "delete", + orphanedRowAction: "delete" }) connected_accounts: ConnectedAccount[]; @@ -168,8 +166,7 @@ export class User extends BaseClass { @Column({ type: "simple-array", select: false }) fingerprints: string[] = []; // array of fingerprints -> used to prevent multiple accounts - - @OneToOne(()=> UserSettings, { + @OneToOne(() => UserSettings, { cascade: true, orphanedRowAction: "delete", eager: false @@ -185,7 +182,7 @@ export class User extends BaseClass { notes: { [key: string]: string } = {}; //key is ID of user async save(): Promise<any> { - if(!this.settings) this.settings = new UserSettings(); + if (!this.settings) this.settings = new UserSettings(); this.settings.id = this.id; //await this.settings.save(); return super.save(); @@ -203,7 +200,7 @@ export class User extends BaseClass { return await User.findOneOrFail({ where: { id: user_id }, select: [...PublicUserProjection, ...((opts?.select as FindOptionsSelectByString<User>) || [])], - ...opts, + ...opts }); } @@ -241,7 +238,7 @@ export class User extends BaseClass { username, password, date_of_birth, - req, + req }: { username: string; password?: string; @@ -258,8 +255,8 @@ export class User extends BaseClass { throw FieldErrors({ username: { code: "USERNAME_TOO_MANY_USERS", - message: req?.t("auth:register.USERNAME_TOO_MANY_USERS"), - }, + message: req?.t("auth:register.USERNAME_TOO_MANY_USERS") + } }); } @@ -276,7 +273,7 @@ export class User extends BaseClass { email: email, data: { hash: password, - valid_tokens_since: new Date(), + valid_tokens_since: new Date() }, settings: { ...new UserSettings(), locale: language } }); @@ -319,6 +316,6 @@ export class UserFlags extends BitField { VERIFIED_BOT: BigInt(1) << BigInt(16), EARLY_VERIFIED_BOT_DEVELOPER: BigInt(1) << BigInt(17), CERTIFIED_MODERATOR: BigInt(1) << BigInt(18), - BOT_HTTP_INTERACTIONS: BigInt(1) << BigInt(19), + BOT_HTTP_INTERACTIONS: BigInt(1) << BigInt(19) }; } diff --git a/src/util/entities/UserGroup.ts b/src/util/entities/UserGroup.ts index 709b9d0b..08d68a4e 100644 --- a/src/util/entities/UserGroup.ts +++ b/src/util/entities/UserGroup.ts @@ -1,7 +1,6 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne } from "typeorm"; import { BaseClass } from "./BaseClass"; -import { Guild } from "./Guild"; import { User } from "./User"; @Entity("groups") @@ -11,11 +10,11 @@ export class UserGroup extends BaseClass { @Column() hoist: boolean; - + @JoinColumn({ name: "controller", referencedColumnName: "id" }) @ManyToOne(() => User) controller?: User; - + @Column() mentionable_by?: string; @@ -27,11 +26,10 @@ export class UserGroup extends BaseClass { @Column({ nullable: true }) icon: string; - + @Column({ nullable: true }) parent?: string; - - @Column({ type: "simple-array", nullable: true}) - associciations: string[]; + @Column({ type: "simple-array", nullable: true }) + associciations: string[]; } diff --git a/src/util/entities/UserSettings.ts b/src/util/entities/UserSettings.ts index ef6f95af..9fa18a4d 100644 --- a/src/util/entities/UserSettings.ts +++ b/src/util/entities/UserSettings.ts @@ -1,119 +1,119 @@ -import { Column, Entity, JoinColumn } from "typeorm"; +import { Column, Entity } from "typeorm"; import { BaseClassWithoutId, PrimaryIdColumn } from "."; @Entity("user_settings") export class UserSettings extends BaseClassWithoutId { - @PrimaryIdColumn() + @PrimaryIdColumn() id: string; @Column({ nullable: true }) - afk_timeout: number = 3600; - - @Column({ nullable: true }) - allow_accessibility_detection: boolean = true; - - @Column({ nullable: true }) - animate_emoji: boolean = true; - - @Column({ nullable: true }) - animate_stickers: number = 0; - - @Column({ nullable: true }) - contact_sync_enabled: boolean = false; - - @Column({ nullable: true }) - convert_emoticons: boolean = false; - - @Column({ nullable: true, type: "simple-json" }) - custom_status: CustomStatus | null = null; - - @Column({ nullable: true }) - default_guilds_restricted: boolean = false; - - @Column({ nullable: true }) - detect_platform_accounts: boolean = false; - - @Column({ nullable: true }) - developer_mode: boolean = true; - - @Column({ nullable: true }) - disable_games_tab: boolean = true; - - @Column({ nullable: true }) - enable_tts_command: boolean = false; - - @Column({ nullable: true }) - explicit_content_filter: number = 0; - - @Column({ nullable: true, type: "simple-json" }) - friend_source_flags: FriendSourceFlags = { all: true }; - - @Column({ nullable: true }) - gateway_connected: boolean = false; - - @Column({ nullable: true }) - gif_auto_play: boolean = false; - - @Column({ nullable: true, type: "simple-json" }) - guild_folders: GuildFolder[] = []; // every top guild is displayed as a "folder" - - @Column({ nullable: true, type: "simple-json" }) - guild_positions: string[] = []; // guild ids ordered by position - - @Column({ nullable: true }) - inline_attachment_media: boolean = true; - - @Column({ nullable: true }) - inline_embed_media: boolean = true; - - @Column({ nullable: true }) - locale: string = "en-US"; // en_US - - @Column({ nullable: true }) - message_display_compact: boolean = false; - - @Column({ nullable: true }) - native_phone_integration_enabled: boolean = true; - - @Column({ nullable: true }) - render_embeds: boolean = true; - - @Column({ nullable: true }) - render_reactions: boolean = true; - - @Column({ nullable: true, type: "simple-json" }) - restricted_guilds: string[] = []; - - @Column({ nullable: true }) - show_current_game: boolean = true; - - @Column({ nullable: true }) - status: "online" | "offline" | "dnd" | "idle" | "invisible" = "online"; - - @Column({ nullable: true }) - stream_notifications_enabled: boolean = false; - - @Column({ nullable: true }) - theme: "dark" | "white" = "dark"; // dark - - @Column({ nullable: true }) - timezone_offset: number = 0; // e.g -60 + afk_timeout: number = 3600; + + @Column({ nullable: true }) + allow_accessibility_detection: boolean = true; + + @Column({ nullable: true }) + animate_emoji: boolean = true; + + @Column({ nullable: true }) + animate_stickers: number = 0; + + @Column({ nullable: true }) + contact_sync_enabled: boolean = false; + + @Column({ nullable: true }) + convert_emoticons: boolean = false; + + @Column({ nullable: true, type: "simple-json" }) + custom_status: CustomStatus | null = null; + + @Column({ nullable: true }) + default_guilds_restricted: boolean = false; + + @Column({ nullable: true }) + detect_platform_accounts: boolean = false; + + @Column({ nullable: true }) + developer_mode: boolean = true; + + @Column({ nullable: true }) + disable_games_tab: boolean = true; + + @Column({ nullable: true }) + enable_tts_command: boolean = false; + + @Column({ nullable: true }) + explicit_content_filter: number = 0; + + @Column({ nullable: true, type: "simple-json" }) + friend_source_flags: FriendSourceFlags = { all: true }; + + @Column({ nullable: true }) + gateway_connected: boolean = false; + + @Column({ nullable: true }) + gif_auto_play: boolean = false; + + @Column({ nullable: true, type: "simple-json" }) + guild_folders: GuildFolder[] = []; // every top guild is displayed as a "folder" + + @Column({ nullable: true, type: "simple-json" }) + guild_positions: string[] = []; // guild ids ordered by position + + @Column({ nullable: true }) + inline_attachment_media: boolean = true; + + @Column({ nullable: true }) + inline_embed_media: boolean = true; + + @Column({ nullable: true }) + locale: string = "en-US"; // en_US + + @Column({ nullable: true }) + message_display_compact: boolean = false; + + @Column({ nullable: true }) + native_phone_integration_enabled: boolean = true; + + @Column({ nullable: true }) + render_embeds: boolean = true; + + @Column({ nullable: true }) + render_reactions: boolean = true; + + @Column({ nullable: true, type: "simple-json" }) + restricted_guilds: string[] = []; + + @Column({ nullable: true }) + show_current_game: boolean = true; + + @Column({ nullable: true }) + status: "online" | "offline" | "dnd" | "idle" | "invisible" = "online"; + + @Column({ nullable: true }) + stream_notifications_enabled: boolean = false; + + @Column({ nullable: true }) + theme: "dark" | "white" = "dark"; // dark + + @Column({ nullable: true }) + timezone_offset: number = 0; // e.g -60 } interface CustomStatus { - emoji_id?: string; - emoji_name?: string; - expires_at?: number; - text?: string; + emoji_id?: string; + emoji_name?: string; + expires_at?: number; + text?: string; } interface GuildFolder { - color: number; - guild_ids: string[]; - id: number; - name: string; + color: number; + guild_ids: string[]; + id: number; + name: string; } -interface FriendSourceFlags { - all: boolean -} \ No newline at end of file +interface FriendSourceFlags { + all: boolean; +} diff --git a/src/util/entities/VoiceState.ts b/src/util/entities/VoiceState.ts index 75748a01..baf2c687 100644 --- a/src/util/entities/VoiceState.ts +++ b/src/util/entities/VoiceState.ts @@ -2,8 +2,8 @@ import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Channel } from "./Channel"; import { Guild } from "./Guild"; -import { User } from "./User"; import { Member } from "./Member"; +import { User } from "./User"; //https://gist.github.com/vassjozsef/e482c65df6ee1facaace8b3c9ff66145#file-voice_state-ex @Entity("voice_states") @@ -14,7 +14,7 @@ export class VoiceState extends BaseClass { @JoinColumn({ name: "guild_id" }) @ManyToOne(() => Guild, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) guild?: Guild; @@ -24,7 +24,7 @@ export class VoiceState extends BaseClass { @JoinColumn({ name: "channel_id" }) @ManyToOne(() => Channel, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) channel: Channel; @@ -34,7 +34,7 @@ export class VoiceState extends BaseClass { @JoinColumn({ name: "user_id" }) @ManyToOne(() => User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) user: User; diff --git a/src/util/entities/Webhook.ts b/src/util/entities/Webhook.ts index 89538417..3d94ddb6 100644 --- a/src/util/entities/Webhook.ts +++ b/src/util/entities/Webhook.ts @@ -7,7 +7,7 @@ import { User } from "./User"; export enum WebhookType { Incoming = 1, - ChannelFollower = 2, + ChannelFollower = 2 } @Entity("webhooks") @@ -30,7 +30,7 @@ export class Webhook extends BaseClass { @JoinColumn({ name: "guild_id" }) @ManyToOne(() => Guild, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) guild: Guild; @@ -40,7 +40,7 @@ export class Webhook extends BaseClass { @JoinColumn({ name: "channel_id" }) @ManyToOne(() => Channel, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) channel: Channel; @@ -50,7 +50,7 @@ export class Webhook extends BaseClass { @JoinColumn({ name: "application_id" }) @ManyToOne(() => Application, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) application: Application; @@ -60,7 +60,7 @@ export class Webhook extends BaseClass { @JoinColumn({ name: "user_id" }) @ManyToOne(() => User, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) user: User; @@ -70,7 +70,7 @@ export class Webhook extends BaseClass { @JoinColumn({ name: "source_guild_id" }) @ManyToOne(() => Guild, { - onDelete: "CASCADE", + onDelete: "CASCADE" }) source_guild: Guild; } diff --git a/src/util/entities/index.ts b/src/util/entities/index.ts index c6f12022..2b91c2ba 100644 --- a/src/util/entities/index.ts +++ b/src/util/entities/index.ts @@ -1,10 +1,12 @@ export * from "./Application"; export * from "./Attachment"; export * from "./AuditLog"; +export * from "./BackupCodes"; export * from "./Ban"; export * from "./BaseClass"; export * from "./Categories"; export * from "./Channel"; +export * from "./ClientRelease"; export * from "./Config"; export * from "./ConnectedAccount"; export * from "./Emoji"; @@ -13,6 +15,7 @@ export * from "./Invite"; export * from "./Member"; export * from "./Message"; export * from "./Migration"; +export * from "./Note"; export * from "./RateLimit"; export * from "./ReadState"; export * from "./Recipient"; @@ -25,9 +28,6 @@ export * from "./Team"; export * from "./TeamMember"; export * from "./Template"; export * from "./User"; +export * from "./UserSettings"; export * from "./VoiceState"; export * from "./Webhook"; -export * from "./ClientRelease"; -export * from "./BackupCodes"; -export * from "./Note"; -export * from "./UserSettings"; |