summary refs log tree commit diff
path: root/util/src/entities/Channel.ts
diff options
context:
space:
mode:
Diffstat (limited to 'util/src/entities/Channel.ts')
-rw-r--r--util/src/entities/Channel.ts98
1 files changed, 82 insertions, 16 deletions
diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts
index 4900f485..e3586dfc 100644
--- a/util/src/entities/Channel.ts
+++ b/util/src/entities/Channel.ts
@@ -1,8 +1,12 @@
-import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, RelationId } from "typeorm";
+import { Column, Entity, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToMany, RelationId } 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";
 
 export enum ChannelType {
 	GUILD_TEXT = 0, // a text channel within a server
@@ -25,40 +29,39 @@ 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[];
+	@OneToMany(() => Recipient, (recipient: Recipient) => recipient.channel, { cascade: true })
+	recipients?: Recipient[];
 
+	@Column({ nullable: true })
 	@RelationId((channel: Channel) => channel.last_message)
 	last_message_id: string;
 
 	@JoinColumn({ name: "last_message_id" })
-	@ManyToOne(() => Message, (message: Message) => message.id)
+	@ManyToOne(() => Message)
 	last_message?: Message;
 
+	@Column({ nullable: true })
 	@RelationId((channel: Channel) => channel.guild)
 	guild_id?: string;
 
 	@JoinColumn({ name: "guild_id" })
-	@ManyToOne(() => Guild, (guild: Guild) => guild.id)
+	@ManyToOne(() => Guild)
 	guild: Guild;
 
+	@Column({ nullable: true })
 	@RelationId((channel: Channel) => channel.parent)
 	parent_id: string;
 
 	@JoinColumn({ name: "parent_id" })
-	@ManyToOne(() => Channel, (channel: Channel) => channel.id)
+	@ManyToOne(() => Channel)
 	parent?: Channel;
 
+	@Column({ nullable: true })
 	@RelationId((channel: Channel) => channel.owner)
 	owner_id: string;
 
 	@JoinColumn({ name: "owner_id" })
-	@ManyToOne(() => User, (user: User) => user.id)
+	@ManyToOne(() => User)
 	owner: User;
 
 	@Column({ nullable: true })
@@ -82,14 +85,77 @@ export class Channel extends BaseClass {
 	@Column({ nullable: true })
 	user_limit?: number;
 
-	@Column()
-	nsfw: boolean;
+	@Column({ nullable: true })
+	nsfw?: boolean;
 
-	@Column()
-	rate_limit_per_user: number;
+	@Column({ nullable: true })
+	rate_limit_per_user?: number;
 
 	@Column({ nullable: true })
 	topic?: string;
+
+	// TODO: DM channel
+	static async createChannel(
+		channel: Partial<Channel>,
+		user_id: string = "0",
+		opts?: {
+			keepId?: boolean;
+			skipExistsCheck?: boolean;
+			skipPermissionCheck?: boolean;
+			skipEventEmit?: boolean;
+		}
+	) {
+		if (!opts?.skipPermissionCheck) {
+			// Always check if user has permission first
+			const permissions = await getPermission(user_id, channel.guild_id);
+			permissions.hasThrow("MANAGE_CHANNELS");
+		}
+
+		switch (channel.type) {
+			case ChannelType.GUILD_TEXT:
+			case ChannelType.GUILD_VOICE:
+				if (channel.parent_id && !opts?.skipExistsCheck) {
+					const exists = await Channel.findOneOrFail({ 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:
+				break;
+			case ChannelType.DM:
+			case ChannelType.GROUP_DM:
+				throw new HTTPError("You can't create a dm channel in a guild");
+			// TODO: check if guild is community server
+			case ChannelType.GUILD_STORE:
+			case ChannelType.GUILD_NEWS:
+			default:
+				throw new HTTPError("Not yet supported");
+		}
+
+		if (!channel.permission_overwrites) channel.permission_overwrites = [];
+		// TODO: auto generate position
+
+		channel = {
+			...channel,
+			...(!opts?.keepId && { id: Snowflake.generate() }),
+			created_at: new Date(),
+			position: channel.position || 0,
+		};
+
+		await Promise.all([
+			Channel.insert(channel),
+			!opts?.skipEventEmit
+				? emitEvent({
+						event: "CHANNEL_CREATE",
+						data: channel,
+						guild_id: channel.guild_id,
+				  } as ChannelCreateEvent)
+				: Promise.resolve(),
+		]);
+
+		return channel;
+	}
 }
 
 export interface ChannelPermissionOverwrite {