1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
import { Channel, ChannelType, Message, PublicUserProjection, Recipient, User } from "../entities";
import { HTTPError } from "lambert-server";
import { emitEvent, trimSpecial } from "../util";
import { DmChannelDTO } from "../dtos";
import { ChannelRecipientRemoveEvent } from "../interfaces";
export function checker(arr: any[], target: any[]) {
return target.every(v => arr.includes(v));
}
export class ChannelService {
public 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 (checker(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])
}
public 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 ChannelService.deleteChannel(channel);
await emitEvent({
event: "CHANNEL_DELETE",
data: await DmChannelDTO.from(channel, [user_id]),
user_id: user_id
});
return
}
let channel_dto = null;
//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?
channel_dto = await DmChannelDTO.from(channel, [user_id])
await emitEvent({
event: "CHANNEL_UPDATE",
data: channel_dto,
channel_id: channel.id
});
}
await channel.save()
await emitEvent({
event: "CHANNEL_DELETE",
data: channel_dto !== null ? channel_dto : await DmChannelDTO.from(channel, [user_id]),
user_id: user_id
});
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);
}
public 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 })
}
}
|