diff --git a/util/src/entities/Application.ts b/util/src/entities/Application.ts
deleted file mode 100644
index 103f8e84..00000000
--- a/util/src/entities/Application.ts
+++ /dev/null
@@ -1,156 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, OneToOne, RelationId } from "typeorm";
-import { BaseClass } from "./BaseClass";
-import { Guild } from "./Guild";
-import { Team } from "./Team";
-import { User } from "./User";
-
-@Entity("applications")
-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};
-
- @Column({ nullable: true })
- terms_of_service_url?: string;
-
- @Column({ nullable: true })
- privacy_policy_url?: string;
-
- //just for us
-
- //@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
-
- //@Column({ nullable: true })
- //primary_sku_id?: string; // if this application is a game sold, this field will be the id of the "Game SKU" that is created,
-
- //@Column({ nullable: true })
- //slug?: string; // if this application is a game sold, this field will be the URL slug that links to the store page
-
- @JoinColumn({ name: "team_id" })
- @ManyToOne(() => Team, {
- onDelete: "CASCADE",
- nullable: true
- })
- team?: Team;
-
- }
-
-export interface ApplicationCommand {
- id: string;
- application_id: string;
- name: string;
- description: string;
- options?: ApplicationCommandOption[];
-}
-
-export interface ApplicationCommandOption {
- type: ApplicationCommandOptionType;
- name: string;
- description: string;
- required?: boolean;
- choices?: ApplicationCommandOptionChoice[];
- options?: ApplicationCommandOption[];
-}
-
-export interface ApplicationCommandOptionChoice {
- name: string;
- value: string | number;
-}
-
-export enum ApplicationCommandOptionType {
- SUB_COMMAND = 1,
- SUB_COMMAND_GROUP = 2,
- STRING = 3,
- INTEGER = 4,
- BOOLEAN = 5,
- USER = 6,
- CHANNEL = 7,
- ROLE = 8,
-}
-
-export interface ApplicationCommandInteractionData {
- id: string;
- name: string;
- options?: ApplicationCommandInteractionDataOption[];
-}
-
-export interface ApplicationCommandInteractionDataOption {
- name: string;
- value?: any;
- options?: ApplicationCommandInteractionDataOption[];
-}
diff --git a/util/src/entities/Attachment.ts b/util/src/entities/Attachment.ts
deleted file mode 100644
index 7b4b17eb..00000000
--- a/util/src/entities/Attachment.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import { BeforeRemove, Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-import { URL } from "url";
-import { deleteFile } from "../util/cdn";
-import { BaseClass } from "./BaseClass";
-
-@Entity("attachments")
-export class Attachment extends BaseClass {
- @Column()
- filename: string; // name of file attached
-
- @Column()
- size: number; // size of file in bytes
-
- @Column()
- url: string; // source url of file
-
- @Column()
- proxy_url: string; // a proxied url of file
-
- @Column({ nullable: true })
- height?: number; // height of file (if image)
-
- @Column({ nullable: true })
- width?: number; // width of file (if image)
-
- @Column({ nullable: true })
- content_type?: string;
-
- @Column({ nullable: true })
- @RelationId((attachment: Attachment) => attachment.message)
- message_id: string;
-
- @JoinColumn({ name: "message_id" })
- @ManyToOne(() => require("./Message").Message, (message: import("./Message").Message) => message.attachments, {
- onDelete: "CASCADE",
- })
- message: import("./Message").Message;
-
- @BeforeRemove()
- onDelete() {
- return deleteFile(new URL(this.url).pathname);
- }
-}
diff --git a/util/src/entities/AuditLog.ts b/util/src/entities/AuditLog.ts
deleted file mode 100644
index b003e7ba..00000000
--- a/util/src/entities/AuditLog.ts
+++ /dev/null
@@ -1,194 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-import { BaseClass } from "./BaseClass";
-import { ChannelPermissionOverwrite } from "./Channel";
-import { User } from "./User";
-
-export enum AuditLogEvents {
- // guild level
- GUILD_UPDATE = 1,
- GUILD_IMPORT = 2,
- GUILD_EXPORTED = 3,
- GUILD_ARCHIVE = 4,
- GUILD_UNARCHIVE = 5,
- // join-leave
- USER_JOIN = 6,
- USER_LEAVE = 7,
- // channels
- CHANNEL_CREATE = 10,
- CHANNEL_UPDATE = 11,
- CHANNEL_DELETE = 12,
- // permission overrides
- CHANNEL_OVERWRITE_CREATE = 13,
- CHANNEL_OVERWRITE_UPDATE = 14,
- CHANNEL_OVERWRITE_DELETE = 15,
- // kick and ban
- MEMBER_KICK = 20,
- MEMBER_PRUNE = 21,
- MEMBER_BAN_ADD = 22,
- MEMBER_BAN_REMOVE = 23,
- // member updates
- MEMBER_UPDATE = 24,
- MEMBER_ROLE_UPDATE = 25,
- MEMBER_MOVE = 26,
- MEMBER_DISCONNECT = 27,
- BOT_ADD = 28,
- // roles
- ROLE_CREATE = 30,
- ROLE_UPDATE = 31,
- ROLE_DELETE = 32,
- ROLE_SWAP = 33,
- // invites
- INVITE_CREATE = 40,
- INVITE_UPDATE = 41,
- INVITE_DELETE = 42,
- // webhooks
- WEBHOOK_CREATE = 50,
- WEBHOOK_UPDATE = 51,
- WEBHOOK_DELETE = 52,
- WEBHOOK_SWAP = 53,
- // custom emojis
- EMOJI_CREATE = 60,
- EMOJI_UPDATE = 61,
- EMOJI_DELETE = 62,
- EMOJI_SWAP = 63,
- // deletion
- MESSAGE_CREATE = 70, // messages sent using non-primary seat of the user only
- MESSAGE_EDIT = 71, // non-self edits only
- MESSAGE_DELETE = 72,
- MESSAGE_BULK_DELETE = 73,
- // pinning
- MESSAGE_PIN = 74,
- MESSAGE_UNPIN = 75,
- // integrations
- INTEGRATION_CREATE = 80,
- INTEGRATION_UPDATE = 81,
- INTEGRATION_DELETE = 82,
- // stage actions
- STAGE_INSTANCE_CREATE = 83,
- STAGE_INSTANCE_UPDATE = 84,
- STAGE_INSTANCE_DELETE = 85,
- // stickers
- STICKER_CREATE = 90,
- STICKER_UPDATE = 91,
- STICKER_DELETE = 92,
- STICKER_SWAP = 93,
- // threads
- THREAD_CREATE = 110,
- THREAD_UPDATE = 111,
- THREAD_DELETE = 112,
- // application commands
- APPLICATION_COMMAND_PERMISSION_UPDATE = 121,
- // automod
- POLICY_CREATE = 140,
- POLICY_UPDATE = 141,
- POLICY_DELETE = 142,
- 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,
-}
-
-@Entity("audit_logs")
-export class AuditLog extends BaseClass {
- @JoinColumn({ name: "target_id" })
- @ManyToOne(() => User)
- target?: User;
-
- @Column({ nullable: true })
- @RelationId((auditlog: AuditLog) => auditlog.user)
- user_id: string;
-
- @JoinColumn({ name: "user_id" })
- @ManyToOne(() => User, (user: User) => user.id)
- user: User;
-
- @Column({ type: "int" })
- action_type: AuditLogEvents;
-
- @Column({ type: "simple-json", nullable: true })
- options?: {
- delete_member_days?: string;
- members_removed?: string;
- channel_id?: string;
- messaged_id?: string;
- count?: string;
- id?: string;
- type?: string;
- role_name?: string;
- };
-
- @Column()
- @Column({ type: "simple-json" })
- changes: AuditLogChange[];
-
- @Column({ nullable: true })
- reason?: string;
-}
-
-export interface AuditLogChange {
- new_value?: AuditLogChangeValue;
- old_value?: AuditLogChangeValue;
- key: string;
-}
-
-export interface AuditLogChangeValue {
- name?: string;
- description?: string;
- icon_hash?: string;
- splash_hash?: string;
- discovery_splash_hash?: string;
- banner_hash?: string;
- owner_id?: string;
- region?: string;
- preferred_locale?: string;
- afk_channel_id?: string;
- afk_timeout?: number;
- rules_channel_id?: string;
- public_updates_channel_id?: string;
- mfa_level?: number;
- verification_level?: number;
- explicit_content_filter?: number;
- default_message_notifications?: number;
- vanity_url_code?: string;
- $add?: {}[];
- $remove?: {}[];
- prune_delete_days?: number;
- widget_enabled?: boolean;
- widget_channel_id?: string;
- system_channel_id?: string;
- position?: number;
- topic?: string;
- bitrate?: number;
- permission_overwrites?: ChannelPermissionOverwrite[];
- nsfw?: boolean;
- application_id?: string;
- rate_limit_per_user?: number;
- permissions?: string;
- color?: number;
- hoist?: boolean;
- mentionable?: boolean;
- allow?: string;
- deny?: string;
- code?: string;
- channel_id?: string;
- inviter_id?: string;
- max_uses?: number;
- uses?: number;
- max_age?: number;
- temporary?: boolean;
- deaf?: boolean;
- mute?: boolean;
- nick?: string;
- avatar_hash?: string;
- id?: string;
- type?: number;
- enable_emoticons?: boolean;
- expire_behavior?: number;
- expire_grace_period?: number;
- user_limit?: number;
-}
diff --git a/util/src/entities/BackupCodes.ts b/util/src/entities/BackupCodes.ts
deleted file mode 100644
index 9092c14e..00000000
--- a/util/src/entities/BackupCodes.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-import { BaseClass } from "./BaseClass";
-import { User } from "./User";
-
-@Entity("backup_codes")
-export class BackupCode extends BaseClass {
- @JoinColumn({ name: "user_id" })
- @ManyToOne(() => User, { onDelete: "CASCADE" })
- user: User;
-
- @Column()
- code: string;
-
- @Column()
- consumed: boolean;
-
- @Column()
- expired: boolean;
-}
\ No newline at end of file
diff --git a/util/src/entities/Ban.ts b/util/src/entities/Ban.ts
deleted file mode 100644
index 9504bd8e..00000000
--- a/util/src/entities/Ban.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-import { BaseClass } from "./BaseClass";
-import { Guild } from "./Guild";
-import { User } from "./User";
-
-@Entity("bans")
-export class Ban extends BaseClass {
- @Column({ nullable: true })
- @RelationId((ban: Ban) => ban.user)
- user_id: string;
-
- @JoinColumn({ name: "user_id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE",
- })
- user: User;
-
- @Column({ nullable: true })
- @RelationId((ban: Ban) => ban.guild)
- guild_id: string;
-
- @JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild, {
- onDelete: "CASCADE",
- })
- guild: Guild;
-
- @Column({ nullable: true })
- @RelationId((ban: Ban) => ban.executor)
- executor_id: string;
-
- @JoinColumn({ name: "executor_id" })
- @ManyToOne(() => User)
- executor: User;
-
- @Column()
- ip: string;
-
- @Column({ nullable: true })
- reason?: string;
-}
diff --git a/util/src/entities/BaseClass.ts b/util/src/entities/BaseClass.ts
deleted file mode 100644
index aecc2465..00000000
--- a/util/src/entities/BaseClass.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import "reflect-metadata";
-import { BaseEntity, ObjectIdColumn, PrimaryColumn, SaveOptions } from "typeorm";
-import { Snowflake } from "../util/Snowflake";
-
-export class BaseClassWithoutId extends BaseEntity {
- constructor() {
- super();
- }
-}
-
-export const PrimaryIdColumn = process.env.DATABASE?.startsWith("mongodb") ? ObjectIdColumn : PrimaryColumn;
-
-export class BaseClass extends BaseClassWithoutId {
- @PrimaryIdColumn()
- id: string;
-
- constructor() {
- super();
- if (!this.id) this.id = Snowflake.generate();
- }
-
- save(options?: SaveOptions | undefined): Promise<this> {
- if (!this.id) this.id = Snowflake.generate();
- return super.save(options);
- }
-}
diff --git a/util/src/entities/Categories.ts b/util/src/entities/Categories.ts
deleted file mode 100644
index 81fbc303..00000000
--- a/util/src/entities/Categories.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { PrimaryColumn, Column, Entity} from "typeorm";
-import { BaseClassWithoutId } from "./BaseClass";
-
-// TODO: categories:
-// [{
-// "id": 16,
-// "default": "Anime & Manga",
-// "localizations": {
-// "de": "Anime & Manga",
-// "fr": "Anim\u00e9s et mangas",
-// "ru": "\u0410\u043d\u0438\u043c\u0435 \u0438 \u043c\u0430\u043d\u0433\u0430"
-// }
-// },
-// "is_primary": false/true
-// }]
-// Also populate discord default categories
-
-@Entity("categories")
-export class Categories extends BaseClassWithoutId { // Not using snowflake
-
- @PrimaryColumn()
- id: number;
-
- @Column({ nullable: true })
- name: string;
-
- @Column({ type: "simple-json" })
- localizations: string;
-
- @Column({ nullable: true })
- is_primary: boolean;
-
-}
\ No newline at end of file
diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts
deleted file mode 100644
index a576d7af..00000000
--- a/util/src/entities/Channel.ts
+++ /dev/null
@@ -1,391 +0,0 @@
-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,
-}
diff --git a/util/src/entities/ClientRelease.ts b/util/src/entities/ClientRelease.ts
deleted file mode 100644
index c5afd307..00000000
--- a/util/src/entities/ClientRelease.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { Column, Entity} from "typeorm";
-import { BaseClass } from "./BaseClass";
-
-@Entity("client_release")
-export class Release extends BaseClass {
- @Column()
- name: string;
-
- @Column()
- pub_date: string;
-
- @Column()
- url: string;
-
- @Column()
- deb_url: string;
-
- @Column()
- osx_url: string;
-
- @Column()
- win_url: string;
-
- @Column({ nullable: true })
- notes?: string;
-}
diff --git a/util/src/entities/Config.ts b/util/src/entities/Config.ts
deleted file mode 100644
index 606fe901..00000000
--- a/util/src/entities/Config.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { Column, Entity } from "typeorm";
-import { BaseClassWithoutId, PrimaryIdColumn } from "./BaseClass";
-
-@Entity("config")
-export class ConfigEntity extends BaseClassWithoutId {
- @PrimaryIdColumn()
- key: string;
-
- @Column({ type: "simple-json", nullable: true })
- value: number | boolean | null | string | undefined;
-}
\ No newline at end of file
diff --git a/util/src/entities/ConnectedAccount.ts b/util/src/entities/ConnectedAccount.ts
deleted file mode 100644
index 09ae30ab..00000000
--- a/util/src/entities/ConnectedAccount.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-import { BaseClass } from "./BaseClass";
-import { User } from "./User";
-
-export interface PublicConnectedAccount extends Pick<ConnectedAccount, "name" | "type" | "verified"> {}
-
-@Entity("connected_accounts")
-export class ConnectedAccount extends BaseClass {
- @Column({ nullable: true })
- @RelationId((account: ConnectedAccount) => account.user)
- user_id: string;
-
- @JoinColumn({ name: "user_id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE",
- })
- user: User;
-
- @Column({ select: false })
- access_token: string;
-
- @Column({ select: false })
- friend_sync: boolean;
-
- @Column()
- name: string;
-
- @Column({ select: false })
- revoked: boolean;
-
- @Column({ select: false })
- show_activity: boolean;
-
- @Column()
- type: string;
-
- @Column()
- verified: boolean;
-
- @Column({ select: false })
- visibility: number;
-}
diff --git a/util/src/entities/Emoji.ts b/util/src/entities/Emoji.ts
deleted file mode 100644
index a3615b7d..00000000
--- a/util/src/entities/Emoji.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-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 {
- @Column()
- animated: boolean;
-
- @Column()
- available: boolean; // whether this emoji can be used, may be false due to various reasons
-
- @Column()
- guild_id: string;
-
- @JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild, {
- onDelete: "CASCADE",
- })
- guild: Guild;
-
- @Column({ nullable: true })
- @RelationId((emoji: Emoji) => emoji.user)
- user_id: string;
-
- @JoinColumn({ name: "user_id" })
- @ManyToOne(() => User)
- user: User;
-
- @Column()
- managed: boolean;
-
- @Column()
- name: string;
-
- @Column()
- require_colons: boolean;
-
- @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/util/src/entities/Encryption.ts b/util/src/entities/Encryption.ts
deleted file mode 100644
index 6b578d15..00000000
--- a/util/src/entities/Encryption.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";
-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})
- channel_id: Snowflake;
-
- @Column()
- encryption_permission_mask: BitField;
-
- @Column()
- allowed_algorithms: string[];
-
- @Column()
- current_algorithm: string;
-
- @Column({nullable: true})
- used_since_message: Snowflake;
-
-}
diff --git a/util/src/entities/Group.ts b/util/src/entities/Group.ts
deleted file mode 100644
index b24d38cf..00000000
--- a/util/src/entities/Group.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-
-import { BaseClass } from "./BaseClass";
-
-@Entity("groups")
-export class UserGroup extends BaseClass {
- @Column({ nullable: true })
- parent?: BigInt;
-
- @Column()
- color: number;
-
- @Column()
- hoist: boolean;
-
- @Column()
- mentionable: boolean;
-
- @Column()
- name: string;
-
- @Column()
- rights: BigInt;
-
- @Column()
- position: number;
-
- @Column({ nullable: true })
- icon: BigInt;
-
- @Column({ nullable: true })
- unicode_emoji: BigInt;
-}
diff --git a/util/src/entities/Guild.ts b/util/src/entities/Guild.ts
deleted file mode 100644
index d146e577..00000000
--- a/util/src/entities/Guild.ts
+++ /dev/null
@@ -1,370 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, OneToMany, OneToOne, RelationId } from "typeorm";
-import { OrmUtils } from "../util/imports/OrmUtils";
-import { Config, handleFile, Snowflake } from "..";
-import { Ban } from "./Ban";
-import { BaseClass } from "./BaseClass";
-import { Channel } from "./Channel";
-import { Emoji } from "./Emoji";
-import { Invite } from "./Invite";
-import { Member } from "./Member";
-import { Role } from "./Role";
-import { Sticker } from "./Sticker";
-import { Template } from "./Template";
-import { User } from "./User";
-import { VoiceState } from "./VoiceState";
-import { Webhook } from "./Webhook";
-
-// TODO: application_command_count, application_command_counts: {1: 0, 2: 0, 3: 0}
-// TODO: guild_scheduled_events
-// TODO: stage_instances
-// TODO: threads
-// TODO:
-// "keywords": [
-// "Genshin Impact",
-// "Paimon",
-// "Honkai Impact",
-// "ARPG",
-// "Open-World",
-// "Waifu",
-// "Anime",
-// "Genshin",
-// "miHoYo",
-// "Gacha"
-// ],
-
-export const PublicGuildRelations = [
- "channels",
- "emojis",
- "members",
- "roles",
- "stickers",
- "voice_states",
- "members.user",
-];
-
-@Entity("guilds")
-export class Guild extends BaseClass {
- @Column({ nullable: true })
- @RelationId((guild: Guild) => guild.afk_channel)
- afk_channel_id?: string;
-
- @JoinColumn({ name: "afk_channel_id" })
- @ManyToOne(() => Channel)
- afk_channel?: Channel;
-
- @Column({ nullable: true })
- afk_timeout?: number = Config.get().defaults.guild.afkTimeout;
-
- // * commented out -> use owner instead
- // application id of the guild creator if it is bot-created
- // @Column({ nullable: true })
- // application?: string;
-
- @JoinColumn({ name: "ban_ids" })
- @OneToMany(() => Ban, (ban: Ban) => ban.guild, {
- cascade: true,
- orphanedRowAction: "delete",
- })
- bans: Ban[];
-
- @Column({ nullable: true })
- banner?: string;
-
- @Column({ nullable: true })
- default_message_notifications?: number = Config.get().defaults.guild.defaultMessageNotifications;
-
- @Column({ nullable: true })
- description?: string;
-
- @Column({ nullable: true })
- discovery_splash?: string;
-
- @Column({ nullable: true })
- explicit_content_filter?: number = Config.get().defaults.guild.explicitContentFilter;
-
- @Column({ type: "simple-array" })
- features: string[]; //TODO use enum
- //TODO: https://discord.com/developers/docs/resources/guild#guild-object-guild-features
-
- @Column({ nullable: true })
- primary_category_id: number;
-
- @Column({ nullable: true })
- icon?: string;
-
- @Column({ nullable: true })
- large?: boolean;
-
- @Column({ nullable: true })
- max_members?: number = Config.get().limits.guild.maxMembers; // e.g. default 100.000
-
- @Column({ nullable: true })
- max_presences?: number = Config.get().defaults.guild.maxPresences;
-
- @Column({ nullable: true })
- max_video_channel_users?: number = Config.get().defaults.guild.maxVideoChannelUsers; // ? default: 25, is this max 25 streaming or watching
-
- @Column({ nullable: true })
- member_count?: number = 0;
-
- @Column({ nullable: true })
- presence_count?: number = 0; // users online
-
- @OneToMany(() => Member, (member: Member) => member.guild, {
- cascade: true,
- orphanedRowAction: "delete",
- onDelete: "CASCADE",
- })
- members: Member[];
-
- @JoinColumn({ name: "role_ids" })
- @OneToMany(() => Role, (role: Role) => role.guild, {
- cascade: true,
- orphanedRowAction: "delete",
- onDelete: "CASCADE",
- })
- roles: Role[];
-
- @JoinColumn({ name: "channel_ids" })
- @OneToMany(() => Channel, (channel: Channel) => channel.guild, {
- cascade: true,
- orphanedRowAction: "delete",
- })
- channels: Channel[];
-
- @Column({ nullable: true })
- @RelationId((guild: Guild) => guild.template)
- template_id?: string;
-
- @JoinColumn({ name: "template_id", referencedColumnName: "id" })
- @ManyToOne(() => Template)
- template: Template;
-
- @JoinColumn({ name: "emoji_ids" })
- @OneToMany(() => Emoji, (emoji: Emoji) => emoji.guild, {
- cascade: true,
- orphanedRowAction: "delete",
- onDelete: "CASCADE",
- })
- emojis: Emoji[];
-
- @JoinColumn({ name: "sticker_ids" })
- @OneToMany(() => Sticker, (sticker: Sticker) => sticker.guild, {
- cascade: true,
- orphanedRowAction: "delete",
- onDelete: "CASCADE",
- })
- stickers: Sticker[];
-
- @JoinColumn({ name: "invite_ids" })
- @OneToMany(() => Invite, (invite: Invite) => invite.guild, {
- cascade: true,
- orphanedRowAction: "delete",
- onDelete: "CASCADE",
- })
- invites: Invite[];
-
- @JoinColumn({ name: "voice_state_ids" })
- @OneToMany(() => VoiceState, (voicestate: VoiceState) => voicestate.guild, {
- cascade: true,
- orphanedRowAction: "delete",
- onDelete: "CASCADE",
- })
- voice_states: VoiceState[];
-
- @JoinColumn({ name: "webhook_ids" })
- @OneToMany(() => Webhook, (webhook: Webhook) => webhook.guild, {
- cascade: true,
- orphanedRowAction: "delete",
- onDelete: "CASCADE",
- })
- webhooks: Webhook[];
-
- @Column({ nullable: true })
- mfa_level?: number;
-
- @Column()
- name: string;
-
- @Column({ nullable: true })
- @RelationId((guild: Guild) => guild.owner)
- 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
-
- @Column({ nullable: true })
- preferred_locale?: string;
-
- @Column({ nullable: true })
- premium_subscription_count?: number;
-
- @Column({ nullable: true })
- premium_tier?: number; // crowd premium level
-
- @Column({ nullable: true })
- @RelationId((guild: Guild) => guild.public_updates_channel)
- public_updates_channel_id: string;
-
- @JoinColumn({ name: "public_updates_channel_id" })
- @ManyToOne(() => Channel)
- public_updates_channel?: Channel;
-
- @Column({ nullable: true })
- @RelationId((guild: Guild) => guild.rules_channel)
- rules_channel_id?: string;
-
- @JoinColumn({ name: "rules_channel_id" })
- @ManyToOne(() => Channel)
- rules_channel?: string;
-
- @Column({ nullable: true })
- region?: string;
-
- @Column({ nullable: true })
- splash?: string;
-
- @Column({ nullable: true })
- @RelationId((guild: Guild) => guild.system_channel)
- system_channel_id?: string;
-
- @JoinColumn({ name: "system_channel_id" })
- @ManyToOne(() => Channel)
- system_channel?: Channel;
-
- @Column({ nullable: true })
- system_channel_flags?: number;
-
- @Column({ nullable: true })
- unavailable?: boolean;
-
- @Column({ nullable: true })
- verification_level?: number;
-
- @Column({ type: "simple-json" })
- welcome_screen: {
- enabled: boolean;
- description: string;
- welcome_channels: {
- description: string;
- emoji_id?: string;
- emoji_name: string;
- channel_id: string;
- }[];
- };
-
- @Column({ nullable: true })
- @RelationId((guild: Guild) => guild.widget_channel)
- widget_channel_id?: string;
-
- @JoinColumn({ name: "widget_channel_id" })
- @ManyToOne(() => Channel)
- widget_channel?: Channel;
-
- @Column({ nullable: true })
- widget_enabled?: boolean;
-
- @Column({ nullable: true })
- nsfw_level?: number;
-
- @Column({ nullable: true })
- nsfw?: boolean;
-
- // TODO: nested guilds
- @Column({ nullable: true })
- parent?: string;
-
- // only for developer portal
- permissions?: number;
-
- //new guild settings, 11/08/2022:
- @Column({ nullable: true })
- premium_progress_bar_enabled: boolean = false;
-
- 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(), {
- name: body.name || "Fosscord",
- icon: await handleFile(`/icons/${guild_id}`, body.icon as string),
- region: Config.get().regions.default,
- owner_id: body.owner_id, // TODO: need to figure out a way for ownerless guilds and multiply-owned guilds
- afk_timeout: 300,
- default_message_notifications: 1, // defaults effect: setting the push default at mentions-only will save a lot
- explicit_content_filter: 0,
- features: [],
- primary_category_id: null,
- id: guild_id,
- max_members: 250000,
- max_presences: 250000,
- max_video_channel_users: 200,
- presence_count: 0,
- member_count: 0, // will automatically be increased by addMember()
- mfa_level: 0,
- preferred_locale: "en-US",
- premium_subscription_count: 0,
- premium_tier: 0,
- system_channel_flags: 4, // defaults effect: suppress the setup tips to save performance
- unavailable: false,
- nsfw: false,
- nsfw_level: 0,
- verification_level: 0,
- welcome_screen: {
- enabled: false,
- description: "Fill in your description",
- welcome_channels: [],
- },
- widget_enabled: true, // NB: don't set it as false to prevent artificial restrictions
- });
- await guild.save();
-
- // we have to create the role _after_ the guild because else we would get a "SQLITE_CONSTRAINT: FOREIGN KEY constraint failed" error
- // TODO: make the @everyone a pseudorole that is dynamically generated at runtime so we can save storage
- let role: Role = OrmUtils.mergeDeep(new Role(), {
- id: guild_id,
- guild_id: guild_id,
- color: 0,
- hoist: false,
- managed: false,
- // NB: in Fosscord, every role will be non-managed, as we use user-groups instead of roles for managed groups
- mentionable: false,
- name: "@everyone",
- permissions: String("2251804225"),
- position: 0,
- icon: null,
- unicode_emoji: null,
- });
- await role.save();
-
- if (!body.channels || !body.channels.length) body.channels = [{ id: "01", type: 0, name: "general" }];
-
- const ids = new Map();
-
- 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))) {
- let id = ids.get(channel.id) || Snowflake.generate();
-
- let parent_id = ids.get(channel.parent_id);
-
- await Channel.createChannel({ ...channel, guild_id, id, parent_id }, body.owner_id, {
- keepId: true,
- skipExistsCheck: true,
- skipPermissionCheck: true,
- skipEventEmit: true,
- });
- }
-
- return guild;
- }
-}
diff --git a/util/src/entities/Invite.ts b/util/src/entities/Invite.ts
deleted file mode 100644
index 1e0ebe52..00000000
--- a/util/src/entities/Invite.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId, PrimaryColumn } from "typeorm";
-import { Member } from "./Member";
-import { BaseClassWithoutId } from "./BaseClass";
-import { Channel } from "./Channel";
-import { Guild } from "./Guild";
-import { User } from "./User";
-import { random } from "@fosscord/api";
-
-export const PublicInviteRelation = ["inviter", "guild", "channel"];
-
-@Entity("invites")
-export class Invite extends BaseClassWithoutId {
- @PrimaryColumn()
- code: string = random();
-
- @Column()
- temporary: boolean = true;
-
- @Column()
- uses: number = 0;
-
- @Column()
- max_uses: number;
-
- @Column()
- max_age: number;
-
- @Column()
- created_at: Date = new Date();
-
- @Column()
- expires_at: Date;
-
- @Column({ nullable: true })
- @RelationId((invite: Invite) => invite.guild)
- guild_id: string;
-
- @JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild, {
- onDelete: "CASCADE",
- })
- guild: Guild;
-
- @Column({ nullable: true })
- @RelationId((invite: Invite) => invite.channel)
- channel_id: string;
-
- @JoinColumn({ name: "channel_id" })
- @ManyToOne(() => Channel, {
- onDelete: "CASCADE",
- })
- channel: Channel;
-
- @Column({ nullable: true })
- @RelationId((invite: Invite) => invite.inviter)
- inviter_id: string;
-
- @JoinColumn({ name: "inviter_id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE"
- })
- inviter: User;
-
- @Column({ nullable: true })
- @RelationId((invite: Invite) => invite.target_user)
- target_user_id: string;
-
- @JoinColumn({ name: "target_user_id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE",
- })
- target_user?: string; // could be used for "User specific invites" https://github.com/fosscord/fosscord/issues/62
-
- @Column({ nullable: true })
- target_user_type?: number;
-
- @Column({ nullable: true })
- vanity_url?: boolean;
-
- static async joinGuild(user_id: string, code: string) {
- const invite = await Invite.findOneOrFail({ where: { code } });
- if (invite.uses++ >= invite.max_uses && invite.max_uses !== 0) await Invite.delete({ code });
- else await invite.save();
-
- await Member.addToGuild(user_id, invite.guild_id);
- return invite;
- }
-}
diff --git a/util/src/entities/Member.ts b/util/src/entities/Member.ts
deleted file mode 100644
index baac58ed..00000000
--- a/util/src/entities/Member.ts
+++ /dev/null
@@ -1,360 +0,0 @@
-import { PublicUser, User } from "./User";
-import { BaseClass } from "./BaseClass";
-import {
- Column,
- Entity,
- Index,
- JoinColumn,
- JoinTable,
- ManyToMany,
- ManyToOne,
- PrimaryGeneratedColumn,
- RelationId,
-} from "typeorm";
-import { Guild } from "./Guild";
-import { Config, emitEvent } from "../util";
-import {
- GuildCreateEvent,
- GuildDeleteEvent,
- GuildMemberAddEvent,
- GuildMemberRemoveEvent,
- GuildMemberUpdateEvent,
-} from "../interfaces";
-import { HTTPError } from "../util/imports/HTTPError";
-import { Role } from "./Role";
-import { BaseClassWithoutId } from "./BaseClass";
-import { Ban, PublicGuildRelations } from ".";
-import { DiscordApiErrors } from "../util/Constants";
-import { OrmUtils } from "../util/imports/OrmUtils";
-
-export const MemberPrivateProjection: (keyof Member)[] = [
- "id",
- "guild",
- "guild_id",
- "deaf",
- "joined_at",
- "last_message_id",
- "mute",
- "nick",
- "pending",
- "premium_since",
- "roles",
- "settings",
- "user",
-];
-
-@Entity("members")
-@Index(["id", "guild_id"], { unique: true })
-export class Member extends BaseClassWithoutId {
- @PrimaryGeneratedColumn()
- index: string;
-
- @Column()
- @RelationId((member: Member) => member.user)
- id: string;
-
- @JoinColumn({ name: "id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE",
- })
- user: User;
-
- @Column()
- @RelationId((member: Member) => member.guild)
- guild_id: string;
-
- @JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild, {
- onDelete: "CASCADE",
- })
- guild: Guild;
-
- @Column({ nullable: true })
- nick?: string;
-
- @JoinTable({
- name: "member_roles",
- joinColumn: { name: "index", referencedColumnName: "index" },
- inverseJoinColumn: {
- name: "role_id",
- referencedColumnName: "id",
- },
- })
- @ManyToMany(() => Role, { cascade: true })
- roles: Role[];
-
- @Column()
- joined_at: Date;
-
- @Column({ nullable: true })
- premium_since?: Date;
-
- @Column()
- deaf: boolean;
-
- @Column()
- mute: boolean;
-
- @Column()
- pending: boolean;
-
- @Column({ type: "simple-json", select: false })
- settings: UserGuildSettings;
-
- @Column({ nullable: true })
- last_message_id?: string;
-
- /**
- @JoinColumn({ name: "id" })
- @ManyToOne(() => User, {
- onDelete: "DO NOTHING",
- // do not auto-kick force-joined members just because their joiners left the server
- }) **/
- @Column({ nullable: true })
- joined_by?: string;
-
- // TODO: add this when we have proper read receipts
- // @Column({ type: "simple-json" })
- // read_state: ReadState;
-
- static async IsInGuildOrFail(user_id: string, guild_id: string) {
- if (await Member.count({ where: { id: user_id, guild: { id: guild_id } } })) return true;
- throw new HTTPError("You are not member of this guild", 403);
- }
-
- static async removeFromGuild(user_id: string, guild_id: string) {
- const guild = await Guild.findOneOrFail({ select: ["owner_id", "member_count"], where: { id: guild_id } });
- if (guild.owner_id === user_id) throw new Error("The owner cannot be removed of the guild");
- const member = await Member.findOneOrFail({ where: { id: user_id, guild_id }, relations: ["user"] });
-
- // use promise all to execute all promises at the same time -> save time
- //TODO: check for bugs
- if (guild.member_count) guild.member_count--;
- return Promise.all([
- Member.delete({
- id: user_id,
- guild_id,
- }),
- //Guild.decrement({ id: guild_id }, "member_count", -1),
-
- emitEvent({
- event: "GUILD_DELETE",
- data: {
- id: guild_id,
- },
- user_id: user_id,
- } as GuildDeleteEvent),
- emitEvent({
- event: "GUILD_MEMBER_REMOVE",
- data: { guild_id, user: member.user },
- guild_id,
- } as GuildMemberRemoveEvent),
- ]);
- }
-
- static async addRole(user_id: string, guild_id: string, role_id: string) {
- const [member, role] = await Promise.all([
- // @ts-ignore
- Member.findOneOrFail({
- where: { id: user_id, guild_id },
- relations: ["user", "roles"], // we don't want to load the role objects just the ids
- select: ["index"],
- }),
- Role.findOneOrFail({ where: { id: role_id, guild_id }, select: ["id"] }),
- ]);
- member.roles.push(OrmUtils.mergeDeep(new Role(), { id: role_id }));
-
- await Promise.all([
- member.save(),
- emitEvent({
- event: "GUILD_MEMBER_UPDATE",
- data: {
- guild_id,
- user: member.user,
- roles: member.roles.map((x) => x.id),
- },
- guild_id,
- } as GuildMemberUpdateEvent),
- ]);
- }
-
- static async removeRole(user_id: string, guild_id: string, role_id: string) {
- const [member] = await Promise.all([
- // @ts-ignore
- Member.findOneOrFail({
- where: { id: user_id, guild_id },
- relations: ["user", "roles"], // we don't want to load the role objects just the ids
- select: ["index"],
- }),
- await Role.findOneOrFail({ where: { id: role_id, guild_id } }),
- ]);
- member.roles = member.roles.filter((x) => x.id == role_id);
-
- await Promise.all([
- member.save(),
- emitEvent({
- event: "GUILD_MEMBER_UPDATE",
- data: {
- guild_id,
- user: member.user,
- roles: member.roles.map((x) => x.id),
- },
- guild_id,
- } as GuildMemberUpdateEvent),
- ]);
- }
-
- static async changeNickname(user_id: string, guild_id: string, nickname: string) {
- const member = await Member.findOneOrFail({
- where: {
- id: user_id,
- guild_id,
- },
- relations: ["user"],
- });
- member.nick = nickname;
-
- await Promise.all([
- member.save(),
-
- emitEvent({
- event: "GUILD_MEMBER_UPDATE",
- data: {
- guild_id,
- user: member.user,
- nick: nickname,
- },
- guild_id,
- } as GuildMemberUpdateEvent),
- ]);
- }
-
- static async addToGuild(user_id: string, guild_id: string) {
- const user = await User.getPublicUser(user_id);
- const isBanned = await Ban.count({ where: { guild_id, user_id } });
- if (isBanned) {
- throw DiscordApiErrors.USER_BANNED;
- }
- const { maxGuilds } = Config.get().limits.user;
- const guild_count = await Member.count({ where: { id: user_id } });
- if (guild_count >= maxGuilds) {
- throw new HTTPError(`You are at the ${maxGuilds} server limit.`, 403);
- }
-
- const guild = await Guild.findOneOrFail({
- where: {
- id: guild_id,
- },
- relations: PublicGuildRelations,
- });
-
- if (await Member.count({ where: { id: user.id, guild: { id: guild_id } } }))
- throw new HTTPError("You are already a member of this guild", 400);
-
- const member = {
- id: user_id,
- guild_id,
- nick: undefined,
- roles: [guild_id], // @everyone role
- joined_at: new Date(),
- premium_since: null,
- deaf: false,
- mute: false,
- pending: false,
- };
- //TODO: check for bugs
- if (guild.member_count) guild.member_count++;
- await Promise.all([
- OrmUtils.mergeDeep(new Member(), {
- ...member,
- roles: [OrmUtils.mergeDeep(new Role(), { id: guild_id })],
- // read_state: {},
- settings: {
- channel_overrides: [],
- message_notifications: 0,
- mobile_push: true,
- muted: false,
- suppress_everyone: false,
- suppress_roles: false,
- version: 0,
- },
- // Member.save is needed because else the roles relations wouldn't be updated
- }).save(),
- //Guild.increment({ id: guild_id }, "member_count", 1),
- emitEvent({
- event: "GUILD_MEMBER_ADD",
- data: {
- ...member,
- user,
- guild_id,
- },
- guild_id,
- } as GuildMemberAddEvent),
- emitEvent({
- event: "GUILD_CREATE",
- data: {
- ...guild,
- members: [...guild.members, { ...member, user }],
- member_count: (guild.member_count || 0) + 1,
- guild_hashes: {},
- guild_scheduled_events: [],
- joined_at: member.joined_at,
- presences: [],
- stage_instances: [],
- threads: [],
- },
- user_id,
- } as GuildCreateEvent),
- ]);
- }
-}
-
-export interface UserGuildSettings {
- channel_overrides: {
- channel_id: string;
- message_notifications: number;
- mute_config: MuteConfig;
- muted: boolean;
- }[];
- message_notifications: number;
- mobile_push: boolean;
- mute_config: MuteConfig;
- muted: boolean;
- suppress_everyone: boolean;
- suppress_roles: boolean;
- version: number;
-}
-
-export interface MuteConfig {
- end_time: number;
- selected_time_window: number;
-}
-
-export type PublicMemberKeys =
- | "id"
- | "guild_id"
- | "nick"
- | "roles"
- | "joined_at"
- | "pending"
- | "deaf"
- | "mute"
- | "premium_since";
-
-export const PublicMemberProjection: PublicMemberKeys[] = [
- "id",
- "guild_id",
- "nick",
- "roles",
- "joined_at",
- "pending",
- "deaf",
- "mute",
- "premium_since",
-];
-
-// @ts-ignore
-export type PublicMember = Pick<Member, Omit<PublicMemberKeys, "roles">> & {
- user: PublicUser;
- roles: string[]; // only role ids not objects
-};
diff --git a/util/src/entities/Message.ts b/util/src/entities/Message.ts
deleted file mode 100644
index ba3d4f2d..00000000
--- a/util/src/entities/Message.ts
+++ /dev/null
@@ -1,284 +0,0 @@
-import { User } from "./User";
-import { Member } from "./Member";
-import { Role } from "./Role";
-import { Channel } from "./Channel";
-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 { BaseClass } from "./BaseClass";
-import { Guild } from "./Guild";
-import { Webhook } from "./Webhook";
-import { Sticker } from "./Sticker";
-import { Attachment } from "./Attachment";
-
-export enum MessageType {
- DEFAULT = 0,
- RECIPIENT_ADD = 1,
- RECIPIENT_REMOVE = 2,
- CALL = 3,
- CHANNEL_NAME_CHANGE = 4,
- CHANNEL_ICON_CHANGE = 5,
- CHANNEL_PINNED_MESSAGE = 6,
- GUILD_MEMBER_JOIN = 7,
- USER_PREMIUM_GUILD_SUBSCRIPTION = 8,
- USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1 = 9,
- USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2 = 10,
- USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3 = 11,
- CHANNEL_FOLLOW_ADD = 12,
- ACTION = 13, // /me messages
- GUILD_DISCOVERY_DISQUALIFIED = 14,
- GUILD_DISCOVERY_REQUALIFIED = 15,
- ENCRYPTED = 16,
- REPLY = 19,
- APPLICATION_COMMAND = 20, // application command or self command invocation
- ROUTE_ADDED = 41, // custom message routing: new route affecting that channel
- ROUTE_DISABLED = 42, // custom message routing: given route no longer affecting that channel
- SELF_COMMAND_SCRIPT = 43, // self command scripts
- ENCRYPTION = 50,
- CUSTOM_START = 63,
- UNHANDLED = 255
-}
-
-@Entity("messages")
-@Index(["channel_id", "id"], { unique: true })
-export class Message extends BaseClass {
- @Column({ nullable: true })
- @RelationId((message: Message) => message.channel)
- @Index()
- channel_id: string;
-
- @JoinColumn({ name: "channel_id" })
- @ManyToOne(() => Channel, {
- onDelete: "CASCADE",
- })
- channel: Channel;
-
- @Column({ nullable: true })
- @RelationId((message: Message) => message.guild)
- guild_id?: string;
-
- @JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild, {
- onDelete: "CASCADE",
- })
- guild?: Guild;
-
- @Column({ nullable: true })
- @RelationId((message: Message) => message.author)
- @Index()
- author_id: string;
-
- @JoinColumn({ name: "author_id", referencedColumnName: "id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE",
- })
- author?: User;
-
- @Column({ nullable: true })
- @RelationId((message: Message) => message.member)
- member_id: string;
-
- @JoinColumn({ name: "member_id", referencedColumnName: "id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE",
- })
- member?: Member;
-
- @Column({ nullable: true })
- @RelationId((message: Message) => message.webhook)
- webhook_id: string;
-
- @JoinColumn({ name: "webhook_id" })
- @ManyToOne(() => Webhook)
- webhook?: Webhook;
-
- @Column({ nullable: true })
- @RelationId((message: Message) => message.application)
- application_id: string;
-
- @JoinColumn({ name: "application_id" })
- @ManyToOne(() => Application)
- application?: Application;
-
- @Column({ nullable: true })
- content?: string;
-
- @Column()
- @CreateDateColumn()
- timestamp: Date;
-
- @Column({ nullable: true })
- edited_timestamp?: Date;
-
- @Column({ nullable: true })
- tts?: boolean;
-
- @Column({ nullable: true })
- mention_everyone?: boolean;
-
- @JoinTable({ name: "message_user_mentions" })
- @ManyToMany(() => User)
- mentions: User[];
-
- @JoinTable({ name: "message_role_mentions" })
- @ManyToMany(() => Role)
- mention_roles: Role[];
-
- @JoinTable({ name: "message_channel_mentions" })
- @ManyToMany(() => Channel)
- mention_channels: Channel[];
-
- @JoinTable({ name: "message_stickers" })
- @ManyToMany(() => Sticker, { cascade: true, onDelete: "CASCADE" })
- sticker_items?: Sticker[];
-
- @OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, {
- cascade: true,
- orphanedRowAction: "delete",
- })
- attachments?: Attachment[];
-
- @Column({ type: "simple-json" })
- embeds: Embed[];
-
- @Column({ type: "simple-json" })
- reactions: Reaction[];
-
- @Column({ type: "text", nullable: true })
- nonce?: string;
-
- @Column({ nullable: true })
- pinned?: boolean;
-
- @Column({ type: "int" })
- type: MessageType;
-
- @Column({ type: "simple-json", nullable: true })
- activity?: {
- type: number;
- party_id: string;
- };
-
- @Column({ nullable: true })
- flags?: string;
- @Column({ type: "simple-json", nullable: true })
- message_reference?: {
- message_id: string;
- channel_id?: string;
- guild_id?: string;
- };
-
- @JoinColumn({ name: "message_reference_id" })
- @ManyToOne(() => Message)
- referenced_message?: Message;
-
- @Column({ type: "simple-json", nullable: true })
- interaction?: {
- id: string;
- type: InteractionType;
- name: string;
- user_id: string; // the user who invoked the interaction
- // user: User; // TODO: autopopulate user
- };
-
- @Column({ type: "simple-json", nullable: true })
- components?: MessageComponent[];
-}
-
-export interface MessageComponent {
- type: number;
- style?: number;
- label?: string;
- emoji?: PartialEmoji;
- custom_id?: string;
- url?: string;
- disabled?: boolean;
- components: MessageComponent[];
-}
-
-export enum MessageComponentType {
- Script = 0, // self command script
- ActionRow = 1,
- Button = 2,
-}
-
-export interface Embed {
- title?: string; //title of embed
- type?: EmbedType; // type of embed (always "rich" for webhook embeds)
- description?: string; // description of embed
- url?: string; // url of embed
- timestamp?: Date; // timestamp of embed content
- color?: number; // color code of the embed
- footer?: {
- text: string;
- icon_url?: string;
- proxy_icon_url?: string;
- }; // footer object footer information
- image?: EmbedImage; // image object image information
- thumbnail?: EmbedImage; // thumbnail object thumbnail information
- video?: EmbedImage; // video object video information
- provider?: {
- name?: string;
- url?: string;
- }; // provider object provider information
- author?: {
- name?: string;
- url?: string;
- icon_url?: string;
- proxy_icon_url?: string;
- }; // author object author information
- fields?: {
- name: string;
- value: string;
- inline?: boolean;
- }[];
-}
-
-export enum EmbedType {
- rich = "rich",
- image = "image",
- video = "video",
- gifv = "gifv",
- article = "article",
- link = "link",
-}
-
-export interface EmbedImage {
- url?: string;
- proxy_url?: string;
- height?: number;
- width?: number;
-}
-
-export interface Reaction {
- count: number;
- //// not saved in the database // me: boolean; // whether the current user reacted using this emoji
- emoji: PartialEmoji;
- user_ids: string[];
-}
-
-export interface PartialEmoji {
- id?: string;
- name: string;
- animated?: boolean;
-}
-
-export interface AllowedMentions {
- parse?: ("users" | "roles" | "everyone")[];
- roles?: string[];
- users?: string[];
- replied_user?: boolean;
-}
diff --git a/util/src/entities/Migration.ts b/util/src/entities/Migration.ts
deleted file mode 100644
index 3f39ae72..00000000
--- a/util/src/entities/Migration.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { Column, Entity, ObjectIdColumn, PrimaryGeneratedColumn } from "typeorm";
-import { BaseClassWithoutId } from ".";
-
-export const PrimaryIdAutoGenerated = process.env.DATABASE?.startsWith("mongodb")
- ? ObjectIdColumn
- : PrimaryGeneratedColumn;
-
-@Entity("migrations")
-export class Migration extends BaseClassWithoutId {
- @PrimaryIdAutoGenerated()
- id: number;
-
- @Column({ type: "bigint" })
- timestamp: number;
-
- @Column()
- name: string;
-}
diff --git a/util/src/entities/Note.ts b/util/src/entities/Note.ts
deleted file mode 100644
index 36017c5e..00000000
--- a/util/src/entities/Note.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, Unique } from "typeorm";
-import { BaseClass } from "./BaseClass";
-import { User } from "./User";
-
-@Entity("notes")
-@Unique(["owner", "target"])
-export class Note extends BaseClass {
- @JoinColumn({ name: "owner_id" })
- @ManyToOne(() => User, { onDelete: "CASCADE" })
- owner: User;
-
- @JoinColumn({ name: "target_id" })
- @ManyToOne(() => User, { onDelete: "CASCADE" })
- target: User;
-
- @Column()
- content: string;
-}
\ No newline at end of file
diff --git a/util/src/entities/RateLimit.ts b/util/src/entities/RateLimit.ts
deleted file mode 100644
index f5916f6b..00000000
--- a/util/src/entities/RateLimit.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { Column, Entity } from "typeorm";
-import { BaseClass } from "./BaseClass";
-
-@Entity("rate_limits")
-export class RateLimit extends BaseClass {
- @Column() // no relation as it also
- executor_id: string;
-
- @Column()
- hits: number;
-
- @Column()
- blocked: boolean;
-
- @Column()
- expires_at: Date;
-}
diff --git a/util/src/entities/ReadState.ts b/util/src/entities/ReadState.ts
deleted file mode 100644
index b915573b..00000000
--- a/util/src/entities/ReadState.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-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
-// notification cursor and public read receipt need to be forwards-only (the former to prevent re-pinging when marked as unread, and the latter to be acceptable as a legal acknowledgement in criminal proceedings), and private read marker needs to be advance-rewind capable
-// public read receipt ≥ notification cursor ≥ private fully read marker
-
-@Entity("read_states")
-@Index(["channel_id", "user_id"], { unique: true })
-export class ReadState extends BaseClass {
- @Column()
- @RelationId((read_state: ReadState) => read_state.channel)
- channel_id: string;
-
- @JoinColumn({ name: "channel_id" })
- @ManyToOne(() => Channel, {
- onDelete: "CASCADE",
- })
- channel: Channel;
-
- @Column()
- @RelationId((read_state: ReadState) => read_state.user)
- user_id: string;
-
- @JoinColumn({ name: "user_id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE",
- })
- user: User;
-
- // fully read marker
- @Column({ nullable: true })
- last_message_id: string;
-
- // public read receipt
- @Column({ nullable: true })
- public_ack: string;
-
- // notification cursor / private read receipt
- @Column({ nullable: true })
- notifications_cursor: string;
-
- @Column({ nullable: true })
- last_pin_timestamp?: Date;
-
- @Column({ nullable: true })
- mention_count: number;
-
- // @Column({ nullable: true })
- // TODO: derive this from (last_message_id=notifications_cursor=public_ack)=true
- manual: boolean;
-}
diff --git a/util/src/entities/Recipient.ts b/util/src/entities/Recipient.ts
deleted file mode 100644
index a945f938..00000000
--- a/util/src/entities/Recipient.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-import { BaseClass } from "./BaseClass";
-
-@Entity("recipients")
-export class Recipient extends BaseClass {
- @Column()
- @RelationId((recipient: Recipient) => recipient.channel)
- channel_id: string;
-
- @JoinColumn({ name: "channel_id" })
- @ManyToOne(() => require("./Channel").Channel, {
- onDelete: "CASCADE",
- })
- channel: import("./Channel").Channel;
-
- @Column()
- @RelationId((recipient: Recipient) => recipient.user)
- user_id: string;
-
- @JoinColumn({ name: "user_id" })
- @ManyToOne(() => require("./User").User, {
- onDelete: "CASCADE",
- })
- user: import("./User").User;
-
- @Column({ default: false })
- closed: boolean;
-
- // TODO: settings/mute/nick/added at/encryption keys/read_state
-}
diff --git a/util/src/entities/Relationship.ts b/util/src/entities/Relationship.ts
deleted file mode 100644
index c3592c76..00000000
--- a/util/src/entities/Relationship.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { Column, Entity, Index, JoinColumn, ManyToOne, RelationId } from "typeorm";
-import { BaseClass } from "./BaseClass";
-import { User } from "./User";
-
-export enum RelationshipType {
- outgoing = 4,
- incoming = 3,
- blocked = 2,
- friends = 1,
-}
-
-@Entity("relationships")
-@Index(["from_id", "to_id"], { unique: true })
-export class Relationship extends BaseClass {
- @Column({})
- @RelationId((relationship: Relationship) => relationship.from)
- from_id: string;
-
- @JoinColumn({ name: "from_id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE",
- })
- from: User;
-
- @Column({})
- @RelationId((relationship: Relationship) => relationship.to)
- to_id: string;
-
- @JoinColumn({ name: "to_id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE",
- })
- to: User;
-
- @Column({ nullable: true })
- nickname?: string;
-
- @Column({ type: "int" })
- type: RelationshipType;
-
- toPublicRelationship() {
- return {
- id: this.to?.id || this.to_id,
- type: this.type,
- nickname: this.nickname,
- user: this.to?.toPublicUser(),
- };
- }
-}
diff --git a/util/src/entities/Role.ts b/util/src/entities/Role.ts
deleted file mode 100644
index 4b721b5b..00000000
--- a/util/src/entities/Role.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-
-import { BaseClass } from "./BaseClass";
-import { Guild } from "./Guild";
-
-@Entity("roles")
-export class Role extends BaseClass {
- @Column({ nullable: true })
- @RelationId((role: Role) => role.guild)
- guild_id: string;
-
- @JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild, {
- onDelete: "CASCADE",
- })
- guild: Guild;
-
- @Column()
- color: number;
-
- @Column()
- hoist: boolean;
-
- @Column()
- managed: boolean;
-
- @Column()
- mentionable: boolean;
-
- @Column()
- name: string;
-
- @Column()
- permissions: string;
-
- @Column()
- position: number;
-
- @Column({ nullable: true })
- icon: string;
-
- @Column({ nullable: true })
- unicode_emoji: string;
-
- @Column({ type: "simple-json", nullable: true })
- tags?: {
- bot_id?: string;
- integration_id?: string;
- premium_subscriber?: boolean;
- };
-}
diff --git a/util/src/entities/Session.ts b/util/src/entities/Session.ts
deleted file mode 100644
index 969efa89..00000000
--- a/util/src/entities/Session.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-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";
-
-//TODO we need to remove all sessions on server start because if the server crashes without closing websockets it won't delete them
-
-@Entity("sessions")
-export class Session extends BaseClass {
- @Column({ nullable: true })
- @RelationId((session: Session) => session.user)
- user_id: string;
-
- @JoinColumn({ name: "user_id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE",
- })
- user: User;
-
- //TODO check, should be 32 char long hex string
- @Column({ nullable: false, select: false })
- session_id: string;
-
- @Column({ type: "simple-json", nullable: true })
- activities: Activity[];
-
- // TODO client_status
- @Column({ type: "simple-json", select: false })
- client_info: {
- client: string;
- os: string;
- version: number;
- };
-
- @Column({ nullable: false, type: "varchar" })
- status: Status; //TODO enum
-}
-
-export const PrivateSessionProjection: (keyof Session)[] = [
- "user_id",
- "session_id",
- "activities",
- "client_info",
- "status",
-];
diff --git a/util/src/entities/Sticker.ts b/util/src/entities/Sticker.ts
deleted file mode 100644
index 37bc6fbe..00000000
--- a/util/src/entities/Sticker.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-import { User } from "./User";
-import { BaseClass } from "./BaseClass";
-import { Guild } from "./Guild";
-
-export enum StickerType {
- STANDARD = 1,
- GUILD = 2,
-}
-
-export enum StickerFormatType {
- GIF = 0, // gif is a custom format type and not in discord spec
- PNG = 1,
- APNG = 2,
- LOTTIE = 3,
-}
-
-@Entity("stickers")
-export class Sticker extends BaseClass {
- @Column()
- name: string;
-
- @Column({ nullable: true })
- description?: string;
-
- @Column({ nullable: true })
- available?: boolean;
-
- @Column({ nullable: true })
- tags?: string;
-
- @Column({ nullable: true })
- @RelationId((sticker: Sticker) => sticker.pack)
- pack_id?: string;
-
- @JoinColumn({ name: "pack_id" })
- @ManyToOne(() => require("./StickerPack").StickerPack, {
- onDelete: "CASCADE",
- nullable: true,
- })
- pack: import("./StickerPack").StickerPack;
-
- @Column({ nullable: true })
- guild_id?: string;
-
- @JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild, {
- onDelete: "CASCADE",
- })
- guild?: Guild;
-
- @Column({ nullable: true })
- user_id?: string;
-
- @JoinColumn({ name: "user_id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE",
- })
- user?: User;
-
- @Column({ type: "int" })
- type: StickerType;
-
- @Column({ type: "int" })
- format_type: StickerFormatType;
-}
diff --git a/util/src/entities/StickerPack.ts b/util/src/entities/StickerPack.ts
deleted file mode 100644
index ec8c69a2..00000000
--- a/util/src/entities/StickerPack.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, OneToMany, OneToOne, RelationId } from "typeorm";
-import { Sticker } from ".";
-import { BaseClass } from "./BaseClass";
-
-@Entity("sticker_packs")
-export class StickerPack extends BaseClass {
- @Column()
- name: string;
-
- @Column({ nullable: true })
- description?: string;
-
- @Column({ nullable: true })
- banner_asset_id?: string;
-
- @OneToMany(() => Sticker, (sticker: Sticker) => sticker.pack, {
- cascade: true,
- orphanedRowAction: "delete",
- })
- stickers: Sticker[];
-
- // sku_id: string
-
- @Column({ nullable: true })
- @RelationId((pack: StickerPack) => pack.cover_sticker)
- cover_sticker_id?: string;
-
- @ManyToOne(() => Sticker, { nullable: true })
- @JoinColumn()
- cover_sticker?: Sticker;
-}
diff --git a/util/src/entities/Team.ts b/util/src/entities/Team.ts
deleted file mode 100644
index 22140b7f..00000000
--- a/util/src/entities/Team.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, OneToMany, RelationId } from "typeorm";
-import { BaseClass } from "./BaseClass";
-import { TeamMember } from "./TeamMember";
-import { User } from "./User";
-
-@Entity("teams")
-export class Team extends BaseClass {
- @Column({ nullable: true })
- icon?: string;
-
- @JoinColumn({ name: "member_ids" })
- @OneToMany(() => TeamMember, (member: TeamMember) => member.team, {
- orphanedRowAction: "delete",
- })
- members: TeamMember[];
-
- @Column()
- name: string;
-
- @Column({ nullable: true })
- @RelationId((team: Team) => team.owner_user)
- owner_user_id: string;
-
- @JoinColumn({ name: "owner_user_id" })
- @ManyToOne(() => User)
- owner_user: User;
-}
diff --git a/util/src/entities/TeamMember.ts b/util/src/entities/TeamMember.ts
deleted file mode 100644
index b726e1e8..00000000
--- a/util/src/entities/TeamMember.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-import { BaseClass } from "./BaseClass";
-import { User } from "./User";
-
-export enum TeamMemberState {
- INVITED = 1,
- ACCEPTED = 2,
-}
-
-@Entity("team_members")
-export class TeamMember extends BaseClass {
- @Column({ type: "int" })
- membership_state: TeamMemberState;
-
- @Column({ type: "simple-array" })
- permissions: string[];
-
- @Column({ nullable: true })
- @RelationId((member: TeamMember) => member.team)
- team_id: string;
-
- @JoinColumn({ name: "team_id" })
- @ManyToOne(() => require("./Team").Team, (team: import("./Team").Team) => team.members, {
- onDelete: "CASCADE",
- })
- team: import("./Team").Team;
-
- @Column({ nullable: true })
- @RelationId((member: TeamMember) => member.user)
- user_id: string;
-
- @JoinColumn({ name: "user_id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE",
- })
- user: User;
-}
diff --git a/util/src/entities/Template.ts b/util/src/entities/Template.ts
deleted file mode 100644
index 1d952283..00000000
--- a/util/src/entities/Template.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-import { BaseClass } from "./BaseClass";
-import { Guild } from "./Guild";
-import { User } from "./User";
-
-@Entity("templates")
-export class Template extends BaseClass {
- @Column({ unique: true })
- code: string;
-
- @Column()
- name: string;
-
- @Column({ nullable: true })
- description?: string;
-
- @Column({ nullable: true })
- usage_count?: number;
-
- @Column({ nullable: true })
- @RelationId((template: Template) => template.creator)
- creator_id: string;
-
- @JoinColumn({ name: "creator_id" })
- @ManyToOne(() => User)
- creator: User;
-
- @Column()
- created_at: Date;
-
- @Column()
- updated_at: Date;
-
- @Column({ nullable: true })
- @RelationId((template: Template) => template.source_guild)
- source_guild_id: string;
-
- @JoinColumn({ name: "source_guild_id" })
- @ManyToOne(() => Guild)
- source_guild: Guild;
-
- @Column({ type: "simple-json" })
- serialized_source_guild: Guild;
-}
diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts
deleted file mode 100644
index 61343e81..00000000
--- a/util/src/entities/User.ts
+++ /dev/null
@@ -1,324 +0,0 @@
-import { Column, Entity, FindOneOptions, FindOptionsSelectByString, JoinColumn, OneToMany, OneToOne } from "typeorm";
-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 ".";
-
-export enum PublicUserEnum {
- username,
- discriminator,
- id,
- public_flags,
- avatar,
- accent_color,
- banner,
- bio,
- bot,
- premium_since,
-}
-export type PublicUserKeys = keyof typeof PublicUserEnum;
-
-export enum PrivateUserEnum {
- flags,
- mfa_enabled,
- email,
- phone,
- verified,
- nsfw_allowed,
- premium,
- premium_type,
- disabled,
- settings,
- // locale
-}
-export type PrivateUserKeys = keyof typeof PrivateUserEnum | 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"),
-] as PrivateUserKeys[];
-
-// Private user data that should never get sent to the client
-export type PublicUser = Pick<User, PublicUserKeys>;
-
-export interface UserPublic extends Pick<User, PublicUserKeys> {}
-
-export interface UserPrivate extends Pick<User, PrivateUserKeys> {
- locale: string;
-}
-
-// TODO: add purchased_flags, premium_usage_flags
-
-@Entity("users")
-export class User extends BaseClass {
- @Column()
- username: string; // username max length 32, min 2 (should be configurable)
-
- @Column()
- discriminator: string; // opaque string: 4 digits on discord.com
-
- setDiscriminator(val: string) {
- const number = Number(val);
- if (isNaN(number)) throw new Error("invalid discriminator");
- if (number <= 0 || number >= 10000) throw new Error("discriminator must be between 1 and 9999");
- this.discriminator = val.toString().padStart(4, "0");
- }
-
- @Column({ nullable: true })
- avatar?: string; // hash of the user avatar
-
- @Column({ nullable: true })
- accent_color?: number; // banner color of user
-
- @Column({ nullable: true })
- banner?: string; // hash of the user banner
-
- @Column({ nullable: true, select: false })
- phone?: string; // phone number of the user
-
- @Column({ select: false })
- desktop: boolean = false; // if the user has desktop app installed
-
- @Column({ select: false })
- mobile: boolean = false; // if the user has mobile app installed
-
- @Column()
- premium: boolean = Config.get().defaults.user.premium; // if user bought individual premium
-
- @Column()
- premium_type: number = Config.get().defaults.user.premium_type; // individual premium level
-
- @Column()
- bot: boolean = false; // if user is bot
-
- @Column()
- bio: string; // short description of the user (max 190 chars -> should be configurable)
-
- @Column()
- system: boolean = false; // shouldn't be used, the api sends this field type true, if the generated message comes from a system generated author
-
- @Column({ select: false })
- nsfw_allowed: boolean = true; // if the user can do age-restricted actions (NSFW channels/guilds/commands) // TODO: depending on age
-
- @Column({ select: false })
- mfa_enabled: boolean; // if multi factor authentication is enabled
-
- @Column({ select: false, nullable: true })
- totp_secret?: string;
-
- @Column({ nullable: true, select: false })
- totp_last_ticket?: string;
-
- @Column()
- created_at: Date = new Date(); // registration date
-
- @Column({ nullable: true })
- premium_since: Date = new Date(); // premium date
-
- @Column({ select: false })
- verified: boolean = Config.get().defaults.user.verified; // if the user is offically verified
-
- @Column()
- disabled: boolean = false; // if the account is disabled
-
- @Column()
- deleted: boolean = false; // if the user was deleted
-
- @Column({ nullable: true, select: false })
- email?: string; // email of the user
-
- @Column()
- flags: string = "0"; // UserFlags // TODO: generate
-
- @Column()
- public_flags: number = 0;
-
- @Column({ type: "bigint" })
- rights: string = Config.get().register.defaultRights; // Rights
-
- @OneToMany(() => Session, (session: Session) => session.user)
- sessions: Session[];
-
- @JoinColumn({ name: "relationship_ids" })
- @OneToMany(() => Relationship, (relationship: Relationship) => relationship.from, {
- cascade: true,
- orphanedRowAction: "delete",
- })
- relationships: Relationship[];
-
- @JoinColumn({ name: "connected_account_ids" })
- @OneToMany(() => ConnectedAccount, (account: ConnectedAccount) => account.user, {
- cascade: true,
- orphanedRowAction: "delete",
- })
- connected_accounts: ConnectedAccount[];
-
- @Column({ type: "simple-json", select: false })
- data: {
- valid_tokens_since: Date; // all tokens with a previous issue date are invalid
- hash?: string; // hash of the password, salt is saved in password (bcrypt)
- };
-
- @Column({ type: "simple-array", select: false })
- fingerprints: string[] = []; // array of fingerprints -> used to prevent multiple accounts
-
-
- @OneToOne(()=> UserSettings, {
- cascade: true,
- orphanedRowAction: "delete",
- eager: false
- })
- @JoinColumn()
- settings: UserSettings;
-
- // workaround to prevent fossord-unaware clients from deleting settings not used by them
- @Column({ type: "simple-json", select: false })
- extended_settings: string = "{}";
-
- @Column({ type: "simple-json" })
- notes: { [key: string]: string } = {}; //key is ID of user
-
- async save(): Promise<any> {
- if(!this.settings) this.settings = new UserSettings();
- this.settings.id = this.id;
- //await this.settings.save();
- return super.save();
- }
-
- toPublicUser() {
- const user: any = {};
- PublicUserProjection.forEach((x) => {
- user[x] = this[x];
- });
- return user as PublicUser;
- }
-
- static async getPublicUser(user_id: string, opts?: FindOneOptions<User>) {
- return await User.findOneOrFail({
- where: { id: user_id },
- select: [...PublicUserProjection, ...((opts?.select as FindOptionsSelectByString<User>) || [])],
- ...opts,
- });
- }
-
- public static async generateDiscriminator(username: string): Promise<string | undefined> {
- if (Config.get().register.incrementingDiscriminators) {
- // discriminator will be incrementally generated
-
- // First we need to figure out the currently highest discrimnator for the given username and then increment it
- const users = await User.find({ where: { username }, select: ["discriminator"] });
- const highestDiscriminator = Math.max(0, ...users.map((u) => Number(u.discriminator)));
-
- const discriminator = highestDiscriminator + 1;
- if (discriminator >= 10000) {
- return undefined;
- }
-
- return discriminator.toString().padStart(4, "0");
- } else {
- // discriminator will be randomly generated
-
- // randomly generates a discriminator between 1 and 9999 and checks max five times if it already exists
- // TODO: is there any better way to generate a random discriminator only once, without checking if it already exists in the database?
- for (let tries = 0; tries < 5; tries++) {
- const discriminator = Math.randomIntBetween(1, 9999).toString().padStart(4, "0");
- const exists = await User.findOne({ where: { discriminator, username: username }, select: ["id"] });
- if (!exists) return discriminator;
- }
-
- return undefined;
- }
- }
-
- static async register({
- email,
- username,
- password,
- date_of_birth,
- req,
- }: {
- username: string;
- password?: string;
- email?: string;
- date_of_birth?: Date; // "2000-04-03"
- req?: any;
- }) {
- // trim special uf8 control characters -> Backspace, Newline, ...
- username = trimSpecial(username);
-
- const discriminator = await User.generateDiscriminator(username);
- if (!discriminator) {
- // We've failed to generate a valid and unused discriminator
- throw FieldErrors({
- username: {
- code: "USERNAME_TOO_MANY_USERS",
- message: req?.t("auth:register.USERNAME_TOO_MANY_USERS"),
- },
- });
- }
-
- // TODO: save date_of_birth
- // 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 user = OrmUtils.mergeDeep(new User(), {
- //required:
- username: username,
- discriminator,
- id: Snowflake.generate(),
- email: email,
- data: {
- hash: password,
- valid_tokens_since: new Date(),
- },
- settings: { ...new UserSettings(), locale: language }
- });
-
- 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) => {});
- }
- }
- });
-
- return user;
- }
-}
-
-export const CUSTOM_USER_FLAG_OFFSET = BigInt(1) << BigInt(32);
-
-export class UserFlags extends BitField {
- static FLAGS = {
- DISCORD_EMPLOYEE: BigInt(1) << BigInt(0),
- PARTNERED_SERVER_OWNER: BigInt(1) << BigInt(1),
- HYPESQUAD_EVENTS: BigInt(1) << BigInt(2),
- BUGHUNTER_LEVEL_1: BigInt(1) << BigInt(3),
- MFA_SMS: BigInt(1) << BigInt(4),
- PREMIUM_PROMO_DISMISSED: BigInt(1) << BigInt(5),
- HOUSE_BRAVERY: BigInt(1) << BigInt(6),
- HOUSE_BRILLIANCE: BigInt(1) << BigInt(7),
- HOUSE_BALANCE: BigInt(1) << BigInt(8),
- EARLY_SUPPORTER: BigInt(1) << BigInt(9),
- TEAM_USER: BigInt(1) << BigInt(10),
- TRUST_AND_SAFETY: BigInt(1) << BigInt(11),
- SYSTEM: BigInt(1) << BigInt(12),
- HAS_UNREAD_URGENT_MESSAGES: BigInt(1) << BigInt(13),
- BUGHUNTER_LEVEL_2: BigInt(1) << BigInt(14),
- UNDERAGE_DELETED: BigInt(1) << BigInt(15),
- 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),
- };
-}
diff --git a/util/src/entities/UserGroup.ts b/util/src/entities/UserGroup.ts
deleted file mode 100644
index 709b9d0b..00000000
--- a/util/src/entities/UserGroup.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-
-import { BaseClass } from "./BaseClass";
-import { Guild } from "./Guild";
-import { User } from "./User";
-
-@Entity("groups")
-export class UserGroup extends BaseClass {
- @Column()
- color: number;
-
- @Column()
- hoist: boolean;
-
- @JoinColumn({ name: "controller", referencedColumnName: "id" })
- @ManyToOne(() => User)
- controller?: User;
-
- @Column()
- mentionable_by?: string;
-
- @Column()
- name: string;
-
- @Column()
- rights: string;
-
- @Column({ nullable: true })
- icon: string;
-
- @Column({ nullable: true })
- parent?: string;
-
- @Column({ type: "simple-array", nullable: true})
- associciations: string[];
-
-}
diff --git a/util/src/entities/UserSettings.ts b/util/src/entities/UserSettings.ts
deleted file mode 100644
index ef6f95af..00000000
--- a/util/src/entities/UserSettings.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-import { Column, Entity, JoinColumn } from "typeorm";
-import { BaseClassWithoutId, PrimaryIdColumn } from ".";
-
-@Entity("user_settings")
-export class UserSettings extends BaseClassWithoutId {
- @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
-}
-
-interface CustomStatus {
- emoji_id?: string;
- emoji_name?: string;
- expires_at?: number;
- text?: string;
-}
-
-interface GuildFolder {
- color: number;
- guild_ids: string[];
- id: number;
- name: string;
-}
-
-interface FriendSourceFlags {
- all: boolean
-}
\ No newline at end of file
diff --git a/util/src/entities/VoiceState.ts b/util/src/entities/VoiceState.ts
deleted file mode 100644
index 75748a01..00000000
--- a/util/src/entities/VoiceState.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-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";
-
-//https://gist.github.com/vassjozsef/e482c65df6ee1facaace8b3c9ff66145#file-voice_state-ex
-@Entity("voice_states")
-export class VoiceState extends BaseClass {
- @Column({ nullable: true })
- @RelationId((voice_state: VoiceState) => voice_state.guild)
- guild_id: string;
-
- @JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild, {
- onDelete: "CASCADE",
- })
- guild?: Guild;
-
- @Column({ nullable: true })
- @RelationId((voice_state: VoiceState) => voice_state.channel)
- channel_id: string;
-
- @JoinColumn({ name: "channel_id" })
- @ManyToOne(() => Channel, {
- onDelete: "CASCADE",
- })
- channel: Channel;
-
- @Column({ nullable: true })
- @RelationId((voice_state: VoiceState) => voice_state.user)
- user_id: string;
-
- @JoinColumn({ name: "user_id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE",
- })
- user: 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;
-
- @Column()
- session_id: string;
-
- @Column({ nullable: true })
- token: string;
-
- @Column()
- deaf: boolean;
-
- @Column()
- mute: boolean;
-
- @Column()
- self_deaf: boolean;
-
- @Column()
- self_mute: boolean;
-
- @Column({ nullable: true })
- self_stream?: boolean;
-
- @Column()
- self_video: boolean;
-
- @Column()
- suppress: boolean; // whether this user is muted by the current user
-
- @Column({ nullable: true, default: null })
- request_to_speak_timestamp?: Date;
-}
diff --git a/util/src/entities/Webhook.ts b/util/src/entities/Webhook.ts
deleted file mode 100644
index 89538417..00000000
--- a/util/src/entities/Webhook.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-import { Application } from "./Application";
-import { BaseClass } from "./BaseClass";
-import { Channel } from "./Channel";
-import { Guild } from "./Guild";
-import { User } from "./User";
-
-export enum WebhookType {
- Incoming = 1,
- ChannelFollower = 2,
-}
-
-@Entity("webhooks")
-export class Webhook extends BaseClass {
- @Column({ type: "int" })
- type: WebhookType;
-
- @Column({ nullable: true })
- name?: string;
-
- @Column({ nullable: true })
- avatar?: string;
-
- @Column({ nullable: true })
- token?: string;
-
- @Column({ nullable: true })
- @RelationId((webhook: Webhook) => webhook.guild)
- guild_id: string;
-
- @JoinColumn({ name: "guild_id" })
- @ManyToOne(() => Guild, {
- onDelete: "CASCADE",
- })
- guild: Guild;
-
- @Column({ nullable: true })
- @RelationId((webhook: Webhook) => webhook.channel)
- channel_id: string;
-
- @JoinColumn({ name: "channel_id" })
- @ManyToOne(() => Channel, {
- onDelete: "CASCADE",
- })
- channel: Channel;
-
- @Column({ nullable: true })
- @RelationId((webhook: Webhook) => webhook.application)
- application_id: string;
-
- @JoinColumn({ name: "application_id" })
- @ManyToOne(() => Application, {
- onDelete: "CASCADE",
- })
- application: Application;
-
- @Column({ nullable: true })
- @RelationId((webhook: Webhook) => webhook.user)
- user_id: string;
-
- @JoinColumn({ name: "user_id" })
- @ManyToOne(() => User, {
- onDelete: "CASCADE",
- })
- user: User;
-
- @Column({ nullable: true })
- @RelationId((webhook: Webhook) => webhook.guild)
- source_guild_id: string;
-
- @JoinColumn({ name: "source_guild_id" })
- @ManyToOne(() => Guild, {
- onDelete: "CASCADE",
- })
- source_guild: Guild;
-}
diff --git a/util/src/entities/index.ts b/util/src/entities/index.ts
deleted file mode 100644
index c6f12022..00000000
--- a/util/src/entities/index.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-export * from "./Application";
-export * from "./Attachment";
-export * from "./AuditLog";
-export * from "./Ban";
-export * from "./BaseClass";
-export * from "./Categories";
-export * from "./Channel";
-export * from "./Config";
-export * from "./ConnectedAccount";
-export * from "./Emoji";
-export * from "./Guild";
-export * from "./Invite";
-export * from "./Member";
-export * from "./Message";
-export * from "./Migration";
-export * from "./RateLimit";
-export * from "./ReadState";
-export * from "./Recipient";
-export * from "./Relationship";
-export * from "./Role";
-export * from "./Session";
-export * from "./Sticker";
-export * from "./StickerPack";
-export * from "./Team";
-export * from "./TeamMember";
-export * from "./Template";
-export * from "./User";
-export * from "./VoiceState";
-export * from "./Webhook";
-export * from "./ClientRelease";
-export * from "./BackupCodes";
-export * from "./Note";
-export * from "./UserSettings";
|