Removed ChannelService, more fixes
This commit is contained in:
parent
97e0c8709b
commit
ada95b6c39
@ -1,4 +1,4 @@
|
|||||||
import { Channel, ChannelDeleteEvent, ChannelPermissionOverwriteType, ChannelService, ChannelType, ChannelUpdateEvent, emitEvent, Recipient } from "@fosscord/util";
|
import { Channel, ChannelDeleteEvent, ChannelPermissionOverwriteType, ChannelType, ChannelUpdateEvent, emitEvent, Recipient } from "@fosscord/util";
|
||||||
import { Request, Response, Router } from "express";
|
import { Request, Response, Router } from "express";
|
||||||
import { handleFile, route } from "@fosscord/api";
|
import { handleFile, route } from "@fosscord/api";
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ router.delete("/", route({ permission: "MANAGE_CHANNELS" }), async (req: Request
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
} else if (channel.type === ChannelType.GROUP_DM) {
|
} else if (channel.type === ChannelType.GROUP_DM) {
|
||||||
await ChannelService.removeRecipientFromChannel(channel, req.user_id)
|
await Channel.removeRecipientFromChannel(channel, req.user_id)
|
||||||
} else {
|
} else {
|
||||||
//TODO messages in this channel should be deleted before deleting the channel
|
//TODO messages in this channel should be deleted before deleting the channel
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Router, Response, Request } from "express";
|
import { Router, Response, Request } from "express";
|
||||||
import { Attachment, Channel, ChannelType, DmChannelDTO, Embed, emitEvent, getPermission, Message, MessageCreateEvent } from "@fosscord/util";
|
import { Attachment, Channel, ChannelType, DmChannelDTO, Embed, emitEvent, getPermission, Message, MessageCreateEvent, Recipient } from "@fosscord/util";
|
||||||
import { HTTPError } from "lambert-server";
|
import { HTTPError } from "lambert-server";
|
||||||
import { handleMessage, postHandleMessage, route } from "@fosscord/api";
|
import { handleMessage, postHandleMessage, route } from "@fosscord/api";
|
||||||
import multer from "multer";
|
import multer from "multer";
|
||||||
@ -150,7 +150,6 @@ router.post(
|
|||||||
return res.status(400).json(error);
|
return res.status(400).json(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//TODO querying the DB at every message post should be avoided, caching maybe?
|
|
||||||
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients", "recipients.user"] })
|
const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients", "recipients.user"] })
|
||||||
|
|
||||||
const embeds = [];
|
const embeds = [];
|
||||||
@ -184,7 +183,8 @@ router.post(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(channel.recipients!.map(async r => {
|
//Only one recipients should be closed here, since in group DMs the recipient is deleted not closed
|
||||||
|
await Promise.all(channel.recipients!.filter(r => r.closed).map(async r => {
|
||||||
r.closed = false;
|
r.closed = false;
|
||||||
return await r.save()
|
return await r.save()
|
||||||
}));
|
}));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Request, Response, Router } from "express";
|
import { Request, Response, Router } from "express";
|
||||||
import { Channel, ChannelRecipientAddEvent, ChannelService, ChannelType, DiscordApiErrors, DmChannelDTO, emitEvent, PublicUserProjection, Recipient, User } from "@fosscord/util";
|
import { Channel, ChannelRecipientAddEvent, ChannelType, DiscordApiErrors, DmChannelDTO, emitEvent, PublicUserProjection, Recipient, User } from "@fosscord/util";
|
||||||
|
|
||||||
const router: Router = Router();
|
const router: Router = Router();
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ router.put("/:user_id", async (req: Request, res: Response) => {
|
|||||||
user_id
|
user_id
|
||||||
].unique()
|
].unique()
|
||||||
|
|
||||||
const new_channel = await ChannelService.createDMChannel(recipients, req.user_id)
|
const new_channel = await Channel.createDMChannel(recipients, req.user_id)
|
||||||
return res.status(201).json(new_channel);
|
return res.status(201).json(new_channel);
|
||||||
} else {
|
} else {
|
||||||
if (channel.recipients!.map(r => r.user_id).includes(user_id)) {
|
if (channel.recipients!.map(r => r.user_id).includes(user_id)) {
|
||||||
@ -49,7 +49,7 @@ router.delete("/:user_id", async (req: Request, res: Response) => {
|
|||||||
throw DiscordApiErrors.INVALID_RECIPIENT //TODO is this the right error?
|
throw DiscordApiErrors.INVALID_RECIPIENT //TODO is this the right error?
|
||||||
}
|
}
|
||||||
|
|
||||||
await ChannelService.removeRecipientFromChannel(channel, user_id)
|
await Channel.removeRecipientFromChannel(channel, user_id)
|
||||||
|
|
||||||
return res.sendStatus(204);
|
return res.sendStatus(204);
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Request, Response, Router } from "express";
|
import { Request, Response, Router } from "express";
|
||||||
import { Recipient, ChannelService, DmChannelDTO } from "@fosscord/util";
|
import { Recipient, DmChannelDTO, Channel } from "@fosscord/util";
|
||||||
import { route } from "@fosscord/api";
|
import { route } from "@fosscord/api";
|
||||||
|
|
||||||
const router: Router = Router();
|
const router: Router = Router();
|
||||||
@ -16,7 +16,7 @@ export interface DmChannelCreateSchema {
|
|||||||
|
|
||||||
router.post("/", route({ body: "DmChannelCreateSchema" }), async (req: Request, res: Response) => {
|
router.post("/", route({ body: "DmChannelCreateSchema" }), async (req: Request, res: Response) => {
|
||||||
const body = req.body as DmChannelCreateSchema;
|
const body = req.body as DmChannelCreateSchema;
|
||||||
res.json(await ChannelService.createDMChannel(body.recipients, req.user_id, body.name));
|
res.json(await Channel.createDMChannel(body.recipients, req.user_id, body.name));
|
||||||
});
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
@ -32,7 +32,7 @@ export async function setupListener(this: WebSocket) {
|
|||||||
});
|
});
|
||||||
const guilds = members.map((x) => x.guild);
|
const guilds = members.map((x) => x.guild);
|
||||||
const recipients = await Recipient.find({
|
const recipients = await Recipient.find({
|
||||||
where: { user_id: this.user_id },
|
where: { user_id: this.user_id, closed: false },
|
||||||
relations: ["channel"],
|
relations: ["channel"],
|
||||||
});
|
});
|
||||||
const dm_channels = recipients.map((x) => x.channel);
|
const dm_channels = recipients.map((x) => x.channel);
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";
|
import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";
|
||||||
import { BaseClass } from "./BaseClass";
|
import { BaseClass } from "./BaseClass";
|
||||||
import { Guild } from "./Guild";
|
import { Guild } from "./Guild";
|
||||||
import { User } from "./User";
|
import { PublicUserProjection, User } from "./User";
|
||||||
import { HTTPError } from "lambert-server";
|
import { HTTPError } from "lambert-server";
|
||||||
import { emitEvent, getPermission, Snowflake } from "../util";
|
import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial } from "../util";
|
||||||
import { ChannelCreateEvent } from "../interfaces";
|
import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces";
|
||||||
import { Recipient } from "./Recipient";
|
import { Recipient } from "./Recipient";
|
||||||
|
import { DmChannelDTO } from "../dtos";
|
||||||
|
import { Message } from "./Message";
|
||||||
|
|
||||||
export enum ChannelType {
|
export enum ChannelType {
|
||||||
GUILD_TEXT = 0, // a text channel within a server
|
GUILD_TEXT = 0, // a text channel within a server
|
||||||
@ -97,7 +99,6 @@ export class Channel extends BaseClass {
|
|||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
topic?: string;
|
topic?: string;
|
||||||
|
|
||||||
// TODO: DM channel
|
|
||||||
static async createChannel(
|
static async createChannel(
|
||||||
channel: Partial<Channel>,
|
channel: Partial<Channel>,
|
||||||
user_id: string = "0",
|
user_id: string = "0",
|
||||||
@ -160,6 +161,113 @@ export class Channel extends BaseClass {
|
|||||||
return channel;
|
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() {
|
isDm() {
|
||||||
return this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM
|
return this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import "reflect-metadata";
|
|||||||
export * from "./util/index";
|
export * from "./util/index";
|
||||||
export * from "./interfaces/index";
|
export * from "./interfaces/index";
|
||||||
export * from "./entities/index";
|
export * from "./entities/index";
|
||||||
export * from "./services/index";
|
|
||||||
export * from "./dtos/index";
|
export * from "./dtos/index";
|
||||||
|
|
||||||
// import Config from "../util/Config";
|
// import Config from "../util/Config";
|
||||||
|
@ -1,118 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 })
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export * from "./ChannelService";
|
|
3
util/src/util/Array.ts
Normal file
3
util/src/util/Array.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export function containsAll(arr: any[], target: any[]) {
|
||||||
|
return target.every(v => arr.includes(v));
|
||||||
|
}
|
@ -12,3 +12,4 @@ export * from "./RabbitMQ";
|
|||||||
export * from "./Regex";
|
export * from "./Regex";
|
||||||
export * from "./Snowflake";
|
export * from "./Snowflake";
|
||||||
export * from "./String";
|
export * from "./String";
|
||||||
|
export * from "./Array";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user