diff options
author | Diego Magdaleno <diegomagdaleno@protonmail.com> | 2021-05-22 15:55:45 -0500 |
---|---|---|
committer | Diego Magdaleno <diegomagdaleno@protonmail.com> | 2021-05-22 15:55:45 -0500 |
commit | e4a4759e971387675d127990b53dfd8b3a443d82 (patch) | |
tree | 8f4e8101fafc01492ace38a5fa51e32f07b85e1d /src/util | |
parent | Config: Refactor config to be be in separate classes (diff) | |
download | server-e4a4759e971387675d127990b53dfd8b3a443d82.tar.xz |
Fix merge issues, update to reflect config changes and package.json
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/Channel.ts | 54 | ||||
-rw-r--r-- | src/util/Member.ts | 49 | ||||
-rw-r--r-- | src/util/Message.ts | 54 | ||||
-rw-r--r-- | src/util/instanceOf.ts | 17 |
4 files changed, 142 insertions, 32 deletions
diff --git a/src/util/Channel.ts b/src/util/Channel.ts new file mode 100644 index 00000000..c8df85bc --- /dev/null +++ b/src/util/Channel.ts @@ -0,0 +1,54 @@ +import { + ChannelCreateEvent, + ChannelModel, + ChannelType, + getPermission, + GuildModel, + Snowflake, + TextChannel, + VoiceChannel +} from "@fosscord/server-util"; +import { HTTPError } from "lambert-server"; +import { emitEvent } from "./Event"; + +// TODO: DM channel +export async function createChannel(channel: Partial<TextChannel | VoiceChannel>, user_id: string = "0") { + if (!channel.permission_overwrites) channel.permission_overwrites = []; + + switch (channel.type) { + case ChannelType.GUILD_TEXT: + case ChannelType.GUILD_VOICE: + 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"); + } + + const permissions = await getPermission(user_id, channel.guild_id); + permissions.hasThrow("MANAGE_CHANNELS"); + + if (channel.parent_id) { + const exists = await ChannelModel.findOne({ id: channel.parent_id }, { guild_id: true }).exec(); + 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"); + } + + // TODO: auto generate position + + channel = await new ChannelModel({ + ...channel, + id: Snowflake.generate(), + created_at: new Date(), + // @ts-ignore + recipients: null + }).save(); + + await emitEvent({ event: "CHANNEL_CREATE", data: channel, guild_id: channel.guild_id } as ChannelCreateEvent); + + return channel; +} diff --git a/src/util/Member.ts b/src/util/Member.ts index 2842298d..d03a8f12 100644 --- a/src/util/Member.ts +++ b/src/util/Member.ts @@ -10,7 +10,7 @@ import { RoleModel, toObject, UserModel, - GuildDocument, + GuildDocument } from "@fosscord/server-util"; import { HTTPError } from "lambert-server"; @@ -27,7 +27,7 @@ export const PublicMemberProjection = { pending: true, deaf: true, mute: true, - premium_since: true, + premium_since: true }; export async function isMember(user_id: string, guild_id: string) { @@ -59,12 +59,13 @@ export async function addMember(user_id: string, guild_id: string, cache?: { gui premium_since: undefined, deaf: false, mute: false, - pending: false, + pending: false }; await Promise.all([ new MemberModel({ ...member, + read_state: {}, settings: { channel_overrides: [], message_notifications: 0, @@ -73,8 +74,8 @@ export async function addMember(user_id: string, guild_id: string, cache?: { gui muted: false, suppress_everyone: false, suppress_roles: false, - version: 0, - }, + version: 0 + } }).save(), UserModel.updateOne({ id: user_id }, { $push: { guilds: guild_id } }).exec(), @@ -85,10 +86,10 @@ export async function addMember(user_id: string, guild_id: string, cache?: { gui data: { ...member, user, - guild_id: guild_id, + guild_id: guild_id }, - guild_id: guild_id, - } as GuildMemberAddEvent), + guild_id: guild_id + } as GuildMemberAddEvent) ]); await emitEvent({ @@ -99,7 +100,7 @@ export async function addMember(user_id: string, guild_id: string, cache?: { gui .populate({ path: "joined_at", match: { id: user.id } }) .execPopulate() ), - user_id, + user_id } as GuildCreateEvent); } @@ -115,7 +116,7 @@ export async function removeMember(user_id: string, guild_id: string) { return Promise.all([ MemberModel.deleteOne({ id: user_id, - guild_id: guild_id, + guild_id: guild_id }).exec(), UserModel.updateOne({ id: user.id }, { $pull: { guilds: guild_id } }).exec(), GuildModel.updateOne({ id: guild_id }, { $inc: { member_count: -1 } }).exec(), @@ -123,18 +124,18 @@ export async function removeMember(user_id: string, guild_id: string) { emitEvent({ event: "GUILD_DELETE", data: { - id: guild_id, + id: guild_id }, - user_id: user_id, + user_id: user_id } as GuildDeleteEvent), emitEvent({ event: "GUILD_MEMBER_REMOVE", data: { guild_id: guild_id, - user: user, + user: user }, - guild_id: guild_id, - } as GuildMemberRemoveEvent), + guild_id: guild_id + } as GuildMemberRemoveEvent) ]); } @@ -147,7 +148,7 @@ export async function addRole(user_id: string, guild_id: string, role_id: string var memberObj = await MemberModel.findOneAndUpdate( { id: user_id, - guild_id: guild_id, + guild_id: guild_id }, { $push: { roles: role_id } } ).exec(); @@ -159,9 +160,9 @@ export async function addRole(user_id: string, guild_id: string, role_id: string data: { guild_id: guild_id, user: user, - roles: memberObj.roles, + roles: memberObj.roles }, - guild_id: guild_id, + guild_id: guild_id } as GuildMemberUpdateEvent); } @@ -174,7 +175,7 @@ export async function removeRole(user_id: string, guild_id: string, role_id: str var memberObj = await MemberModel.findOneAndUpdate( { id: user_id, - guild_id: guild_id, + guild_id: guild_id }, { $pull: { roles: role_id } } ).exec(); @@ -186,9 +187,9 @@ export async function removeRole(user_id: string, guild_id: string, role_id: str data: { guild_id: guild_id, user: user, - roles: memberObj.roles, + roles: memberObj.roles }, - guild_id: guild_id, + guild_id: guild_id } as GuildMemberUpdateEvent); } @@ -198,7 +199,7 @@ export async function changeNickname(user_id: string, guild_id: string, nickname var memberObj = await MemberModel.findOneAndUpdate( { id: user_id, - guild_id: guild_id, + guild_id: guild_id }, { nick: nickname } ).exec(); @@ -210,8 +211,8 @@ export async function changeNickname(user_id: string, guild_id: string, nickname data: { guild_id: guild_id, user: user, - nick: nickname, + nick: nickname }, - guild_id: guild_id, + guild_id: guild_id } as GuildMemberUpdateEvent); } diff --git a/src/util/Message.ts b/src/util/Message.ts new file mode 100644 index 00000000..0d3cdac7 --- /dev/null +++ b/src/util/Message.ts @@ -0,0 +1,54 @@ +import { ChannelModel, MessageCreateEvent } from "@fosscord/server-util"; +import { Snowflake } from "@fosscord/server-util"; +import { MessageModel } from "@fosscord/server-util"; +import { PublicMemberProjection } from "@fosscord/server-util"; +import { toObject } from "@fosscord/server-util"; +import { getPermission } from "@fosscord/server-util"; +import { Message } from "@fosscord/server-util"; +import { HTTPError } from "lambert-server"; +import { emitEvent } from "./Event"; +// TODO: check webhook, application, system author + +export async function handleMessage(opts: Partial<Message>) { + const channel = await ChannelModel.findOne({ id: opts.channel_id }, { guild_id: true, type: true, permission_overwrites: true }).exec(); + if (!channel || !opts.channel_id) throw new HTTPError("Channel not found", 404); + // TODO: are tts messages allowed in dm channels? should permission be checked? + + const permissions = await getPermission(opts.author_id, channel.guild_id, opts.channel_id, { channel }); + permissions.hasThrow("SEND_MESSAGES"); + if (opts.tts) permissions.hasThrow("SEND_TTS_MESSAGES"); + if (opts.message_reference) { + permissions.hasThrow("READ_MESSAGE_HISTORY"); + if (opts.message_reference.guild_id !== channel.guild_id) throw new HTTPError("You can only reference messages from this guild"); + } + + if (opts.message_reference) { + if (opts.message_reference.channel_id !== opts.channel_id) throw new HTTPError("You can only reference messages from this channel"); + // TODO: should be checked if the referenced message exists? + } + + // TODO: check and put it all in the body + return { + ...opts, + guild_id: channel.guild_id, + channel_id: opts.channel_id, + // TODO: generate mentions and check permissions + mention_channels_ids: [], + mention_role_ids: [], + mention_user_ids: [], + attachments: [], // TODO: message attachments + embeds: opts.embeds || [], + reactions: opts.reactions || [], + type: opts.type ?? 0 + }; +} + +export async function sendMessage(opts: Partial<Message>) { + const message = await handleMessage({ ...opts, id: Snowflake.generate(), timestamp: new Date() }); + + const data = toObject(await new MessageModel(message).populate({ path: "member", select: PublicMemberProjection }).save()); + + await emitEvent({ event: "MESSAGE_CREATE", channel_id: opts.channel_id, data, guild_id: message.guild_id } as MessageCreateEvent); + + return data; +} diff --git a/src/util/instanceOf.ts b/src/util/instanceOf.ts index e4e58092..b67bde27 100644 --- a/src/util/instanceOf.ts +++ b/src/util/instanceOf.ts @@ -5,7 +5,8 @@ import { Tuple } from "lambert-server"; import "missing-native-js-functions"; export const OPTIONAL_PREFIX = "$"; -export const EMAIL_REGEX = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; +export const EMAIL_REGEX = + /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; export function check(schema: any) { return (req: Request, res: Response, next: NextFunction) => { @@ -27,9 +28,9 @@ export function FieldErrors(fields: Record<string, { code?: string; message: str _errors: [ { message, - code: code || "BASE_TYPE_INVALID", - }, - ], + code: code || "BASE_TYPE_INVALID" + } + ] })) ); } @@ -68,7 +69,7 @@ export function instanceOf( optional = false, errors = {}, req, - ref, + ref }: { path?: string; optional?: boolean; errors?: any; req: Request; ref?: { key: string | number; obj: any } } ): Boolean { if (!ref) ref = { obj: null, key: "" }; @@ -131,7 +132,7 @@ export function instanceOf( optional, errors: errors[i], req, - ref: { key: i, obj: value }, + ref: { key: i, obj: value } }) === true ) { delete errors[i]; @@ -153,7 +154,7 @@ export function instanceOf( throw new FieldError( "BASE_TYPE_BAD_LENGTH", req.t("common:field.BASE_TYPE_BAD_LENGTH", { - length: `${type.min} - ${type.max}`, + length: `${type.min} - ${type.max}` }) ); } @@ -185,7 +186,7 @@ export function instanceOf( optional: OPTIONAL, errors: errors[newKey], req, - ref: { key: newKey, obj: value }, + ref: { key: newKey, obj: value } }) === true ) { delete errors[newKey]; |