Merge branch 'master' into auto-delete-relations

This commit is contained in:
Flam3rboy committed 2021-09-19 19:09:13 +02:00
commit ffe179758e
32 files changed
+1039 -680

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
import { MinimalPublicUserDTO } from "./UserDTO";
import { Channel, PublicUserProjection, User } from "../entities";
export class DmChannelDTO {
icon: string | null;
id: string;
last_message_id: string | null;
name: string | null;
origin_channel_id: string | null;
owner_id?: string;
recipients: MinimalPublicUserDTO[];
type: number;
static async from(channel: Channel, excluded_recipients: string[] = [], origin_channel_id?: string) {
const obj = new DmChannelDTO()
obj.icon = channel.icon || null
obj.id = channel.id
obj.last_message_id = channel.last_message_id || null
obj.name = channel.name || null
obj.origin_channel_id = origin_channel_id || null
obj.owner_id = channel.owner_id
obj.type = channel.type
obj.recipients = (await Promise.all(channel.recipients!.filter(r => !excluded_recipients.includes(r.user_id)).map(async r => {
return await User.findOneOrFail({ where: { id: r.user_id }, select: PublicUserProjection })
}))).map(u => new MinimalPublicUserDTO(u))
return obj
}
excludedRecipients(excluded_recipients: string[]): DmChannelDTO {
return {
...this,
recipients: this.recipients.filter(r => !excluded_recipients.includes(r.id))
}
}
}
+17
View File
@@ -0,0 +1,17 @@
import { User } from "../entities";
export class MinimalPublicUserDTO {
avatar?: string | null;
discriminator: string;
id: string;
public_flags: number;
username: string;
constructor(user: User) {
this.avatar = user.avatar
this.discriminator = user.discriminator
this.id = user.id
this.public_flags = user.public_flags
this.username = user.username
}
}
+2
View File
@@ -0,0 +1,2 @@
export * from "./DmChannelDTO";
export * from "./UserDTO";
+117 -3
View File
@@ -11,16 +11,17 @@ import {
} from "typeorm";
import { BaseClass } from "./BaseClass";
import { Guild } from "./Guild";
import { User } from "./User";
import { PublicUserProjection, User } from "./User";
import { HTTPError } from "lambert-server";
import { emitEvent, getPermission, Snowflake } from "../util";
import { ChannelCreateEvent } from "../interfaces";
import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial } 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 server
@@ -214,6 +215,119 @@ export class Channel extends BaseClass {
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 (otherRecipientsUsers.length !== recipients.length) {
throw new HTTPError("Recipient/s not found");
}
const type = recipients.length === 1 ? ChannelType.DM : ChannelType.GROUP_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;
await ur.assign({ closed: false }).save();
}
}
}
}
if (channel == null) {
name = trimSpecial(name);
channel = await new Channel({
name,
type,
owner_id: type === ChannelType.DM ? undefined : creator_user_id,
created_at: new Date(),
last_message_id: null,
recipients: channelRecipients.map(
(x) =>
new Recipient({ user_id: x, closed: !(type === ChannelType.GROUP_DM || x === creator_user_id) })
),
}).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 });
}
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 we make the first recipient in the list the new owner
if (channel.owner_id === user_id) {
channel.owner_id = channel.recipients!.find((r) => r.user_id !== user_id)!.user_id; //Is there a criteria to choose the new owner?
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;
}
+3
View File
@@ -19,5 +19,8 @@ export class Recipient extends BaseClass {
@ManyToOne(() => require("./User").User)
user: import("./User").User;
@Column({ default: false })
closed: boolean;
// TODO: settings/mute/nick/added at/encryption keys/read_state
}
+1 -1
View File
@@ -124,7 +124,7 @@ export class User extends BaseClass {
flags: string; // UserFlags
@Column()
public_flags: string;
public_flags: number;
@JoinColumn({ name: "relationship_ids" })
@OneToMany(() => Relationship, (relationship: Relationship) => relationship.from)
+1
View File
@@ -4,6 +4,7 @@ import "reflect-metadata";
export * from "./util/index";
export * from "./interfaces/index";
export * from "./entities/index";
export * from "./dtos/index";
// import Config from "../util/Config";
// import db, { MongooseCache, toObject } from "./util/Database";
+22
View File
@@ -127,6 +127,22 @@ export interface ChannelPinsUpdateEvent extends Event {
};
}
export interface ChannelRecipientAddEvent extends Event {
event: "CHANNEL_RECIPIENT_ADD";
data: {
channel_id: string;
user: User;
};
}
export interface ChannelRecipientRemoveEvent extends Event {
event: "CHANNEL_RECIPIENT_REMOVE";
data: {
channel_id: string;
user: User;
};
}
export interface GuildCreateEvent extends Event {
event: "GUILD_CREATE";
data: Guild & {
@@ -436,6 +452,8 @@ export type EventData =
| ChannelUpdateEvent
| ChannelDeleteEvent
| ChannelPinsUpdateEvent
| ChannelRecipientAddEvent
| ChannelRecipientRemoveEvent
| GuildCreateEvent
| GuildUpdateEvent
| GuildDeleteEvent
@@ -482,6 +500,8 @@ export enum EVENTEnum {
ChannelUpdate = "CHANNEL_UPDATE",
ChannelDelete = "CHANNEL_DELETE",
ChannelPinsUpdate = "CHANNEL_PINS_UPDATE",
ChannelRecipientAdd = "CHANNEL_RECIPIENT_ADD",
ChannelRecipientRemove = "CHANNEL_RECIPIENT_REMOVE",
GuildCreate = "GUILD_CREATE",
GuildUpdate = "GUILD_UPDATE",
GuildDelete = "GUILD_DELETE",
@@ -525,6 +545,8 @@ export type EVENT =
| "CHANNEL_UPDATE"
| "CHANNEL_DELETE"
| "CHANNEL_PINS_UPDATE"
| "CHANNEL_RECIPIENT_ADD"
| "CHANNEL_RECIPIENT_REMOVE"
| "GUILD_CREATE"
| "GUILD_UPDATE"
| "GUILD_DELETE"
+3
View File
@@ -0,0 +1,3 @@
export function containsAll(arr: any[], target: any[]) {
return target.every(v => arr.includes(v));
}
+1
View File
@@ -92,6 +92,7 @@ export class Permissions extends BitField {
}
overwriteChannel(overwrites: ChannelPermissionOverwrite[]) {
if (!overwrites) return this
if (!this.cache) throw new Error("permission chache not available");
overwrites = overwrites.filter((x) => {
if (x.type === 0 && this.cache.roles?.some((r) => r.id === x.id)) return true;
+1
View File
@@ -13,3 +13,4 @@ export * from "./RabbitMQ";
export * from "./Regex";
export * from "./Snowflake";
export * from "./String";
export * from "./Array";