diff options
Diffstat (limited to 'src/util')
43 files changed, 686 insertions, 119 deletions
diff --git a/src/util/config/types/RegionConfiguration.ts b/src/util/config/types/RegionConfiguration.ts index b4b8c4a3..418f46f1 100644 --- a/src/util/config/types/RegionConfiguration.ts +++ b/src/util/config/types/RegionConfiguration.ts @@ -7,7 +7,7 @@ export class RegionConfiguration { { id: "fosscord", name: "Fosscord", - endpoint: "127.0.0.1:3004", + endpoint: undefined, vip: false, custom: false, deprecated: false diff --git a/src/util/entities/Attachment.ts b/src/util/entities/Attachment.ts index 8392f415..395e695a 100644 --- a/src/util/entities/Attachment.ts +++ b/src/util/entities/Attachment.ts @@ -1,7 +1,9 @@ -import { BeforeRemove, Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import "reflect-metadata"; +import { BeforeRemove, Column, Entity, JoinColumn, ManyToOne, Relation, RelationId } from "typeorm"; import { URL } from "url"; import { deleteFile } from "../util/cdn"; import { BaseClass } from "./BaseClass"; +import { Message } from "./Message"; @Entity("attachments") export class Attachment extends BaseClass { @@ -34,7 +36,7 @@ export class Attachment extends BaseClass { @ManyToOne(() => require("./Message").Message, (message: import("./Message").Message) => message.attachments, { onDelete: "CASCADE" }) - message: import("./Message").Message; + message: Relation<Message>; @BeforeRemove() onDelete() { diff --git a/src/util/entities/AuditLog.ts b/src/util/entities/AuditLog.ts index 6f394f42..f8c65145 100644 --- a/src/util/entities/AuditLog.ts +++ b/src/util/entities/AuditLog.ts @@ -1,4 +1,5 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import "reflect-metadata"; +import { Column, Entity, JoinColumn, ManyToOne, Relation, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { ChannelPermissionOverwrite } from "./Channel"; import { User } from "./User"; @@ -97,7 +98,7 @@ export enum AuditLogEvents { export class AuditLog extends BaseClass { @JoinColumn({ name: "target_id" }) @ManyToOne(() => User) - target?: User; + target?: Relation<User>; @Column({ nullable: true }) @RelationId((auditlog: AuditLog) => auditlog.user) @@ -105,7 +106,7 @@ export class AuditLog extends BaseClass { @JoinColumn({ name: "user_id" }) @ManyToOne(() => User, (user: User) => user.id) - user: User; + user: Relation<User>; @Column({ type: "int" }) action_type: AuditLogEvents; diff --git a/src/util/entities/BackupCodes.ts b/src/util/entities/BackupCodes.ts index 503b1dbd..79b60a5e 100644 --- a/src/util/entities/BackupCodes.ts +++ b/src/util/entities/BackupCodes.ts @@ -6,7 +6,7 @@ import { User } from "./User"; export class BackupCode extends BaseClass { @JoinColumn({ name: "user_id" }) @ManyToOne(() => User, { onDelete: "CASCADE" }) - user: User; + user: Relation<User>; @Column() code: string; diff --git a/src/util/entities/Ban.ts b/src/util/entities/Ban.ts index 27c75278..e7daaf2a 100644 --- a/src/util/entities/Ban.ts +++ b/src/util/entities/Ban.ts @@ -1,4 +1,5 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import "reflect-metadata"; +import { Column, Entity, JoinColumn, ManyToOne, Relation, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; import { User } from "./User"; @@ -13,7 +14,7 @@ export class Ban extends BaseClass { @ManyToOne(() => User, { onDelete: "CASCADE" }) - user: User; + user: Relation<User>; @Column({ nullable: true }) @RelationId((ban: Ban) => ban.guild) @@ -23,7 +24,7 @@ export class Ban extends BaseClass { @ManyToOne(() => Guild, { onDelete: "CASCADE" }) - guild: Guild; + guild: Relation<Guild>; @Column({ nullable: true }) @RelationId((ban: Ban) => ban.executor) @@ -31,7 +32,7 @@ export class Ban extends BaseClass { @JoinColumn({ name: "executor_id" }) @ManyToOne(() => User) - executor: User; + executor: Relation<User>; @Column() ip: string; diff --git a/src/util/entities/Channel.ts b/src/util/entities/Channel.ts index b17fdba0..17a077ba 100644 --- a/src/util/entities/Channel.ts +++ b/src/util/entities/Channel.ts @@ -56,7 +56,7 @@ export class Channel extends BaseClass { cascade: true, orphanedRowAction: "delete" }) - recipients?: Recipient[]; + recipients?: Relation<Recipient[]>; @Column({ nullable: true }) last_message_id: string; @@ -69,7 +69,7 @@ export class Channel extends BaseClass { @ManyToOne(() => Guild, { onDelete: "CASCADE" }) - guild: Guild; + guild: Relation<Guild>; @Column({ nullable: true }) @RelationId((channel: Channel) => channel.parent) @@ -77,7 +77,7 @@ export class Channel extends BaseClass { @JoinColumn({ name: "parent_id" }) @ManyToOne(() => Channel) - parent?: Channel; + parent?: Relation<Channel>; // for group DMs and owned custom channel types @Column({ nullable: true }) @@ -86,7 +86,7 @@ export class Channel extends BaseClass { @JoinColumn({ name: "owner_id" }) @ManyToOne(() => User) - owner: User; + owner: Relation<User>; @Column({ nullable: true }) last_pin_timestamp?: number; @@ -113,16 +113,13 @@ export class Channel extends BaseClass { 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[]; + invites?: Relation<Invite[]>; @Column({ nullable: true }) retention_policy_id?: string; @@ -131,25 +128,25 @@ export class Channel extends BaseClass { cascade: true, orphanedRowAction: "delete" }) - messages?: Message[]; + messages?: Relation<Message[]>; @OneToMany(() => VoiceState, (voice_state: VoiceState) => voice_state.channel, { cascade: true, orphanedRowAction: "delete" }) - voice_states?: VoiceState[]; + voice_states?: Relation<VoiceState[]>; @OneToMany(() => ReadState, (read_state: ReadState) => read_state.channel, { cascade: true, orphanedRowAction: "delete" }) - read_states?: ReadState[]; + read_states?: Relation<ReadState[]>; @OneToMany(() => Webhook, (webhook: Webhook) => webhook.channel, { cascade: true, orphanedRowAction: "delete" }) - webhooks?: Webhook[]; + webhooks?: Relation<Webhook[]>; @Column({ nullable: true }) flags?: number = 0; diff --git a/src/util/entities/ConnectedAccount.ts b/src/util/entities/ConnectedAccount.ts index 018b3995..a74b7a43 100644 --- a/src/util/entities/ConnectedAccount.ts +++ b/src/util/entities/ConnectedAccount.ts @@ -1,4 +1,5 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import "reflect-metadata"; +import { Column, Entity, JoinColumn, ManyToOne, Relation, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { User } from "./User"; @@ -14,7 +15,7 @@ export class ConnectedAccount extends BaseClass { @ManyToOne(() => User, { onDelete: "CASCADE" }) - user: User; + user: Relation<User>; @Column({ select: false }) access_token: string; diff --git a/src/util/entities/Emoji.ts b/src/util/entities/Emoji.ts index a2552995..4a453afe 100644 --- a/src/util/entities/Emoji.ts +++ b/src/util/entities/Emoji.ts @@ -1,4 +1,5 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import "reflect-metadata"; +import { Column, Entity, JoinColumn, ManyToOne, Relation, RelationId } from "typeorm"; import { User } from "."; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; @@ -18,7 +19,7 @@ export class Emoji extends BaseClass { @ManyToOne(() => Guild, { onDelete: "CASCADE" }) - guild: Guild; + guild: Relation<Guild>; @Column({ nullable: true }) @RelationId((emoji: Emoji) => emoji.user) @@ -26,7 +27,7 @@ export class Emoji extends BaseClass { @JoinColumn({ name: "user_id" }) @ManyToOne(() => User) - user: User; + user: Relation<User>; @Column() managed: boolean; diff --git a/src/util/entities/Guild.ts b/src/util/entities/Guild.ts index 015c6d04..9efb7e74 100644 --- a/src/util/entities/Guild.ts +++ b/src/util/entities/Guild.ts @@ -41,8 +41,8 @@ export class Guild extends BaseClass { afk_channel_id?: string; @JoinColumn({ name: "afk_channel_id" }) - @ManyToOne(() => Channel) - afk_channel?: Channel; + @ManyToOne(() => Channel, { nullable: true }) + afk_channel?: Relation<Channel>; @Column({ nullable: true }) afk_timeout?: number = Config.get().defaults.guild.afkTimeout; @@ -57,7 +57,7 @@ export class Guild extends BaseClass { cascade: true, orphanedRowAction: "delete" }) - bans: Ban[]; + bans: Relation<Ban[]>; @Column({ nullable: true }) banner?: string; @@ -107,7 +107,7 @@ export class Guild extends BaseClass { orphanedRowAction: "delete", onDelete: "CASCADE" }) - members: Member[]; + members: Relation<Member[]>; @JoinColumn({ name: "role_ids" }) @OneToMany(() => Role, (role: Role) => role.guild, { @@ -115,14 +115,14 @@ export class Guild extends BaseClass { orphanedRowAction: "delete", onDelete: "CASCADE" }) - roles: Role[]; + roles: Relation<Role[]>; @JoinColumn({ name: "channel_ids" }) @OneToMany(() => Channel, (channel: Channel) => channel.guild, { cascade: true, orphanedRowAction: "delete" }) - channels: Channel[]; + channels: Relation<Channel[]>; @Column({ nullable: true }) @RelationId((guild: Guild) => guild.template) @@ -130,7 +130,7 @@ export class Guild extends BaseClass { @JoinColumn({ name: "template_id", referencedColumnName: "id" }) @ManyToOne(() => Template) - template: Template; + template: Relation<Template>; @JoinColumn({ name: "emoji_ids" }) @OneToMany(() => Emoji, (emoji: Emoji) => emoji.guild, { @@ -138,7 +138,7 @@ export class Guild extends BaseClass { orphanedRowAction: "delete", onDelete: "CASCADE" }) - emojis: Emoji[]; + emojis: Relation<Emoji[]>; @JoinColumn({ name: "sticker_ids" }) @OneToMany(() => Sticker, (sticker: Sticker) => sticker.guild, { @@ -146,7 +146,7 @@ export class Guild extends BaseClass { orphanedRowAction: "delete", onDelete: "CASCADE" }) - stickers: Sticker[]; + stickers: Relation<Sticker[]>; @JoinColumn({ name: "invite_ids" }) @OneToMany(() => Invite, (invite: Invite) => invite.guild, { @@ -154,7 +154,7 @@ export class Guild extends BaseClass { orphanedRowAction: "delete", onDelete: "CASCADE" }) - invites: Invite[]; + invites: Relation<Invite[]>; @JoinColumn({ name: "voice_state_ids" }) @OneToMany(() => VoiceState, (voicestate: VoiceState) => voicestate.guild, { @@ -162,7 +162,7 @@ export class Guild extends BaseClass { orphanedRowAction: "delete", onDelete: "CASCADE" }) - voice_states: VoiceState[]; + voice_states: Relation<VoiceState[]>; @JoinColumn({ name: "webhook_ids" }) @OneToMany(() => Webhook, (webhook: Webhook) => webhook.guild, { @@ -170,7 +170,7 @@ export class Guild extends BaseClass { orphanedRowAction: "delete", onDelete: "CASCADE" }) - webhooks: Webhook[]; + webhooks: Relation<Webhook[]>; @Column({ nullable: true }) mfa_level?: number; @@ -183,8 +183,8 @@ export class Guild extends BaseClass { owner_id?: string; // optional to allow for ownerless guilds @JoinColumn({ name: "owner_id", referencedColumnName: "id" }) - @ManyToOne(() => User) - owner?: User; // optional to allow for ownerless guilds + @ManyToOne(() => User, { nullable: true }) + owner?: Relation<User>; // optional to allow for ownerless guilds @Column({ nullable: true }) preferred_locale?: string; @@ -200,16 +200,16 @@ export class Guild extends BaseClass { public_updates_channel_id: string; @JoinColumn({ name: "public_updates_channel_id" }) - @ManyToOne(() => Channel) - public_updates_channel?: Channel; + @ManyToOne(() => Channel, { nullable: true }) + public_updates_channel?: Relation<Channel>; @Column({ nullable: true }) @RelationId((guild: Guild) => guild.rules_channel) rules_channel_id?: string; @JoinColumn({ name: "rules_channel_id" }) - @ManyToOne(() => Channel) - rules_channel?: string; + @ManyToOne(() => Channel, { nullable: true }) + rules_channel?: Relation<Channel>; @Column({ nullable: true }) region?: string; @@ -222,8 +222,8 @@ export class Guild extends BaseClass { system_channel_id?: string; @JoinColumn({ name: "system_channel_id" }) - @ManyToOne(() => Channel) - system_channel?: Channel; + @ManyToOne(() => Channel, { nullable: true }) + system_channel?: Relation<Channel>; @Column({ nullable: true }) system_channel_flags?: number; @@ -251,8 +251,8 @@ export class Guild extends BaseClass { widget_channel_id?: string; @JoinColumn({ name: "widget_channel_id" }) - @ManyToOne(() => Channel) - widget_channel?: Channel; + @ManyToOne(() => Channel, { nullable: true }) + widget_channel?: Relation<Channel>; @Column({ nullable: true }) widget_enabled?: boolean; @@ -333,13 +333,13 @@ export class Guild extends BaseClass { const ids = new Map(); - body.channels.forEach((x) => { - if (x.id) { - ids.set(x.id, Snowflake.generate()); + body.channels!.forEach((x) => { + if (x!.id) { + ids.set(x!.id, Snowflake.generate()); } }); - for (const channel of body.channels?.sort((a, b) => (a.parent_id ? 1 : -1))) { + for (const channel of body.channels!.sort((a, b) => (a.parent_id ? 1 : -1))) { let id = ids.get(channel.id) || Snowflake.generate(); let parent_id = ids.get(channel.parent_id); diff --git a/src/util/entities/Invite.ts b/src/util/entities/Invite.ts index f6ba85d7..383c932b 100644 --- a/src/util/entities/Invite.ts +++ b/src/util/entities/Invite.ts @@ -39,7 +39,7 @@ export class Invite extends BaseClassWithoutId { @ManyToOne(() => Guild, { onDelete: "CASCADE" }) - guild: Guild; + guild: Relation<Guild>; @Column({ nullable: true }) @RelationId((invite: Invite) => invite.channel) @@ -49,7 +49,7 @@ export class Invite extends BaseClassWithoutId { @ManyToOne(() => Channel, { onDelete: "CASCADE" }) - channel: Channel; + channel: Relation<Channel>; @Column({ nullable: true }) @RelationId((invite: Invite) => invite.inviter) @@ -69,7 +69,7 @@ export class Invite extends BaseClassWithoutId { @ManyToOne(() => User, { onDelete: "CASCADE" }) - target_user?: string; // could be used for "User specific invites" https://github.com/fosscord/fosscord/issues/62 + target_user?: Relation<User>; // could be used for "User specific invites" https://github.com/fosscord/fosscord/issues/62 @Column({ nullable: true }) target_user_type?: number; diff --git a/src/util/entities/Member.ts b/src/util/entities/Member.ts index 42a014d4..f5329481 100644 --- a/src/util/entities/Member.ts +++ b/src/util/entities/Member.ts @@ -40,7 +40,7 @@ export class Member extends BaseClassWithoutId { @ManyToOne(() => User, { onDelete: "CASCADE" }) - user: User; + user: Relation<User>; @Column() @RelationId((member: Member) => member.guild) @@ -50,7 +50,7 @@ export class Member extends BaseClassWithoutId { @ManyToOne(() => Guild, { onDelete: "CASCADE" }) - guild: Guild; + guild: Relation<Guild>; @Column({ nullable: true }) nick?: string; @@ -64,7 +64,7 @@ export class Member extends BaseClassWithoutId { } }) @ManyToMany(() => Role, { cascade: true }) - roles: Role[]; + roles: Relation<Role[]>; @Column() joined_at: Date; @@ -106,7 +106,7 @@ export class Member extends BaseClassWithoutId { } static async removeFromGuild(user_id: string, guild_id: string) { - const guild = await Guild.findOneOrFail({ select: ["owner_id", "member_count"], where: { id: guild_id } }); + const guild = await require("./Guild").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"] }); @@ -224,7 +224,7 @@ export class Member extends BaseClassWithoutId { throw new HTTPError(`You are at the ${maxGuilds} server limit.`, 403); } - const guild = await Guild.findOneOrFail({ + const guild = await require("./Guild").Guild.findOneOrFail({ where: { id: guild_id }, diff --git a/src/util/entities/Message.ts b/src/util/entities/Message.ts index 8122b532..2b5e6f86 100644 --- a/src/util/entities/Message.ts +++ b/src/util/entities/Message.ts @@ -51,7 +51,7 @@ export class Message extends BaseClass { @ManyToOne(() => Channel, { onDelete: "CASCADE" }) - channel: Channel; + channel: Relation<Channel>; @Column({ nullable: true }) @RelationId((message: Message) => message.guild) @@ -61,7 +61,7 @@ export class Message extends BaseClass { @ManyToOne(() => Guild, { onDelete: "CASCADE" }) - guild?: Guild; + guild?: Relation<Guild>; @Column({ nullable: true }) @RelationId((message: Message) => message.author) @@ -72,7 +72,7 @@ export class Message extends BaseClass { @ManyToOne(() => User, { onDelete: "CASCADE" }) - author?: User; + author?: Relation<User>; @Column({ nullable: true }) @RelationId((message: Message) => message.member) @@ -82,7 +82,7 @@ export class Message extends BaseClass { @ManyToOne(() => User, { onDelete: "CASCADE" }) - member?: Member; + member?: Relation<Member>; @Column({ nullable: true }) @RelationId((message: Message) => message.webhook) @@ -90,7 +90,7 @@ export class Message extends BaseClass { @JoinColumn({ name: "webhook_id" }) @ManyToOne(() => Webhook) - webhook?: Webhook; + webhook?: Relation<Webhook>; @Column({ nullable: true }) @RelationId((message: Message) => message.application) @@ -98,7 +98,7 @@ export class Message extends BaseClass { @JoinColumn({ name: "application_id" }) @ManyToOne(() => Application) - application?: Application; + application?: Relation<Application>; @Column({ nullable: true }) content?: string; @@ -118,25 +118,25 @@ export class Message extends BaseClass { @JoinTable({ name: "message_user_mentions" }) @ManyToMany(() => User) - mentions: User[]; + mentions: Relation<User[]>; @JoinTable({ name: "message_role_mentions" }) @ManyToMany(() => Role) - mention_roles: Role[]; + mention_roles: Relation<Role[]>; @JoinTable({ name: "message_channel_mentions" }) @ManyToMany(() => Channel) - mention_channels: Channel[]; + mention_channels: Relation<Channel[]>; @JoinTable({ name: "message_stickers" }) @ManyToMany(() => Sticker, { cascade: true, onDelete: "CASCADE" }) - sticker_items?: Sticker[]; + sticker_items?: Relation<Sticker[]>; @OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, { cascade: true, orphanedRowAction: "delete" }) - attachments?: Attachment[]; + attachments?: Relation<Attachment[]>; @Column({ type: "simple-json" }) embeds: Embed[]; @@ -170,7 +170,7 @@ export class Message extends BaseClass { @JoinColumn({ name: "message_reference_id" }) @ManyToOne(() => Message) - referenced_message?: Message; + referenced_message?: Relation<Message>; @Column({ type: "simple-json", nullable: true }) interaction?: { diff --git a/src/util/entities/Migration.ts b/src/util/entities/Migration.ts index 626ec429..07fd25a6 100644 --- a/src/util/entities/Migration.ts +++ b/src/util/entities/Migration.ts @@ -1,3 +1,4 @@ +import "reflect-metadata"; import { Column, Entity, ObjectIdColumn, PrimaryGeneratedColumn } from "typeorm"; import { BaseClassWithoutId } from "."; diff --git a/src/util/entities/Note.ts b/src/util/entities/Note.ts index b3ac45ee..d6eefd63 100644 --- a/src/util/entities/Note.ts +++ b/src/util/entities/Note.ts @@ -1,4 +1,5 @@ -import { Column, Entity, JoinColumn, ManyToOne, Unique } from "typeorm"; +import "reflect-metadata"; +import { Column, Entity, JoinColumn, ManyToOne, Relation, Unique } from "typeorm"; import { BaseClass } from "./BaseClass"; import { User } from "./User"; @@ -7,11 +8,11 @@ import { User } from "./User"; export class Note extends BaseClass { @JoinColumn({ name: "owner_id" }) @ManyToOne(() => User, { onDelete: "CASCADE" }) - owner: User; + owner: Relation<User>; @JoinColumn({ name: "target_id" }) @ManyToOne(() => User, { onDelete: "CASCADE" }) - target: User; + target: Relation<User>; @Column() content: string; diff --git a/src/util/entities/RateLimit.ts b/src/util/entities/RateLimit.ts index f5916f6b..1f6c359c 100644 --- a/src/util/entities/RateLimit.ts +++ b/src/util/entities/RateLimit.ts @@ -1,3 +1,4 @@ +import "reflect-metadata"; import { Column, Entity } from "typeorm"; import { BaseClass } from "./BaseClass"; diff --git a/src/util/entities/ReadState.ts b/src/util/entities/ReadState.ts index 77d2c08a..462a06f9 100644 --- a/src/util/entities/ReadState.ts +++ b/src/util/entities/ReadState.ts @@ -1,4 +1,5 @@ -import { Column, Entity, Index, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import "reflect-metadata"; +import { Column, Entity, Index, JoinColumn, ManyToOne, Relation, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Channel } from "./Channel"; import { User } from "./User"; @@ -18,7 +19,7 @@ export class ReadState extends BaseClass { @ManyToOne(() => Channel, { onDelete: "CASCADE" }) - channel: Channel; + channel: Relation<Channel>; @Column() @RelationId((read_state: ReadState) => read_state.user) @@ -28,7 +29,7 @@ export class ReadState extends BaseClass { @ManyToOne(() => User, { onDelete: "CASCADE" }) - user: User; + user: Relation<User>; // fully read marker @Column({ nullable: true }) diff --git a/src/util/entities/Recipient.ts b/src/util/entities/Recipient.ts index fc9e629b..a1ae1e17 100644 --- a/src/util/entities/Recipient.ts +++ b/src/util/entities/Recipient.ts @@ -1,5 +1,8 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import "reflect-metadata"; +import { Column, Entity, JoinColumn, ManyToOne, Relation, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; +import { Channel } from "./Channel"; +import { User } from "./User"; @Entity("recipients") export class Recipient extends BaseClass { @@ -11,7 +14,7 @@ export class Recipient extends BaseClass { @ManyToOne(() => require("./Channel").Channel, { onDelete: "CASCADE" }) - channel: import("./Channel").Channel; + channel: Relation<Channel>; @Column() @RelationId((recipient: Recipient) => recipient.user) @@ -21,7 +24,7 @@ export class Recipient extends BaseClass { @ManyToOne(() => require("./User").User, { onDelete: "CASCADE" }) - user: import("./User").User; + user: Relation<User>; @Column({ default: false }) closed: boolean; diff --git a/src/util/entities/Relationship.ts b/src/util/entities/Relationship.ts index b55d9e64..c4525125 100644 --- a/src/util/entities/Relationship.ts +++ b/src/util/entities/Relationship.ts @@ -1,4 +1,5 @@ -import { Column, Entity, Index, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import "reflect-metadata"; +import { Column, Entity, Index, JoinColumn, ManyToOne, Relation, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { User } from "./User"; @@ -20,7 +21,7 @@ export class Relationship extends BaseClass { @ManyToOne(() => User, { onDelete: "CASCADE" }) - from: User; + from: Relation<User>; @Column({}) @RelationId((relationship: Relationship) => relationship.to) @@ -30,7 +31,7 @@ export class Relationship extends BaseClass { @ManyToOne(() => User, { onDelete: "CASCADE" }) - to: User; + to: Relation<User>; @Column({ nullable: true }) nickname?: string; diff --git a/src/util/entities/Role.ts b/src/util/entities/Role.ts index b1fd9bb1..1c5e19cf 100644 --- a/src/util/entities/Role.ts +++ b/src/util/entities/Role.ts @@ -1,4 +1,5 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import "reflect-metadata"; +import { Column, Entity, JoinColumn, ManyToOne, Relation, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; @@ -13,7 +14,7 @@ export class Role extends BaseClass { @ManyToOne(() => Guild, { onDelete: "CASCADE" }) - guild: Guild; + guild: Relation<Guild>; @Column() color: number; diff --git a/src/util/entities/Session.ts b/src/util/entities/Session.ts index 0cb4c309..bc9e6906 100644 --- a/src/util/entities/Session.ts +++ b/src/util/entities/Session.ts @@ -16,7 +16,7 @@ export class Session extends BaseClass { @ManyToOne(() => User, { onDelete: "CASCADE" }) - user: User; + user: Relation<User>; //TODO check, should be 32 char long hex string @Column({ nullable: false, select: false }) diff --git a/src/util/entities/Sticker.ts b/src/util/entities/Sticker.ts index 69836e62..0879e064 100644 --- a/src/util/entities/Sticker.ts +++ b/src/util/entities/Sticker.ts @@ -34,11 +34,11 @@ export class Sticker extends BaseClass { pack_id?: string; @JoinColumn({ name: "pack_id" }) - @ManyToOne(() => require("./StickerPack").StickerPack, { + @ManyToOne(() => StickerPack, { onDelete: "CASCADE", nullable: true }) - pack: import("./StickerPack").StickerPack; + pack: Relation<StickerPack>; @Column({ nullable: true }) guild_id?: string; @@ -47,7 +47,7 @@ export class Sticker extends BaseClass { @ManyToOne(() => Guild, { onDelete: "CASCADE" }) - guild?: Guild; + guild?: Relation<Guild>; @Column({ nullable: true }) user_id?: string; @@ -56,7 +56,7 @@ export class Sticker extends BaseClass { @ManyToOne(() => User, { onDelete: "CASCADE" }) - user?: User; + user?: Relation<User>; @Column({ type: "int" }) type: StickerType; diff --git a/src/util/entities/StickerPack.ts b/src/util/entities/StickerPack.ts index 4619af34..ca8b4cad 100644 --- a/src/util/entities/StickerPack.ts +++ b/src/util/entities/StickerPack.ts @@ -17,7 +17,7 @@ export class StickerPack extends BaseClass { cascade: true, orphanedRowAction: "delete" }) - stickers: Sticker[]; + stickers: Relation<Sticker[]>; // sku_id: string @@ -27,5 +27,5 @@ export class StickerPack extends BaseClass { @ManyToOne(() => Sticker, { nullable: true }) @JoinColumn() - cover_sticker?: Sticker; + cover_sticker?: Relation<Sticker>; } diff --git a/src/util/entities/Team.ts b/src/util/entities/Team.ts index 1d2d7002..48657930 100644 --- a/src/util/entities/Team.ts +++ b/src/util/entities/Team.ts @@ -12,7 +12,7 @@ export class Team extends BaseClass { @OneToMany(() => TeamMember, (member: TeamMember) => member.team, { orphanedRowAction: "delete" }) - members: TeamMember[]; + members: Relation<TeamMember[]>; @Column() name: string; @@ -23,5 +23,5 @@ export class Team extends BaseClass { @JoinColumn({ name: "owner_user_id" }) @ManyToOne(() => User) - owner_user: User; + owner_user: Relation<User>; } diff --git a/src/util/entities/TeamMember.ts b/src/util/entities/TeamMember.ts index d11ebf95..e2950c65 100644 --- a/src/util/entities/TeamMember.ts +++ b/src/util/entities/TeamMember.ts @@ -1,5 +1,7 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import "reflect-metadata"; +import { Column, Entity, JoinColumn, ManyToOne, Relation, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; +import { Team } from "./Team"; import { User } from "./User"; export enum TeamMemberState { @@ -23,7 +25,7 @@ export class TeamMember extends BaseClass { @ManyToOne(() => require("./Team").Team, (team: import("./Team").Team) => team.members, { onDelete: "CASCADE" }) - team: import("./Team").Team; + team: Relation<Team>; @Column({ nullable: true }) @RelationId((member: TeamMember) => member.user) @@ -33,5 +35,5 @@ export class TeamMember extends BaseClass { @ManyToOne(() => User, { onDelete: "CASCADE" }) - user: User; + user: Relation<User>; } diff --git a/src/util/entities/Template.ts b/src/util/entities/Template.ts index 1d952283..bcd2b259 100644 --- a/src/util/entities/Template.ts +++ b/src/util/entities/Template.ts @@ -1,4 +1,5 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import "reflect-metadata"; +import { Column, Entity, JoinColumn, ManyToOne, Relation, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; import { User } from "./User"; @@ -23,7 +24,7 @@ export class Template extends BaseClass { @JoinColumn({ name: "creator_id" }) @ManyToOne(() => User) - creator: User; + creator: Relation<User>; @Column() created_at: Date; @@ -37,7 +38,7 @@ export class Template extends BaseClass { @JoinColumn({ name: "source_guild_id" }) @ManyToOne(() => Guild) - source_guild: Guild; + source_guild: Relation<Guild>; @Column({ type: "simple-json" }) serialized_source_guild: Guild; diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts index 1237b676..760ef9c7 100644 --- a/src/util/entities/User.ts +++ b/src/util/entities/User.ts @@ -141,21 +141,21 @@ export class User extends BaseClass { rights: string = Config.get().register.defaultRights; // Rights @OneToMany(() => Session, (session: Session) => session.user) - sessions: Session[]; + sessions: Relation<Session[]>; @JoinColumn({ name: "relationship_ids" }) @OneToMany(() => Relationship, (relationship: Relationship) => relationship.from, { cascade: true, orphanedRowAction: "delete" }) - relationships: Relationship[]; + relationships: Relation<Relationship[]>; @JoinColumn({ name: "connected_account_ids" }) @OneToMany(() => ConnectedAccount, (account: ConnectedAccount) => account.user, { cascade: true, orphanedRowAction: "delete" }) - connected_accounts: ConnectedAccount[]; + connected_accounts: Relation<ConnectedAccount[]>; @Column({ type: "simple-json", select: false }) data: { @@ -264,6 +264,8 @@ export class User extends BaseClass { // appearently discord doesn't save the date of birth and just calculate if nsfw is allowed // if nsfw_allowed is null/undefined it'll require date_of_birth to set it to true/false const language = req?.language === "en" ? "en-US" : req?.language || "en-US"; + const settings = new UserSettings(); + settings.locale = language; const user = OrmUtils.mergeDeep(new User(), { //required: @@ -280,11 +282,14 @@ export class User extends BaseClass { //await (user.settings as UserSettings).save(); await user.save(); + await user.settings.save(); setImmediate(async () => { if (Config.get().guild.autoJoin.enabled) { for (const guild of Config.get().guild.autoJoin.guilds || []) { - await Member.addToGuild(user.id, guild).catch((e) => {}); + await require("./Member") + .Member.addToGuild(user.id, guild) + .catch((e: any) => {}); } } }); diff --git a/src/util/entities/VoiceState.ts b/src/util/entities/VoiceState.ts index baf2c687..55fac313 100644 --- a/src/util/entities/VoiceState.ts +++ b/src/util/entities/VoiceState.ts @@ -1,4 +1,5 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import "reflect-metadata"; +import { Column, Entity, JoinColumn, ManyToOne, Relation, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Channel } from "./Channel"; import { Guild } from "./Guild"; @@ -16,7 +17,7 @@ export class VoiceState extends BaseClass { @ManyToOne(() => Guild, { onDelete: "CASCADE" }) - guild?: Guild; + guild?: Relation<Guild>; @Column({ nullable: true }) @RelationId((voice_state: VoiceState) => voice_state.channel) @@ -26,7 +27,7 @@ export class VoiceState extends BaseClass { @ManyToOne(() => Channel, { onDelete: "CASCADE" }) - channel: Channel; + channel: Relation<Channel>; @Column({ nullable: true }) @RelationId((voice_state: VoiceState) => voice_state.user) @@ -36,20 +37,20 @@ export class VoiceState extends BaseClass { @ManyToOne(() => User, { onDelete: "CASCADE" }) - user: User; + user: Relation<User>; // @JoinColumn([{ name: "user_id", referencedColumnName: "id" },{ name: "guild_id", referencedColumnName: "guild_id" }]) // @ManyToOne(() => Member, { // onDelete: "CASCADE", // }) //TODO find a way to make it work without breaking Guild.voice_states - member: Member; + member: Relation<Member>; @Column() session_id: string; @Column({ nullable: true }) - token: string; + token?: string; @Column() deaf: boolean; diff --git a/src/util/entities/Webhook.ts b/src/util/entities/Webhook.ts index 3d94ddb6..42f74fae 100644 --- a/src/util/entities/Webhook.ts +++ b/src/util/entities/Webhook.ts @@ -1,4 +1,5 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import "reflect-metadata"; +import { Column, Entity, JoinColumn, ManyToOne, Relation, RelationId } from "typeorm"; import { Application } from "./Application"; import { BaseClass } from "./BaseClass"; import { Channel } from "./Channel"; @@ -32,7 +33,7 @@ export class Webhook extends BaseClass { @ManyToOne(() => Guild, { onDelete: "CASCADE" }) - guild: Guild; + guild: Relation<Guild>; @Column({ nullable: true }) @RelationId((webhook: Webhook) => webhook.channel) @@ -42,7 +43,7 @@ export class Webhook extends BaseClass { @ManyToOne(() => Channel, { onDelete: "CASCADE" }) - channel: Channel; + channel: Relation<Channel>; @Column({ nullable: true }) @RelationId((webhook: Webhook) => webhook.application) @@ -52,7 +53,7 @@ export class Webhook extends BaseClass { @ManyToOne(() => Application, { onDelete: "CASCADE" }) - application: Application; + application: Relation<Application>; @Column({ nullable: true }) @RelationId((webhook: Webhook) => webhook.user) @@ -62,7 +63,7 @@ export class Webhook extends BaseClass { @ManyToOne(() => User, { onDelete: "CASCADE" }) - user: User; + user: Relation<User>; @Column({ nullable: true }) @RelationId((webhook: Webhook) => webhook.guild) @@ -72,5 +73,5 @@ export class Webhook extends BaseClass { @ManyToOne(() => Guild, { onDelete: "CASCADE" }) - source_guild: Guild; + source_guild: Relation<Guild>; } diff --git a/src/util/migrations/mariadb/1660258393551-CodeCleanup3.ts b/src/util/migrations/mariadb/1660258393551-CodeCleanup3.ts new file mode 100644 index 00000000..8a6126c7 --- /dev/null +++ b/src/util/migrations/mariadb/1660258393551-CodeCleanup3.ts @@ -0,0 +1,231 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class CodeCleanup31660258393551 implements MigrationInterface { + name = "CodeCleanup31660258393551"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(` + ALTER TABLE \`applications\` DROP FOREIGN KEY \`FK_2ce5a55796fe4c2f77ece57a647\` + `); + await queryRunner.query(` + DROP INDEX \`REL_2ce5a55796fe4c2f77ece57a64\` ON \`applications\` + `); + await queryRunner.query(` + CREATE TABLE \`user_settings\` ( + \`id\` varchar(255) NOT NULL, + \`afk_timeout\` int NULL, + \`allow_accessibility_detection\` tinyint NULL, + \`animate_emoji\` tinyint NULL, + \`animate_stickers\` int NULL, + \`contact_sync_enabled\` tinyint NULL, + \`convert_emoticons\` tinyint NULL, + \`custom_status\` text NULL, + \`default_guilds_restricted\` tinyint NULL, + \`detect_platform_accounts\` tinyint NULL, + \`developer_mode\` tinyint NULL, + \`disable_games_tab\` tinyint NULL, + \`enable_tts_command\` tinyint NULL, + \`explicit_content_filter\` int NULL, + \`friend_source_flags\` text NULL, + \`gateway_connected\` tinyint NULL, + \`gif_auto_play\` tinyint NULL, + \`guild_folders\` text NULL, + \`guild_positions\` text NULL, + \`inline_attachment_media\` tinyint NULL, + \`inline_embed_media\` tinyint NULL, + \`locale\` varchar(255) NULL, + \`message_display_compact\` tinyint NULL, + \`native_phone_integration_enabled\` tinyint NULL, + \`render_embeds\` tinyint NULL, + \`render_reactions\` tinyint NULL, + \`restricted_guilds\` text NULL, + \`show_current_game\` tinyint NULL, + \`status\` varchar(255) NULL, + \`stream_notifications_enabled\` tinyint NULL, + \`theme\` varchar(255) NULL, + \`timezone_offset\` int NULL, + PRIMARY KEY (\`id\`) + ) ENGINE = InnoDB + `); + await queryRunner.query(` + ALTER TABLE \`users\` DROP COLUMN \`settings\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`type\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`hook\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`redirect_uris\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`rpc_application_state\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`store_application_state\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`verification_state\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`interactions_endpoint_url\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`integration_public\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`integration_require_code_grant\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`discoverability_state\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`discovery_eligibility_flags\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`tags\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`install_params\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`bot_user_id\` + `); + await queryRunner.query(` + ALTER TABLE \`guilds\` + ADD \`premium_progress_bar_enabled\` tinyint NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`rpc_origins\` text NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`primary_sku_id\` varchar(255) NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`slug\` varchar(255) NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`guild_id\` varchar(255) NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` CHANGE \`description\` \`description\` varchar(255) NOT NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`flags\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`flags\` varchar(255) NOT NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD CONSTRAINT \`FK_e5bf78cdbbe9ba91062d74c5aba\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION + `); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(` + ALTER TABLE \`applications\` DROP FOREIGN KEY \`FK_e5bf78cdbbe9ba91062d74c5aba\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`flags\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`flags\` int NOT NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` CHANGE \`description\` \`description\` varchar(255) NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`guild_id\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`slug\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`primary_sku_id\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` DROP COLUMN \`rpc_origins\` + `); + await queryRunner.query(` + ALTER TABLE \`guilds\` DROP COLUMN \`premium_progress_bar_enabled\` + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`bot_user_id\` varchar(255) NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`install_params\` text NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`tags\` text NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`discovery_eligibility_flags\` int NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`discoverability_state\` int NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`integration_require_code_grant\` tinyint NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`integration_public\` tinyint NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`interactions_endpoint_url\` varchar(255) NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`verification_state\` int NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`store_application_state\` int NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`rpc_application_state\` int NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`redirect_uris\` text NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`hook\` tinyint NOT NULL + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD \`type\` text NULL + `); + await queryRunner.query(` + ALTER TABLE \`users\` + ADD \`settings\` text NOT NULL + `); + await queryRunner.query(` + DROP TABLE \`user_settings\` + `); + await queryRunner.query(` + CREATE UNIQUE INDEX \`REL_2ce5a55796fe4c2f77ece57a64\` ON \`applications\` (\`bot_user_id\`) + `); + await queryRunner.query(` + ALTER TABLE \`applications\` + ADD CONSTRAINT \`FK_2ce5a55796fe4c2f77ece57a647\` FOREIGN KEY (\`bot_user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION + `); + } +} diff --git a/src/util/migrations/mariadb/1660260587556-CodeCleanup4.ts b/src/util/migrations/mariadb/1660260587556-CodeCleanup4.ts new file mode 100644 index 00000000..aa750f17 --- /dev/null +++ b/src/util/migrations/mariadb/1660260587556-CodeCleanup4.ts @@ -0,0 +1,38 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class CodeCleanup41660260587556 implements MigrationInterface { + name = "CodeCleanup41660260587556"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(` + ALTER TABLE \`users\` + ADD \`settingsId\` varchar(255) NULL + `); + await queryRunner.query(` + ALTER TABLE \`users\` + ADD UNIQUE INDEX \`IDX_76ba283779c8441fd5ff819c8c\` (\`settingsId\`) + `); + await queryRunner.query(` + CREATE UNIQUE INDEX \`REL_76ba283779c8441fd5ff819c8c\` ON \`users\` (\`settingsId\`) + `); + await queryRunner.query(` + ALTER TABLE \`users\` + ADD CONSTRAINT \`FK_76ba283779c8441fd5ff819c8cf\` FOREIGN KEY (\`settingsId\`) REFERENCES \`user_settings\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION + `); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(` + ALTER TABLE \`users\` DROP FOREIGN KEY \`FK_76ba283779c8441fd5ff819c8cf\` + `); + await queryRunner.query(` + DROP INDEX \`REL_76ba283779c8441fd5ff819c8c\` ON \`users\` + `); + await queryRunner.query(` + ALTER TABLE \`users\` DROP INDEX \`IDX_76ba283779c8441fd5ff819c8c\` + `); + await queryRunner.query(` + ALTER TABLE \`users\` DROP COLUMN \`settingsId\` + `); + } +} diff --git a/src/util/migrations/mariadb/1660265930624-CodeCleanup5.ts b/src/util/migrations/mariadb/1660265930624-CodeCleanup5.ts new file mode 100644 index 00000000..6629d4d4 --- /dev/null +++ b/src/util/migrations/mariadb/1660265930624-CodeCleanup5.ts @@ -0,0 +1,52 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class CodeCleanup51660265930624 implements MigrationInterface { + name = "CodeCleanup51660265930624"; + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(` + ALTER TABLE \`users\` + ADD \`settingsId\` varchar(255) NULL + `); + await queryRunner.query(` + ALTER TABLE \`users\` + ADD UNIQUE INDEX \`IDX_76ba283779c8441fd5ff819c8c\` (\`settingsId\`) + `); + await queryRunner.query(` + ALTER TABLE \`channels\` + ADD \`flags\` int NULL + `); + await queryRunner.query(` + ALTER TABLE \`channels\` + ADD \`default_thread_rate_limit_per_user\` int NULL + `); + await queryRunner.query(` + CREATE UNIQUE INDEX \`REL_76ba283779c8441fd5ff819c8c\` ON \`users\` (\`settingsId\`) + `); + await queryRunner.query(` + ALTER TABLE \`users\` + ADD CONSTRAINT \`FK_76ba283779c8441fd5ff819c8cf\` FOREIGN KEY (\`settingsId\`) REFERENCES \`user_settings\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION + `); + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(` + ALTER TABLE \`users\` DROP FOREIGN KEY \`FK_76ba283779c8441fd5ff819c8cf\` + `); + await queryRunner.query(` + DROP INDEX \`REL_76ba283779c8441fd5ff819c8c\` ON \`users\` + `); + await queryRunner.query(` + ALTER TABLE \`channels\` DROP COLUMN \`default_thread_rate_limit_per_user\` + `); + await queryRunner.query(` + ALTER TABLE \`channels\` DROP COLUMN \`flags\` + `); + await queryRunner.query(` + ALTER TABLE \`users\` DROP INDEX \`IDX_76ba283779c8441fd5ff819c8c\` + `); + await queryRunner.query(` + ALTER TABLE \`users\` DROP COLUMN \`settingsId\` + `); + } +} diff --git a/src/util/plugin/Plugin.ts b/src/util/plugin/Plugin.ts new file mode 100644 index 00000000..ee4fd95c --- /dev/null +++ b/src/util/plugin/Plugin.ts @@ -0,0 +1,13 @@ +import { TypedEventEmitter } from "@fosscord/util"; +import EventEmitter from "events"; + +type PluginEvents = { + error: (error: Error | unknown) => void; + loaded: () => void; +}; + +export class Plugin extends (EventEmitter as new () => TypedEventEmitter<PluginEvents>) { + async init() { + // insert default config into database? + } +} diff --git a/src/util/plugin/PluginLoader.ts b/src/util/plugin/PluginLoader.ts new file mode 100644 index 00000000..000f3345 --- /dev/null +++ b/src/util/plugin/PluginLoader.ts @@ -0,0 +1,39 @@ +import fs from "fs"; +import path from "path"; +import { Plugin, PluginManifest } from "./"; + +const root = process.env.PLUGIN_LOCATION || "../plugins"; + +let pluginsLoaded = false; +export class PluginLoader { + public static loadPlugins() { + console.log(`Plugin root directory: ${path.resolve(root)}`); + const dirs = fs.readdirSync(root).filter((x) => { + try { + fs.readdirSync(path.join(root, x)); + return true; + } catch (e) { + return false; + } + }); + console.log(dirs); + dirs.forEach(async (x) => { + let modPath = path.resolve(path.join(root, x)); + console.log(`Trying to load plugin: ${modPath}`); + const manifest = require(path.join(modPath, "plugin.json")) as PluginManifest; + console.log( + `Plugin info: ${manifest.name} (${manifest.id}), written by ${manifest.authors}, available at ${manifest.repository}` + ); + const module_ = require(path.join(modPath, "dist", "index.js")) as Plugin; + try { + await module_.init(); + module_.emit("loaded"); + } catch (error) { + module_.emit("error", error); + } + }); + + // + //module_.pluginPath = + } +} diff --git a/src/util/plugin/PluginManifest.ts b/src/util/plugin/PluginManifest.ts new file mode 100644 index 00000000..d940f2c8 --- /dev/null +++ b/src/util/plugin/PluginManifest.ts @@ -0,0 +1,9 @@ +export class PluginManifest { + id: string; + name: string; + authors: string[]; + repository: string; + license: string; + version: string; // semver + versionCode: number; // integer +} diff --git a/src/util/plugin/index.ts b/src/util/plugin/index.ts new file mode 100644 index 00000000..c4c0c2ac --- /dev/null +++ b/src/util/plugin/index.ts @@ -0,0 +1,3 @@ +export * from "./Plugin"; +export * from "./PluginLoader"; +export * from "./PluginManifest"; diff --git a/src/util/schemas/SelectProtocolSchema.ts b/src/util/schemas/SelectProtocolSchema.ts new file mode 100644 index 00000000..0ba0c23b --- /dev/null +++ b/src/util/schemas/SelectProtocolSchema.ts @@ -0,0 +1,19 @@ +export interface SelectProtocolSchema { + protocol: "webrtc" | "udp"; + data: + | string + | { + address: string; + port: number; + mode: string; + }; + sdp?: string; + codecs?: { + name: "opus" | "VP8" | "VP9" | "H264"; + type: "audio" | "video"; + priority: number; + payload_type: number; + rtx_payload_type?: number | null; + }[]; + rtc_connection_id?: string; // uuid +} diff --git a/src/util/schemas/Validator.ts b/src/util/schemas/Validator.ts new file mode 100644 index 00000000..d506e14c --- /dev/null +++ b/src/util/schemas/Validator.ts @@ -0,0 +1,54 @@ +import Ajv from "ajv"; +import addFormats from "ajv-formats"; +import fs from "fs"; +import path from "path"; + +const SchemaPath = path.join(__dirname, "..", "..", "..", "assets", "schemas.json"); +const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" })); + +export const ajv = new Ajv({ + allErrors: true, + parseDate: true, + allowDate: true, + schemas, + coerceTypes: true, + messages: true, + strict: true, + strictRequired: true +}); + +addFormats(ajv); + +export function validateSchema<G>(schema: string, data: G): G { + const valid = ajv.validate(schema, normalizeBody(data)); + if (!valid) throw ajv.errors; + return data; +} + +// Normalizer is introduced to workaround https://github.com/ajv-validator/ajv/issues/1287 +// this removes null values as ajv doesn't treat them as undefined +// normalizeBody allows to handle circular structures without issues +// taken from https://github.com/serverless/serverless/blob/master/lib/classes/ConfigSchemaHandler/index.js#L30 (MIT license) +export const normalizeBody = (body: any = {}) => { + const normalizedObjectsSet = new WeakSet(); + const normalizeObject = (object: any) => { + if (normalizedObjectsSet.has(object)) return; + normalizedObjectsSet.add(object); + if (Array.isArray(object)) { + for (const [index, value] of object.entries()) { + if (typeof value === "object") normalizeObject(value); + } + } else { + for (const [key, value] of Object.entries(object)) { + if (value == null) { + if (key === "icon" || key === "avatar" || key === "banner" || key === "splash" || key === "discovery_splash") continue; + delete object[key]; + } else if (typeof value === "object") { + normalizeObject(value); + } + } + } + }; + normalizeObject(body); + return body; +}; diff --git a/src/util/schemas/VoiceIdentifySchema.ts b/src/util/schemas/VoiceIdentifySchema.ts new file mode 100644 index 00000000..df023713 --- /dev/null +++ b/src/util/schemas/VoiceIdentifySchema.ts @@ -0,0 +1,12 @@ +export interface VoiceIdentifySchema { + server_id: string; + user_id: string; + session_id: string; + token: string; + video?: boolean; + streams?: { + type: string; + rid: string; + quality: number; + }[]; +} diff --git a/src/util/schemas/VoiceVideoSchema.ts b/src/util/schemas/VoiceVideoSchema.ts new file mode 100644 index 00000000..0ba519e1 --- /dev/null +++ b/src/util/schemas/VoiceVideoSchema.ts @@ -0,0 +1,17 @@ +export interface VoiceVideoSchema { + audio_ssrc: number; + video_ssrc: number; + rtx_ssrc?: number; + user_id?: string; + streams?: { + type: "video" | "audio"; + rid: string; + ssrc: number; + active: boolean; + quality: number; + rtx_ssrc: number; + max_bitrate: number; + max_framerate: number; + max_resolution: { type: string; width: number; height: number }; + }[]; +} diff --git a/src/util/schemas/index.ts b/src/util/schemas/index.ts index a15ab4b0..9f796cc3 100644 --- a/src/util/schemas/index.ts +++ b/src/util/schemas/index.ts @@ -30,6 +30,7 @@ export * from "./RelationshipPostSchema"; export * from "./RelationshipPutSchema"; export * from "./RoleModifySchema"; export * from "./RolePositionUpdateSchema"; +export * from "./SelectProtocolSchema"; export * from "./TemplateCreateSchema"; export * from "./TemplateModifySchema"; export * from "./TotpDisableSchema"; @@ -37,7 +38,10 @@ export * from "./TotpEnableSchema"; export * from "./TotpSchema"; export * from "./UserModifySchema"; export * from "./UserSettingsSchema"; +export * from "./Validator"; export * from "./VanityUrlSchema"; +export * from "./VoiceIdentifySchema"; export * from "./VoiceStateUpdateSchema"; +export * from "./VoiceVideoSchema"; export * from "./WebhookCreateSchema"; export * from "./WidgetModifySchema"; diff --git a/src/util/util/Database.ts b/src/util/util/Database.ts index 647de26a..247c5715 100644 --- a/src/util/util/Database.ts +++ b/src/util/util/Database.ts @@ -91,6 +91,7 @@ function getDataSourceOptions(): DataSourceOptions { cache: { duration: 1000 * 3 // cache all find queries for 3 seconds }, + // relationLoadStrategy: "query", bigNumberStrings: false, supportBigNumbers: true, name: "default", diff --git a/src/util/util/NamingStrategy.ts b/src/util/util/NamingStrategy.ts new file mode 100644 index 00000000..1ff256d6 --- /dev/null +++ b/src/util/util/NamingStrategy.ts @@ -0,0 +1,12 @@ +import { DefaultNamingStrategy } from "typeorm"; + +export class NamingStrategy extends DefaultNamingStrategy { + eagerJoinRelationAlias(alias: string, propertyPath: string) { + const result = super.eagerJoinRelationAlias(alias, propertyPath); + + console.log({ alias, propertyPath, result }); + return result; + } +} + +export const namingStrategy = new NamingStrategy(); diff --git a/src/util/util/imports/TypedEmitter.ts b/src/util/util/imports/TypedEmitter.ts new file mode 100644 index 00000000..7a0fffe2 --- /dev/null +++ b/src/util/util/imports/TypedEmitter.ts @@ -0,0 +1,41 @@ +export type EventMap = { + [key: string]: (...args: any[]) => void; +}; + +/** + * Type-safe event emitter. + * + * Use it like this: + * + * ```typescript + * type MyEvents = { + * error: (error: Error) => void; + * message: (from: string, content: string) => void; + * } + * + * const myEmitter = new EventEmitter() as TypedEmitter<MyEvents>; + * + * myEmitter.emit("error", "x") // <- Will catch this type error; + * ``` + */ +export interface TypedEventEmitter<Events extends EventMap> { + addListener<E extends keyof Events>(event: E, listener: Events[E]): this; + on<E extends keyof Events>(event: E, listener: Events[E]): this; + once<E extends keyof Events>(event: E, listener: Events[E]): this; + prependListener<E extends keyof Events>(event: E, listener: Events[E]): this; + prependOnceListener<E extends keyof Events>(event: E, listener: Events[E]): this; + + off<E extends keyof Events>(event: E, listener: Events[E]): this; + removeAllListeners<E extends keyof Events>(event?: E): this; + removeListener<E extends keyof Events>(event: E, listener: Events[E]): this; + + emit<E extends keyof Events>(event: E, ...args: Parameters<Events[E]>): boolean; + // The sloppy `eventNames()` return type is to mitigate type incompatibilities - see #5 + eventNames(): (keyof Events | string | symbol)[]; + rawListeners<E extends keyof Events>(event: E): Events[E][]; + listeners<E extends keyof Events>(event: E): Events[E][]; + listenerCount<E extends keyof Events>(event: E): number; + + getMaxListeners(): number; + setMaxListeners(maxListeners: number): this; +} |