diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts
index fc954f63..0196fb3e 100644
--- a/util/src/entities/Channel.ts
+++ b/util/src/entities/Channel.ts
@@ -1,12 +1,26 @@
-import { Column, Entity, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToMany, RelationId } from "typeorm";
+import {
+ Column,
+ Entity,
+ FindConditions,
+ JoinColumn,
+ ManyToOne,
+ ObjectID,
+ OneToMany,
+ RelationId,
+ RemoveOptions,
+} from "typeorm";
import { BaseClass } from "./BaseClass";
import { Guild } from "./Guild";
-import { Message } from "./Message";
import { User } from "./User";
import { HTTPError } from "lambert-server";
import { emitEvent, getPermission, Snowflake } from "../util";
import { ChannelCreateEvent } 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";
export enum ChannelType {
GUILD_TEXT = 0, // a text channel within a server
@@ -31,20 +45,22 @@ export class Channel extends BaseClass {
@Column({ nullable: true })
name?: string;
+ @Column({ type: "text", nullable: true })
+ icon?: string | null;
+
@Column({ type: "simple-enum", enum: ChannelType })
type: ChannelType;
- @OneToMany(() => Recipient, (recipient: Recipient) => recipient.channel, { cascade: true })
+ @OneToMany(() => Recipient, (recipient: Recipient) => recipient.channel, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ onDelete: "CASCADE",
+ })
recipients?: Recipient[];
@Column({ nullable: true })
- @RelationId((channel: Channel) => channel.last_message)
last_message_id: string;
- @JoinColumn({ name: "last_message_id" })
- @ManyToOne(() => Message)
- last_message?: Message;
-
@Column({ nullable: true })
@RelationId((channel: Channel) => channel.guild)
guild_id?: string;
@@ -100,6 +116,41 @@ export class Channel extends BaseClass {
@Column({ nullable: true })
topic?: string;
+ @OneToMany(() => Invite, (invite: Invite) => invite.channel, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ onDelete: "CASCADE",
+ })
+ invites?: Invite[];
+
+ @OneToMany(() => Message, (message: Message) => message.channel, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ onDelete: "CASCADE",
+ })
+ messages?: Message[];
+
+ @OneToMany(() => VoiceState, (voice_state: VoiceState) => voice_state.channel, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ onDelete: "CASCADE",
+ })
+ voice_states?: VoiceState[];
+
+ @OneToMany(() => ReadState, (read_state: ReadState) => read_state.channel, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ onDelete: "CASCADE",
+ })
+ read_states?: ReadState[];
+
+ @OneToMany(() => Webhook, (webhook: Webhook) => webhook.channel, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ onDelete: "CASCADE",
+ })
+ webhooks?: Webhook[];
+
// TODO: DM channel
static async createChannel(
channel: Partial<Channel>,
@@ -162,6 +213,10 @@ export class Channel extends BaseClass {
return channel;
}
+
+ isDm() {
+ return this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM;
+ }
}
export interface ChannelPermissionOverwrite {
diff --git a/util/src/entities/Guild.ts b/util/src/entities/Guild.ts
index 7b5d2908..d46d2161 100644
--- a/util/src/entities/Guild.ts
+++ b/util/src/entities/Guild.ts
@@ -81,7 +81,11 @@ export class Guild extends BaseClass {
// application?: string;
@JoinColumn({ name: "ban_ids" })
- @OneToMany(() => Ban, (ban: Ban) => ban.guild)
+ @OneToMany(() => Ban, (ban: Ban) => ban.guild, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ onDelete: "CASCADE",
+ })
bans: Ban[];
@Column({ nullable: true })
@@ -124,15 +128,27 @@ export class Guild extends BaseClass {
@Column({ nullable: true })
presence_count?: number; // users online
- @OneToMany(() => Member, (member: Member) => member.guild)
+ @OneToMany(() => Member, (member: Member) => member.guild, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ onDelete: "CASCADE",
+ })
members: Member[];
@JoinColumn({ name: "role_ids" })
- @OneToMany(() => Role, (role: Role) => role.guild)
+ @OneToMany(() => Role, (role: Role) => role.guild, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ onDelete: "CASCADE",
+ })
roles: Role[];
@JoinColumn({ name: "channel_ids" })
- @OneToMany(() => Channel, (channel: Channel) => channel.guild)
+ @OneToMany(() => Channel, (channel: Channel) => channel.guild, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ onDelete: "CASCADE",
+ })
channels: Channel[];
@Column({ nullable: true })
@@ -144,23 +160,43 @@ export class Guild extends BaseClass {
template: Template;
@JoinColumn({ name: "emoji_ids" })
- @OneToMany(() => Emoji, (emoji: Emoji) => emoji.guild)
+ @OneToMany(() => Emoji, (emoji: Emoji) => emoji.guild, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ onDelete: "CASCADE",
+ })
emojis: Emoji[];
@JoinColumn({ name: "sticker_ids" })
- @OneToMany(() => Sticker, (sticker: Sticker) => sticker.guild)
+ @OneToMany(() => Sticker, (sticker: Sticker) => sticker.guild, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ onDelete: "CASCADE",
+ })
stickers: Sticker[];
@JoinColumn({ name: "invite_ids" })
- @OneToMany(() => Invite, (invite: Invite) => invite.guild)
+ @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)
+ @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)
+ @OneToMany(() => Webhook, (webhook: Webhook) => webhook.guild, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ onDelete: "CASCADE",
+ })
webhooks: Webhook[];
@Column({ nullable: true })
diff --git a/util/src/entities/Message.ts b/util/src/entities/Message.ts
index 506db71a..0712f545 100644
--- a/util/src/entities/Message.ts
+++ b/util/src/entities/Message.ts
@@ -8,12 +8,14 @@ import {
Column,
CreateDateColumn,
Entity,
+ FindConditions,
JoinColumn,
JoinTable,
ManyToMany,
ManyToOne,
OneToMany,
RelationId,
+ RemoveOptions,
UpdateDateColumn,
} from "typeorm";
import { BaseClass } from "./BaseClass";
@@ -112,7 +114,7 @@ export class Message extends BaseClass {
mention_everyone?: boolean;
@JoinTable({ name: "message_user_mentions" })
- @ManyToMany(() => User)
+ @ManyToMany(() => User, { orphanedRowAction: "delete", onDelete: "CASCADE", cascade: true })
mentions: User[];
@JoinTable({ name: "message_role_mentions" })
@@ -127,8 +129,11 @@ export class Message extends BaseClass {
@ManyToMany(() => Sticker)
sticker_items?: Sticker[];
- @JoinColumn({ name: "attachment_ids" })
- @OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, { cascade: true })
+ @OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, {
+ cascade: true,
+ orphanedRowAction: "delete",
+ onDelete: "CASCADE",
+ })
attachments?: Attachment[];
@Column({ type: "simple-json" })
diff --git a/util/src/util/cdn.ts b/util/src/util/cdn.ts
new file mode 100644
index 00000000..754d6244
--- /dev/null
+++ b/util/src/util/cdn.ts
@@ -0,0 +1,54 @@
+import FormData from "form-data";
+import { HTTPError } from "lambert-server";
+import fetch from "node-fetch";
+import { Config } from "./Config";
+import multer from "multer";
+
+export async function uploadFile(path: string, file: Express.Multer.File) {
+ const form = new FormData();
+ form.append("file", file.buffer, {
+ contentType: file.mimetype,
+ filename: file.originalname,
+ });
+
+ const response = await fetch(`${Config.get().cdn.endpoint || "http://localhost:3003"}${path}`, {
+ headers: {
+ signature: Config.get().security.requestSignature,
+ ...form.getHeaders(),
+ },
+ method: "POST",
+ body: form,
+ });
+ const result = await response.json();
+
+ if (response.status !== 200) throw result;
+ return result;
+}
+
+export async function handleFile(path: string, body?: string): Promise<string | undefined> {
+ if (!body || !body.startsWith("data:")) return body;
+ try {
+ const mimetype = body.split(":")[1].split(";")[0];
+ const buffer = Buffer.from(body.split(",")[1], "base64");
+
+ // @ts-ignore
+ const { id } = await uploadFile(path, { buffer, mimetype, originalname: "banner" });
+ return id;
+ } catch (error) {
+ console.error(error);
+ throw new HTTPError("Invalid " + path);
+ }
+}
+
+export async function deleteFile(path: string) {
+ const response = await fetch(`${Config.get().cdn.endpoint || "http://localhost:3003"}${path}`, {
+ headers: {
+ signature: Config.get().security.requestSignature,
+ },
+ method: "DELETE",
+ });
+ const result = await response.json();
+
+ if (response.status !== 200) throw result;
+ return result;
+}
diff --git a/util/src/util/index.ts b/util/src/util/index.ts
index 4e92f017..1ae96da9 100644
--- a/util/src/util/index.ts
+++ b/util/src/util/index.ts
@@ -1,6 +1,7 @@
export * from "./ApiError";
export * from "./BitField";
export * from "./checkToken";
+export * from "./cdn";
export * from "./Config";
export * from "./Constants";
export * from "./Database";
|