diff --git a/util/src/entities/Application.ts b/util/src/entities/Application.ts
index 64b5d2e2..90d0f056 100644
--- a/util/src/entities/Application.ts
+++ b/util/src/entities/Application.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { Guild } from "./Guild";
import { Team } from "./Team";
@@ -38,14 +38,14 @@ export class Application extends BaseClass {
@Column()
verify_key: string;
- @Column()
+ @RelationId((application: Application) => application.team)
team_id: string;
@JoinColumn({ name: "team_id" })
@ManyToOne(() => Team, (team: Team) => team.id)
team?: Team;
- @Column()
+ @RelationId((application: Application) => application.guild)
guild_id: string;
@JoinColumn({ name: "guild_id" })
diff --git a/util/src/entities/AuditLog.ts b/util/src/entities/AuditLog.ts
index 53e99261..2195771b 100644
--- a/util/src/entities/AuditLog.ts
+++ b/util/src/entities/AuditLog.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { ChannelPermissionOverwrite } from "./Channel";
import { User } from "./User";
@@ -43,14 +43,14 @@ export enum AuditLogEvents {
@Entity("audit_logs")
export class AuditLogEntry extends BaseClass {
- @Column()
+ @RelationId((auditlog: AuditLogEntry) => auditlog.target)
target_id: string;
@JoinColumn({ name: "user_id" })
@ManyToOne(() => User, (user: User) => user.id)
target?: User;
- @Column()
+ @RelationId((auditlog: AuditLogEntry) => auditlog.user)
user_id: string;
@JoinColumn({ name: "user_id" })
diff --git a/util/src/entities/Ban.ts b/util/src/entities/Ban.ts
index ceea4a05..2553e886 100644
--- a/util/src/entities/Ban.ts
+++ b/util/src/entities/Ban.ts
@@ -1,25 +1,25 @@
-import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
+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()
+ @RelationId((ban: Ban) => ban.user)
user_id: string;
@JoinColumn({ name: "user_id" })
@ManyToOne(() => User, (user: User) => user.id)
user: User;
- @Column()
+ @RelationId((ban: Ban) => ban.guild)
guild_id: string;
@JoinColumn({ name: "guild_id" })
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
guild: Guild;
- @Column()
+ @RelationId((ban: Ban) => ban.executor)
executor_id: string;
@JoinColumn({ name: "executor_id" })
diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts
index 5845607a..d26f1054 100644
--- a/util/src/entities/Channel.ts
+++ b/util/src/entities/Channel.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToMany, ManyToOne } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { Guild } from "./Guild";
import { Message } from "./Message";
@@ -25,35 +25,35 @@ export class Channel extends BaseClass {
@Column({ type: "simple-enum", enum: ChannelType })
type: ChannelType;
- @Column("simple-array")
+ @RelationId((channel: Channel) => channel.recipients)
recipient_ids: string[];
@JoinColumn({ name: "recipient_ids" })
@ManyToMany(() => User, (user: User) => user.id)
recipients?: User[];
- @Column()
+ @RelationId((channel: Channel) => channel.last_message)
last_message_id: string;
@JoinColumn({ name: "last_message_id" })
@ManyToOne(() => Message, (message: Message) => message.id)
last_message?: Message;
- @Column()
+ @RelationId((channel: Channel) => channel.guild)
guild_id?: string;
@JoinColumn({ name: "guild_id" })
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
guild: Guild;
- @Column()
+ @RelationId((channel: Channel) => channel.parent)
parent_id: string;
@JoinColumn({ name: "parent_id" })
@ManyToOne(() => Channel, (channel: Channel) => channel.id)
parent?: Channel;
- @Column()
+ @RelationId((channel: Channel) => channel.owner)
owner_id: string;
@JoinColumn({ name: "owner_id" })
diff --git a/util/src/entities/Config.ts b/util/src/entities/Config.ts
new file mode 100644
index 00000000..60d84958
--- /dev/null
+++ b/util/src/entities/Config.ts
@@ -0,0 +1,274 @@
+import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
+import { Snowflake } from "../util";
+import { BaseClass } from "./BaseClass";
+import crypto from "crypto";
+
+@Entity("config")
+export class ConfigEntity extends BaseClass {
+ @Column("simple-json")
+ value: ConfigValue;
+}
+
+export interface RateLimitOptions {
+ bot?: number;
+ count: number;
+ window: number;
+ onyIp?: boolean;
+}
+
+export interface Region {
+ id: string;
+ name: string;
+ vip: boolean;
+ custom: boolean;
+ deprecated: boolean;
+ optimal: boolean;
+}
+
+export interface KafkaBroker {
+ ip: string;
+ port: number;
+}
+
+export interface ConfigValue {
+ gateway: {
+ endpointClient: string | null;
+ endpoint: string | null;
+ };
+ cdn: {
+ endpointClient: string | null;
+ endpoint: string | null;
+ };
+ general: {
+ instance_id: string;
+ };
+ permissions: {
+ user: {
+ createGuilds: boolean;
+ };
+ };
+ limits: {
+ user: {
+ maxGuilds: number;
+ maxUsername: number;
+ maxFriends: number;
+ };
+ guild: {
+ maxRoles: number;
+ maxMembers: number;
+ maxChannels: number;
+ maxChannelsInCategory: number;
+ hideOfflineMember: number;
+ };
+ message: {
+ maxCharacters: number;
+ maxTTSCharacters: number;
+ maxReactions: number;
+ maxAttachmentSize: number;
+ maxBulkDelete: number;
+ };
+ channel: {
+ maxPins: number;
+ maxTopic: number;
+ };
+ rate: {
+ ip: Omit<RateLimitOptions, "bot_count">;
+ global: RateLimitOptions;
+ error: RateLimitOptions;
+ routes: {
+ guild: RateLimitOptions;
+ webhook: RateLimitOptions;
+ channel: RateLimitOptions;
+ auth: {
+ login: RateLimitOptions;
+ register: RateLimitOptions;
+ };
+ // TODO: rate limit configuration for all routes
+ };
+ };
+ };
+ security: {
+ autoUpdate: boolean | number;
+ requestSignature: string;
+ jwtSecret: string;
+ forwadedFor: string | null; // header to get the real user ip address
+ captcha: {
+ enabled: boolean;
+ service: "recaptcha" | "hcaptcha" | null; // TODO: hcaptcha, custom
+ sitekey: string | null;
+ secret: string | null;
+ };
+ ipdataApiKey: string | null;
+ };
+ login: {
+ requireCaptcha: boolean;
+ };
+ register: {
+ email: {
+ necessary: boolean; // we have to use necessary instead of required as the cli tool uses json schema and can't use required
+ allowlist: boolean;
+ blocklist: boolean;
+ domains: string[];
+ };
+ dateOfBirth: {
+ necessary: boolean;
+ minimum: number; // in years
+ };
+ requireCaptcha: boolean;
+ requireInvite: boolean;
+ allowNewRegistration: boolean;
+ allowMultipleAccounts: boolean;
+ blockProxies: boolean;
+ password: {
+ minLength: number;
+ minNumbers: number;
+ minUpperCase: number;
+ minSymbols: number;
+ };
+ };
+ regions: {
+ default: string;
+ available: Region[];
+ };
+ rabbitmq: {
+ host: string | null;
+ };
+ kafka: {
+ brokers: KafkaBroker[] | null;
+ };
+}
+
+export const DefaultConfigOptions: ConfigValue = {
+ gateway: {
+ endpointClient: null,
+ endpoint: null,
+ },
+ cdn: {
+ endpointClient: null,
+ endpoint: null,
+ },
+ general: {
+ instance_id: Snowflake.generate(),
+ },
+ permissions: {
+ user: {
+ createGuilds: true,
+ },
+ },
+ limits: {
+ user: {
+ maxGuilds: 100,
+ maxUsername: 32,
+ maxFriends: 1000,
+ },
+ guild: {
+ maxRoles: 250,
+ maxMembers: 250000,
+ maxChannels: 500,
+ maxChannelsInCategory: 50,
+ hideOfflineMember: 1000,
+ },
+ message: {
+ maxCharacters: 2000,
+ maxTTSCharacters: 200,
+ maxReactions: 20,
+ maxAttachmentSize: 8388608,
+ maxBulkDelete: 100,
+ },
+ channel: {
+ maxPins: 50,
+ maxTopic: 1024,
+ },
+ rate: {
+ ip: {
+ count: 500,
+ window: 5,
+ },
+ global: {
+ count: 20,
+ window: 5,
+ bot: 250,
+ },
+ error: {
+ count: 10,
+ window: 5,
+ },
+ routes: {
+ guild: {
+ count: 5,
+ window: 5,
+ },
+ webhook: {
+ count: 5,
+ window: 20,
+ },
+ channel: {
+ count: 5,
+ window: 20,
+ },
+ auth: {
+ login: {
+ count: 5,
+ window: 60,
+ },
+ register: {
+ count: 2,
+ window: 60 * 60 * 12,
+ },
+ },
+ },
+ },
+ },
+ security: {
+ autoUpdate: true,
+ requestSignature: crypto.randomBytes(32).toString("base64"),
+ jwtSecret: crypto.randomBytes(256).toString("base64"),
+ forwadedFor: null,
+ // forwadedFor: "X-Forwarded-For" // nginx/reverse proxy
+ // forwadedFor: "CF-Connecting-IP" // cloudflare:
+ captcha: {
+ enabled: false,
+ service: null,
+ sitekey: null,
+ secret: null,
+ },
+ ipdataApiKey: "eca677b284b3bac29eb72f5e496aa9047f26543605efe99ff2ce35c9",
+ },
+ login: {
+ requireCaptcha: false,
+ },
+ register: {
+ email: {
+ necessary: true,
+ allowlist: false,
+ blocklist: true,
+ domains: [], // TODO: efficiently save domain blocklist in database
+ // domains: fs.readFileSync(__dirname + "/blockedEmailDomains.txt", { encoding: "utf8" }).split("\n"),
+ },
+ dateOfBirth: {
+ necessary: true,
+ minimum: 13,
+ },
+ requireInvite: false,
+ requireCaptcha: true,
+ allowNewRegistration: true,
+ allowMultipleAccounts: true,
+ blockProxies: true,
+ password: {
+ minLength: 8,
+ minNumbers: 2,
+ minUpperCase: 2,
+ minSymbols: 0,
+ },
+ },
+ regions: {
+ default: "fosscord",
+ available: [{ id: "fosscord", name: "Fosscord", vip: false, custom: false, deprecated: false, optimal: false }],
+ },
+ rabbitmq: {
+ host: null,
+ },
+ kafka: {
+ brokers: null,
+ },
+};
diff --git a/util/src/entities/Emoji.ts b/util/src/entities/Emoji.ts
index 366549db..b31ddb3b 100644
--- a/util/src/entities/Emoji.ts
+++ b/util/src/entities/Emoji.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToMany, ManyToOne } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { Guild } from "./Guild";
import { Role } from "./Role";
@@ -30,7 +30,7 @@ export class Emoji extends BaseClass {
@Column()
url: string;
- @Column("simple-array")
+ @RelationId((emoji: Emoji) => emoji.roles)
role_ids: string[];
@JoinColumn({ name: "role_ids" })
diff --git a/util/src/entities/Guild.ts b/util/src/entities/Guild.ts
index d46d31bc..d7b4dff4 100644
--- a/util/src/entities/Guild.ts
+++ b/util/src/entities/Guild.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, OneToOne } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, OneToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { Channel } from "./Channel";
import { Emoji } from "./Emoji";
@@ -10,7 +10,7 @@ import { VoiceState } from "./VoiceState";
@Entity("guilds")
export class Guild extends BaseClass {
- @Column()
+ @RelationId((guild: Guild) => guild.afk_channel)
afk_channel_id?: string;
@JoinColumn({ name: "afk_channel_id" })
@@ -64,35 +64,35 @@ export class Guild extends BaseClass {
@Column()
presence_count?: number; // users online
- @Column("simple-array")
+ @RelationId((guild: Guild) => guild.members)
member_ids: string[];
@JoinColumn({ name: "member_ids" })
@ManyToMany(() => Member, (member: Member) => member.id)
members: Member[];
- @Column("simple-array")
+ @RelationId((guild: Guild) => guild.roles)
role_ids: string[];
@JoinColumn({ name: "role_ids" })
@ManyToMany(() => Role, (role: Role) => role.id)
roles: Role[];
- @Column("simple-array")
+ @RelationId((guild: Guild) => guild.channels)
channel_ids: string[];
@JoinColumn({ name: "channel_ids" })
@ManyToMany(() => Channel, (channel: Channel) => channel.id)
channels: Channel[];
- @Column("simple-array")
+ @RelationId((guild: Guild) => guild.emojis)
emoji_ids: string[];
@JoinColumn({ name: "emoji_ids" })
@ManyToMany(() => Emoji, (emoji: Emoji) => emoji.id)
emojis: Emoji[];
- @Column("simple-array")
+ @RelationId((guild: Guild) => guild.voice_states)
voice_state_ids: string[];
@JoinColumn({ name: "voice_state_ids" })
@@ -105,7 +105,7 @@ export class Guild extends BaseClass {
@Column()
name: string;
- @Column()
+ @RelationId((guild: Guild) => guild.owner)
owner_id: string;
@JoinColumn({ name: "owner_id" })
@@ -121,11 +121,14 @@ export class Guild extends BaseClass {
@Column()
premium_tier?: number; // nitro boost level
+ @RelationId((guild: Guild) => guild.public_updates_channel)
+ public_updates_channel_id: string;
+
@JoinColumn({ name: "public_updates_channel_id" })
@ManyToOne(() => Channel, (channel: Channel) => channel.id)
public_updates_channel?: Channel;
- @Column()
+ @RelationId((guild: Guild) => guild.rules_channel)
rules_channel_id?: string;
@JoinColumn({ name: "rules_channel_id" })
@@ -138,7 +141,7 @@ export class Guild extends BaseClass {
@Column()
splash?: string;
- @Column()
+ @RelationId((guild: Guild) => guild.system_channel)
system_channel_id?: string;
@JoinColumn({ name: "system_channel_id" })
@@ -151,6 +154,9 @@ export class Guild extends BaseClass {
@Column()
unavailable?: boolean;
+ @RelationId((guild: Guild) => guild.vanity_url)
+ vanity_url_code?: string;
+
@JoinColumn({ name: "vanity_url_code" })
@OneToOne(() => Invite, (invite: Invite) => invite.code)
vanity_url?: Invite;
@@ -170,6 +176,9 @@ export class Guild extends BaseClass {
}[];
};
+ @RelationId((guild: Guild) => guild.widget_channel)
+ widget_channel_id?: string;
+
@JoinColumn({ name: "widget_channel_id" })
@ManyToOne(() => Channel, (channel: Channel) => channel.id)
widget_channel?: Channel;
diff --git a/util/src/entities/Invite.ts b/util/src/entities/Invite.ts
index 19f7206a..eac0cba0 100644
--- a/util/src/entities/Invite.ts
+++ b/util/src/entities/Invite.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { Channel } from "./Channel";
import { Guild } from "./Guild";
@@ -27,29 +27,29 @@ export class Invite extends BaseClass {
@Column()
expires_at: Date;
- @Column()
+ @RelationId((invite: Invite) => invite.guild)
guild_id: string;
@JoinColumn({ name: "guild_id" })
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
guild: Guild;
- @Column()
+ @RelationId((invite: Invite) => invite.channel)
channel_id: string;
@JoinColumn({ name: "channel_id" })
@ManyToOne(() => Channel, (channel: Channel) => channel.id)
channel: Channel;
- @Column()
+ @RelationId((invite: Invite) => invite.inviter)
inviter_id: string;
@JoinColumn({ name: "inviter_id" })
@ManyToOne(() => User, (user: User) => user.id)
inviter: User;
- @Column()
- target_usser_id: string;
+ @RelationId((invite: Invite) => invite.target_user)
+ target_user_id: string;
@JoinColumn({ name: "target_user_id" })
@ManyToOne(() => User, (user: User) => user.id)
diff --git a/util/src/entities/Member.ts b/util/src/entities/Member.ts
index c367755e..01634d9e 100644
--- a/util/src/entities/Member.ts
+++ b/util/src/entities/Member.ts
@@ -1,18 +1,18 @@
import { PublicUser, User } from "./User";
import { BaseClass } from "./BaseClass";
-import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
import { Guild } from "./Guild";
@Entity("members")
export class Member extends BaseClass {
- @Column()
+ @RelationId((member: Member) => member.user)
user_id: string;
@JoinColumn({ name: "user_id" })
@ManyToOne(() => User, (user: User) => user.id)
user: User;
- @Column()
+ @RelationId((member: Member) => member.guild)
guild_id: string;
@JoinColumn({ name: "guild_id" })
diff --git a/util/src/entities/Message.ts b/util/src/entities/Message.ts
index 2c0918c7..9daf042c 100644
--- a/util/src/entities/Message.ts
+++ b/util/src/entities/Message.ts
@@ -4,7 +4,16 @@ import { Role } from "./Role";
import { Channel } from "./Channel";
import { InteractionType } from "../interfaces/Interaction";
import { Application } from "./Application";
-import { Column, CreateDateColumn, Entity, JoinColumn, ManyToMany, ManyToOne, UpdateDateColumn } from "typeorm";
+import {
+ Column,
+ CreateDateColumn,
+ Entity,
+ JoinColumn,
+ ManyToMany,
+ ManyToOne,
+ RelationId,
+ UpdateDateColumn,
+} from "typeorm";
import { BaseClass } from "./BaseClass";
import { Guild } from "./Guild";
import { Webhook } from "./Webhook";
@@ -34,42 +43,42 @@ export class Message extends BaseClass {
@Column()
id: string;
- @Column()
+ @RelationId((message: Message) => message.channel)
channel_id: string;
@JoinColumn({ name: "channel_id" })
@ManyToOne(() => Channel, (channel: Channel) => channel.id)
channel: Channel;
- @Column()
+ @RelationId((message: Message) => message.guild)
guild_id: string;
@JoinColumn({ name: "guild_id" })
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
guild?: Guild;
- @Column()
+ @RelationId((message: Message) => message.author)
author_id: string;
@JoinColumn({ name: "author_id" })
@ManyToOne(() => User, (user: User) => user.id)
author?: User;
- @Column()
+ @RelationId((message: Message) => message.member)
member_id: string;
@JoinColumn({ name: "member_id" })
@ManyToOne(() => Member, (member: Member) => member.id)
member?: Member;
- @Column()
+ @RelationId((message: Message) => message.webhook)
webhook_id: string;
@JoinColumn({ name: "webhook_id" })
@ManyToOne(() => Webhook, (webhook: Webhook) => webhook.id)
webhook?: Webhook;
- @Column()
+ @RelationId((message: Message) => message.application)
application_id: string;
@JoinColumn({ name: "application_id" })
@@ -93,21 +102,21 @@ export class Message extends BaseClass {
@Column()
mention_everyone?: boolean;
- @Column("simple-array")
+ @RelationId((message: Message) => message.mention_users)
mention_user_ids: string[];
@JoinColumn({ name: "mention_user_ids" })
@ManyToMany(() => User, (user: User) => user.id)
mention_users: User[];
- @Column("simple-array")
+ @RelationId((message: Message) => message.mention_roles)
mention_role_ids: string[];
@JoinColumn({ name: "mention_role_ids" })
@ManyToMany(() => Role, (role: Role) => role.id)
mention_roles: Role[];
- @Column("simple-array")
+ @RelationId((message: Message) => message.mention_channels)
mention_channel_ids: string[];
@JoinColumn({ name: "mention_channel_ids" })
diff --git a/util/src/entities/RateLimit.ts b/util/src/entities/RateLimit.ts
index 374a0759..3ac35df3 100644
--- a/util/src/entities/RateLimit.ts
+++ b/util/src/entities/RateLimit.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { User } from "./User";
@@ -7,7 +7,7 @@ export class RateLimit extends BaseClass {
@Column()
id: "global" | "error" | string; // channel_239842397 | guild_238927349823 | webhook_238923423498
- @Column()
+ @RelationId((rate_limit: RateLimit) => rate_limit.user)
user_id: string;
@JoinColumn({ name: "user_id" })
diff --git a/util/src/entities/ReadState.ts b/util/src/entities/ReadState.ts
index 7c56b6c6..0310cb5f 100644
--- a/util/src/entities/ReadState.ts
+++ b/util/src/entities/ReadState.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { Channel } from "./Channel";
import { Message } from "./Message";
@@ -6,20 +6,23 @@ import { User } from "./User";
@Entity("read_states")
export class ReadState extends BaseClass {
- @Column()
+ @RelationId((read_state: ReadState) => read_state.channel)
channel_id: string;
@JoinColumn({ name: "channel_id" })
@ManyToOne(() => Channel, (channel: Channel) => channel.id)
channel: Channel;
- @Column()
+ @RelationId((read_state: ReadState) => read_state.user)
user_id: string;
@JoinColumn({ name: "user_id" })
@ManyToOne(() => User, (user: User) => user.id)
user: User;
+ @RelationId((read_state: ReadState) => read_state.last_message)
+ last_message_id: string;
+
@JoinColumn({ name: "last_message_id" })
@ManyToOne(() => Message, (message: Message) => message.id)
last_message?: Message;
diff --git a/util/src/entities/Relationship.ts b/util/src/entities/Relationship.ts
index bd5861f0..3e1280c7 100644
--- a/util/src/entities/Relationship.ts
+++ b/util/src/entities/Relationship.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToOne, OneToMany } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { User } from "./User";
@@ -11,7 +11,7 @@ export enum RelationshipType {
@Entity("relationships")
export class Relationship extends BaseClass {
- @Column()
+ @RelationId((relationship: Relationship) => relationship.user)
user_id: string;
@JoinColumn({ name: "user_id" })
diff --git a/util/src/entities/Role.ts b/util/src/entities/Role.ts
index 7bb144cc..e48fd293 100644
--- a/util/src/entities/Role.ts
+++ b/util/src/entities/Role.ts
@@ -1,10 +1,10 @@
-import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { Guild } from "./Guild";
@Entity("roles")
export class Role extends BaseClass {
- @Column()
+ @RelationId((role: Role) => role.guild)
guild_id: string;
@JoinColumn({ name: "guild_id" })
diff --git a/util/src/entities/Team.ts b/util/src/entities/Team.ts
index 5e645650..fa1b0ed2 100644
--- a/util/src/entities/Team.ts
+++ b/util/src/entities/Team.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToMany, ManyToOne } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { TeamMember } from "./TeamMember";
import { User } from "./User";
@@ -8,7 +8,7 @@ export class Team extends BaseClass {
@Column()
icon?: string;
- @Column("simple-array")
+ @RelationId((team: Team) => team.members)
member_ids: string[];
@JoinColumn({ name: "member_ids" })
@@ -18,7 +18,7 @@ export class Team extends BaseClass {
@Column()
name: string;
- @Column()
+ @RelationId((team: Team) => team.owner_user)
owner_user_id: string;
@JoinColumn({ name: "owner_user_id" })
diff --git a/util/src/entities/TeamMember.ts b/util/src/entities/TeamMember.ts
index 2b1c76f1..f0b54c6f 100644
--- a/util/src/entities/TeamMember.ts
+++ b/util/src/entities/TeamMember.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { User } from "./User";
@@ -15,14 +15,14 @@ export class TeamMember extends BaseClass {
@Column("simple-array")
permissions: string[];
- @Column()
+ @RelationId((member: TeamMember) => member.team)
team_id: string;
@JoinColumn({ name: "team_id" })
@ManyToOne(() => require("./Team").Team, (team: import("./Team").Team) => team.id)
team: import("./Team").Team;
- @Column()
+ @RelationId((member: TeamMember) => member.user)
user_id: string;
@JoinColumn({ name: "user_id" })
diff --git a/util/src/entities/Template.ts b/util/src/entities/Template.ts
index 5c9a5120..c8d2034c 100644
--- a/util/src/entities/Template.ts
+++ b/util/src/entities/Template.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { Guild } from "./Guild";
import { User } from "./User";
@@ -17,6 +17,9 @@ export class Template extends BaseClass {
@Column()
usage_count?: number;
+ @RelationId((template: Template) => template.creator)
+ creator_id: string;
+
@JoinColumn({ name: "creator_id" })
@ManyToOne(() => User, (user: User) => user.id)
creator: User;
@@ -27,6 +30,9 @@ export class Template extends BaseClass {
@Column()
updated_at: Date;
+ @RelationId((template: Template) => template.source_guild)
+ source_guild_id: string;
+
@JoinColumn({ name: "source_guild_id" })
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
source_guild: Guild;
diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts
index 39e59da4..bdf0d35f 100644
--- a/util/src/entities/User.ts
+++ b/util/src/entities/User.ts
@@ -1,8 +1,10 @@
-import { Column, Entity, JoinColumn, OneToMany } from "typeorm";
+import { Column, Entity, JoinColumn, OneToMany, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { BitField } from "../util/BitField";
import { Relationship } from "./Relationship";
import { ConnectedAccount } from "./ConnectedAccount";
+import { HTTPError } from "lambert-server";
+import { Guild } from "./Guild";
export const PublicUserProjection = {
username: true,
@@ -24,6 +26,13 @@ export class User extends BaseClass {
@Column()
discriminator: string; // #0001 4 digit long string from #0001 - #9999
+ 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;
+ }
+
@Column()
avatar?: string; // hash of the user avatar
@@ -84,17 +93,21 @@ export class User extends BaseClass {
@Column({ type: "bigint" })
public_flags: bigint;
- @Column("simple-array") // string in simple-array must not contain commas
- guilds: string[]; // array of guild ids the user is part of
+ @RelationId((user: User) => user.guilds)
+ guild_ids: string[]; // array of guild ids the user is part of
+
+ @JoinColumn({ name: "guild_ids" })
+ @OneToMany(() => Guild, (guild: Guild) => guild.id)
+ guilds: Guild[];
- @Column("simple-array") // string in simple-array must not contain commas
+ @RelationId((user: User) => user.relationships)
relationship_ids: string[]; // array of guild ids the user is part of
@JoinColumn({ name: "relationship_ids" })
@OneToMany(() => User, (user: User) => user.id)
relationships: Relationship[];
- @Column("simple-array") // string in simple-array must not contain commas
+ @RelationId((user: User) => user.connected_accounts)
connected_account_ids: string[]; // array of guild ids the user is part of
@JoinColumn({ name: "connected_account_ids" })
@@ -102,14 +115,28 @@ export class User extends BaseClass {
connected_accounts: ConnectedAccount[];
@Column({ type: "simple-json", select: false })
- user_data: {
+ 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)
- fingerprints: string[]; // array of fingerprints -> used to prevent multiple accounts
};
+ @Column({ type: "simple-array" })
+ fingerprints: string[]; // array of fingerprints -> used to prevent multiple accounts
+
@Column("simple-json")
settings: UserSettings;
+
+ static async getPublicUser(user_id: string, additional_fields?: any) {
+ const user = await User.findOne(
+ { id: user_id },
+ {
+ ...PublicUserProjection,
+ ...additional_fields,
+ }
+ );
+ if (!user) throw new HTTPError("User not found", 404);
+ return user;
+ }
}
export interface UserSettings {
diff --git a/util/src/entities/VoiceState.ts b/util/src/entities/VoiceState.ts
index 2416c6c0..6707a575 100644
--- a/util/src/entities/VoiceState.ts
+++ b/util/src/entities/VoiceState.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToOne, OneToOne } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, OneToOne, RelationId } from "typeorm";
import { BaseClass } from "./BaseClass";
import { Channel } from "./Channel";
import { Guild } from "./Guild";
@@ -6,14 +6,23 @@ import { User } from "./User";
@Entity("voice_states")
export class VoiceState extends BaseClass {
+ @RelationId((voice_state: VoiceState) => voice_state.guild)
+ guild_id: string;
+
@JoinColumn({ name: "guild_id" })
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
guild?: Guild;
+ @RelationId((voice_state: VoiceState) => voice_state.channel)
+ channel_id: string;
+
@JoinColumn({ name: "channel_id" })
@ManyToOne(() => Channel, (channel: Channel) => channel.id)
channel: Channel;
+ @RelationId((voice_state: VoiceState) => voice_state.user)
+ user_id: string;
+
@JoinColumn({ name: "user_id" })
@ManyToOne(() => User, (user: User) => user.id)
user: User;
diff --git a/util/src/entities/Webhook.ts b/util/src/entities/Webhook.ts
index 54233638..dc929c18 100644
--- a/util/src/entities/Webhook.ts
+++ b/util/src/entities/Webhook.ts
@@ -1,5 +1,9 @@
-import { Column, Entity, JoinColumn } from "typeorm";
+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,
@@ -23,18 +27,38 @@ export class Webhook extends BaseClass {
@Column()
token?: string;
- @JoinColumn()
- guild?: string;
+ @RelationId((webhook: Webhook) => webhook.guild)
+ guild_id: string;
- @JoinColumn()
- channel: string;
+ @JoinColumn({ name: "guild_id" })
+ @ManyToOne(() => Guild, (guild: Guild) => guild.id)
+ guild: Guild;
- @JoinColumn()
- application?: string;
+ @RelationId((webhook: Webhook) => webhook.channel)
+ channel_id: string;
- @JoinColumn()
- user?: string;
+ @JoinColumn({ name: "channel_id" })
+ @ManyToOne(() => Channel, (channel: Channel) => channel.id)
+ channel: Channel;
- @JoinColumn()
- source_guild: string;
+ @RelationId((webhook: Webhook) => webhook.application)
+ application_id: string;
+
+ @JoinColumn({ name: "application_id" })
+ @ManyToOne(() => Application, (application: Application) => application.id)
+ application: Application;
+
+ @RelationId((webhook: Webhook) => webhook.user)
+ user_id: string;
+
+ @JoinColumn({ name: "user_id" })
+ @ManyToOne(() => User, (user: User) => user.id)
+ user: User;
+
+ @RelationId((webhook: Webhook) => webhook.guild)
+ source_guild_id: string;
+
+ @JoinColumn({ name: "source_guild_id" })
+ @ManyToOne(() => Guild, (guild: Guild) => guild.id)
+ source_guild: Guild;
}
diff --git a/util/src/entities/index.ts b/util/src/entities/index.ts
index 9cb10016..b9e361c1 100644
--- a/util/src/entities/index.ts
+++ b/util/src/entities/index.ts
@@ -3,6 +3,7 @@ export * from "./AuditLog";
export * from "./Ban";
export * from "./BaseClass";
export * from "./Channel";
+export * from "./Config";
export * from "./ConnectedAccount";
export * from "./Emoji";
export * from "./Guild";
|