summary refs log tree commit diff
path: root/api/src/routes/guilds
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--api/src/routes/guilds/#guild_id/bans.ts81
-rw-r--r--api/src/routes/guilds/#guild_id/channels.ts24
-rw-r--r--api/src/routes/guilds/#guild_id/delete.ts30
-rw-r--r--api/src/routes/guilds/#guild_id/index.ts40
-rw-r--r--api/src/routes/guilds/#guild_id/invites.ts6
-rw-r--r--api/src/routes/guilds/#guild_id/members/#member_id/index.ts41
-rw-r--r--api/src/routes/guilds/#guild_id/members/#member_id/nick.ts5
-rw-r--r--api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts7
-rw-r--r--api/src/routes/guilds/#guild_id/members/index.ts26
-rw-r--r--api/src/routes/guilds/#guild_id/regions.ts9
-rw-r--r--api/src/routes/guilds/#guild_id/roles.ts86
-rw-r--r--api/src/routes/guilds/#guild_id/templates.ts74
-rw-r--r--api/src/routes/guilds/#guild_id/vanity-url.ts44
-rw-r--r--api/src/routes/guilds/#guild_id/welcome_screen.ts34
-rw-r--r--api/src/routes/guilds/#guild_id/widget.json.ts99
-rw-r--r--api/src/routes/guilds/#guild_id/widget.png.ts4
-rw-r--r--api/src/routes/guilds/#guild_id/widget.ts6
-rw-r--r--api/src/routes/guilds/index.ts104
-rw-r--r--api/src/routes/guilds/templates/index.ts34
19 files changed, 307 insertions, 447 deletions
diff --git a/api/src/routes/guilds/#guild_id/bans.ts b/api/src/routes/guilds/#guild_id/bans.ts

index bb3eac03..b84a68a7 100644 --- a/api/src/routes/guilds/#guild_id/bans.ts +++ b/api/src/routes/guilds/#guild_id/bans.ts
@@ -1,30 +1,25 @@ import { Request, Response, Router } from "express"; -import { BanModel, emitEvent, getPermission, GuildBanAddEvent, GuildBanRemoveEvent, GuildModel, toObject } from "@fosscord/util"; +import { emitEvent, getPermission, GuildBanAddEvent, GuildBanRemoveEvent, Guild, Ban, User, Member } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { getIpAdress } from "../../../util/ipAddress"; import { BanCreateSchema } from "../../../schema/Ban"; import { check } from "../../../util/instanceOf"; -import { removeMember } from "../../../util/Member"; -import { getPublicUser } from "../../../util/User"; const router: Router = Router(); router.get("/", async (req: Request, res: Response) => { const { guild_id } = req.params; - const guild = await GuildModel.exists({ id: guild_id }); - if (!guild) throw new HTTPError("Guild not found", 404); - - var bans = await BanModel.find({ guild_id: guild_id }, { user_id: true, reason: true }).exec(); - return res.json(toObject(bans)); + var bans = await Ban.find({ guild_id: guild_id }); + return res.json(bans); }); router.get("/:user", async (req: Request, res: Response) => { const { guild_id } = req.params; const user_id = req.params.ban; - var ban = await BanModel.findOne({ guild_id: guild_id, user_id: user_id }).exec(); + var ban = await Ban.findOneOrFail({ guild_id: guild_id, user_id: user_id }); return res.json(ban); }); @@ -32,57 +27,59 @@ router.put("/:user_id", check(BanCreateSchema), async (req: Request, res: Respon const { guild_id } = req.params; const banned_user_id = req.params.user_id; - const banned_user = await getPublicUser(banned_user_id); + const banned_user = await User.getPublicUser(banned_user_id); const perms = await getPermission(req.user_id, guild_id); perms.hasThrow("BAN_MEMBERS"); if (req.user_id === banned_user_id) throw new HTTPError("You can't ban yourself", 400); + if (perms.cache.guild?.owner_id === banned_user_id) throw new HTTPError("You can't ban the owner", 400); - await removeMember(banned_user_id, guild_id); - - const ban = await new BanModel({ + const ban = new Ban({ user_id: banned_user_id, guild_id: guild_id, ip: getIpAdress(req), executor_id: req.user_id, reason: req.body.reason // || otherwise empty - }).save(); - - await emitEvent({ - event: "GUILD_BAN_ADD", - data: { - guild_id: guild_id, - user: banned_user - }, - guild_id: guild_id - } as GuildBanAddEvent); - - return res.json(toObject(ban)); + }); + + await Promise.all([ + Member.removeFromGuild(banned_user_id, guild_id), + ban.save(), + emitEvent({ + event: "GUILD_BAN_ADD", + data: { + guild_id: guild_id, + user: banned_user + }, + guild_id: guild_id + } as GuildBanAddEvent) + ]); + + return res.json(ban); }); router.delete("/:user_id", async (req: Request, res: Response) => { var { guild_id } = req.params; var banned_user_id = req.params.user_id; - const banned_user = await getPublicUser(banned_user_id); - const guild = await GuildModel.exists({ id: guild_id }); - if (!guild) throw new HTTPError("Guild not found", 404); - + const banned_user = await User.getPublicUser(banned_user_id); const perms = await getPermission(req.user_id, guild_id); perms.hasThrow("BAN_MEMBERS"); - await BanModel.deleteOne({ - user_id: banned_user_id, - guild_id - }).exec(); - - await emitEvent({ - event: "GUILD_BAN_REMOVE", - data: { - guild_id, - user: banned_user - }, - guild_id - } as GuildBanRemoveEvent); + await Promise.all([ + Ban.delete({ + user_id: banned_user_id, + guild_id + }), + + emitEvent({ + event: "GUILD_BAN_REMOVE", + data: { + guild_id, + user: banned_user + }, + guild_id + } as GuildBanRemoveEvent) + ]); return res.status(204).send(); }); diff --git a/api/src/routes/guilds/#guild_id/channels.ts b/api/src/routes/guilds/#guild_id/channels.ts
index 1c55ef24..5aa1d33d 100644 --- a/api/src/routes/guilds/#guild_id/channels.ts +++ b/api/src/routes/guilds/#guild_id/channels.ts
@@ -1,17 +1,16 @@ import { Router, Response, Request } from "express"; -import { ChannelModel, toObject, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util"; +import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { ChannelModifySchema } from "../../../schema/Channel"; import { check } from "../../../util/instanceOf"; -import { createChannel } from "../../../util/Channel"; const router = Router(); router.get("/", async (req: Request, res: Response) => { const { guild_id } = req.params; - const channels = await ChannelModel.find({ guild_id }).exec(); + const channels = await Channel.find({ guild_id }); - res.json(toObject(channels)); + res.json(channels); }); // TODO: check if channel type is permitted @@ -22,9 +21,9 @@ router.post("/", check(ChannelModifySchema), async (req: Request, res: Response) const { guild_id } = req.params; const body = req.body as ChannelModifySchema; - const channel = await createChannel({ ...body, guild_id }, req.user_id); + const channel = await Channel.createChannel({ ...body, guild_id }, req.user_id); - res.status(201).json(toObject(channel)); + res.status(201).json(channel); }); // TODO: check if parent_id exists @@ -48,18 +47,19 @@ router.patch( if (x.parent_id) { opts.parent_id = x.parent_id; - const parent_channel = await ChannelModel.findOne( - { id: x.parent_id, guild_id }, - { permission_overwrites: true } - ).exec(); + const parent_channel = await Channel.findOneOrFail({ + where: { id: x.parent_id, guild_id }, + select: ["permission_overwrites"] + }); if (x.lock_permissions) { opts.permission_overwrites = parent_channel.permission_overwrites; } } - const channel = await ChannelModel.findOneAndUpdate({ id: x.id, guild_id }, opts, { new: true }).exec(); + await Channel.update({ guild_id, id: x.id }, opts); + const channel = await Channel.findOneOrFail({ guild_id, id: x.id }); - await emitEvent({ event: "CHANNEL_UPDATE", data: toObject(channel), channel_id: x.id, guild_id } as ChannelUpdateEvent); + await emitEvent({ event: "CHANNEL_UPDATE", data: channel, channel_id: x.id, guild_id } as ChannelUpdateEvent); }) ]); diff --git a/api/src/routes/guilds/#guild_id/delete.ts b/api/src/routes/guilds/#guild_id/delete.ts
index ba1c2fde..043260e9 100644 --- a/api/src/routes/guilds/#guild_id/delete.ts +++ b/api/src/routes/guilds/#guild_id/delete.ts
@@ -1,15 +1,4 @@ -import { - ChannelModel, - emitEvent, - EmojiModel, - GuildDeleteEvent, - GuildModel, - InviteModel, - MemberModel, - MessageModel, - RoleModel, - UserModel -} from "@fosscord/util"; +import { Channel, emitEvent, GuildDeleteEvent, Guild, Member, Message, Role, Invite, Emoji } from "@fosscord/util"; import { Router, Request, Response } from "express"; import { HTTPError } from "lambert-server"; @@ -20,7 +9,7 @@ const router = Router(); router.post("/", async (req: Request, res: Response) => { var { guild_id } = req.params; - const guild = await GuildModel.findOne({ id: guild_id }, "owner_id").exec(); + const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: ["owner_id"] }); if (guild.owner_id !== req.user_id) throw new HTTPError("You are not the owner of this guild", 401); await emitEvent({ @@ -32,14 +21,13 @@ router.post("/", async (req: Request, res: Response) => { } as GuildDeleteEvent); await Promise.all([ - GuildModel.deleteOne({ id: guild_id }).exec(), - UserModel.updateMany({ guilds: guild_id }, { $pull: { guilds: guild_id } }).exec(), - RoleModel.deleteMany({ guild_id }).exec(), - ChannelModel.deleteMany({ guild_id }).exec(), - EmojiModel.deleteMany({ guild_id }).exec(), - InviteModel.deleteMany({ guild_id }).exec(), - MessageModel.deleteMany({ guild_id }).exec(), - MemberModel.deleteMany({ guild_id }).exec() + Guild.delete({ id: guild_id }), + Role.delete({ guild_id }), + Channel.delete({ guild_id }), + Emoji.delete({ guild_id }), + Invite.delete({ guild_id }), + Message.delete({ guild_id }), + Member.delete({ guild_id }) ]); return res.sendStatus(204); diff --git a/api/src/routes/guilds/#guild_id/index.ts b/api/src/routes/guilds/#guild_id/index.ts
index 87103caa..6f55be3b 100644 --- a/api/src/routes/guilds/#guild_id/index.ts +++ b/api/src/routes/guilds/#guild_id/index.ts
@@ -1,19 +1,5 @@ import { Request, Response, Router } from "express"; -import { - ChannelModel, - emitEvent, - EmojiModel, - getPermission, - GuildDeleteEvent, - GuildModel, - GuildUpdateEvent, - InviteModel, - MemberModel, - MessageModel, - RoleModel, - toObject, - UserModel -} from "@fosscord/util"; +import { emitEvent, getPermission, Guild, GuildUpdateEvent, Member } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { GuildUpdateSchema } from "../../../schema/Guild"; @@ -26,12 +12,15 @@ const router = Router(); router.get("/", async (req: Request, res: Response) => { const { guild_id } = req.params; - const guild = await GuildModel.findOne({ id: guild_id }) - .populate({ path: "joined_at", match: { id: req.user_id } }) - .exec(); + const [guild, member_count, member] = await Promise.all([ + Guild.findOneOrFail({ id: guild_id }), + Member.count({ guild: { id: guild_id }, id: req.user_id }), + Member.findOneOrFail({ id: req.user_id }) + ]); + if (!member_count) throw new HTTPError("You are not a member of the guild you are trying to access", 401); - const member = await MemberModel.exists({ guild_id: guild_id, id: req.user_id }); - if (!member) throw new HTTPError("You are not a member of the guild you are trying to access", 401); + // @ts-ignore + guild.joined_at = member?.joined_at; return res.json(guild); }); @@ -48,15 +37,12 @@ router.patch("/", check(GuildUpdateSchema), async (req: Request, res: Response) if (body.banner) body.banner = await handleFile(`/banners/${guild_id}`, body.banner); if (body.splash) body.splash = await handleFile(`/splashes/${guild_id}`, body.splash); - const guild = await GuildModel.findOneAndUpdate({ id: guild_id }, body, { new: true }) - .populate({ path: "joined_at", match: { id: req.user_id } }) - .exec(); + const guild = await Guild.findOneOrFail({ id: guild_id }); + guild.assign(body); - const data = toObject(guild); + await Promise.all([guild.save(), emitEvent({ event: "GUILD_UPDATE", data: guild, guild_id } as GuildUpdateEvent)]); - emitEvent({ event: "GUILD_UPDATE", data: data, guild_id } as GuildUpdateEvent); - - return res.json(data); + return res.json(guild); }); export default router; diff --git a/api/src/routes/guilds/#guild_id/invites.ts b/api/src/routes/guilds/#guild_id/invites.ts
index 08048d61..1843b689 100644 --- a/api/src/routes/guilds/#guild_id/invites.ts +++ b/api/src/routes/guilds/#guild_id/invites.ts
@@ -1,4 +1,4 @@ -import { getPermission, InviteModel, toObject } from "@fosscord/util"; +import { getPermission, Invite } from "@fosscord/util"; import { Request, Response, Router } from "express"; const router = Router(); @@ -9,9 +9,9 @@ router.get("/", async (req: Request, res: Response) => { const permissions = await getPermission(req.user_id, guild_id); permissions.hasThrow("MANAGE_GUILD"); - const invites = await InviteModel.find({ guild_id }).exec(); + const invites = await Invite.find({ guild_id }); - return res.json(toObject(invites)); + return res.json(invites); }); export default router; diff --git a/api/src/routes/guilds/#guild_id/members/#member_id/index.ts b/api/src/routes/guilds/#guild_id/members/#member_id/index.ts
index 515434d6..d9ce91c0 100644 --- a/api/src/routes/guilds/#guild_id/members/#member_id/index.ts +++ b/api/src/routes/guilds/#guild_id/members/#member_id/index.ts
@@ -1,50 +1,53 @@ import { Request, Response, Router } from "express"; import { - GuildModel, - MemberModel, - UserModel, - toObject, + Guild, + Member, + User, GuildMemberAddEvent, getPermission, PermissionResolvable, - RoleModel, + Role, GuildMemberUpdateEvent, emitEvent } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { addMember, isMember, removeMember } from "../../../../../util/Member"; import { check } from "../../../../../util/instanceOf"; import { MemberChangeSchema } from "../../../../../schema/Member"; +import { In } from "typeorm"; const router = Router(); router.get("/", async (req: Request, res: Response) => { const { guild_id, member_id } = req.params; - await isMember(req.user_id, guild_id); + await Member.IsInGuildOrFail(req.user_id, guild_id); - const member = await MemberModel.findOne({ id: member_id, guild_id }).exec(); + const member = await Member.findOneOrFail({ id: member_id, guild_id }); - return res.json(toObject(member)); + return res.json(member); }); router.patch("/", check(MemberChangeSchema), async (req: Request, res: Response) => { const { guild_id, member_id } = req.params; const body = req.body as MemberChangeSchema; if (body.roles) { - const roles = await RoleModel.find({ id: { $in: body.roles } }).exec(); + const roles = await Role.find({ id: In(body.roles) }); if (body.roles.length !== roles.length) throw new HTTPError("Roles not found", 404); // TODO: check if user has permission to add role } - const member = await MemberModel.findOneAndUpdate({ id: member_id, guild_id }, body, { new: true }).exec(); + const member = await Member.findOneOrFail({ id: member_id, guild_id }); + member.assign(req.body); - await emitEvent({ - event: "GUILD_MEMBER_UPDATE", - guild_id, - data: toObject(member) - } as GuildMemberUpdateEvent); + Promise.all([ + member.save(), + emitEvent({ + event: "GUILD_MEMBER_UPDATE", + guild_id, + data: { ...member, roles: member.roles.map((x) => x.id) } + } as GuildMemberUpdateEvent) + ]); - res.json(toObject(member)); + res.json(member); }); router.put("/", async (req: Request, res: Response) => { @@ -52,7 +55,7 @@ router.put("/", async (req: Request, res: Response) => { throw new HTTPError("Maintenance: Currently you can't add a member", 403); // TODO: only for oauth2 applications - await addMember(member_id, guild_id); + await Member.addToGuild(member_id, guild_id); res.sendStatus(204); }); @@ -62,7 +65,7 @@ router.delete("/", async (req: Request, res: Response) => { const perms = await getPermission(req.user_id, guild_id); perms.hasThrow("KICK_MEMBERS"); - await removeMember(member_id, guild_id); + await Member.removeFromGuild(member_id, guild_id); res.sendStatus(204); }); diff --git a/api/src/routes/guilds/#guild_id/members/#member_id/nick.ts b/api/src/routes/guilds/#guild_id/members/#member_id/nick.ts
index e4308364..3f2975e6 100644 --- a/api/src/routes/guilds/#guild_id/members/#member_id/nick.ts +++ b/api/src/routes/guilds/#guild_id/members/#member_id/nick.ts
@@ -1,8 +1,7 @@ -import { getPermission, PermissionResolvable } from "@fosscord/util"; +import { getPermission, Member, PermissionResolvable } from "@fosscord/util"; import { Request, Response, Router } from "express"; import { check } from "lambert-server"; import { MemberNickChangeSchema } from "../../../../../schema/Member"; -import { changeNickname } from "../../../../../util/Member"; const router = Router(); @@ -17,7 +16,7 @@ router.patch("/", check(MemberNickChangeSchema), async (req: Request, res: Respo const perms = await getPermission(req.user_id, guild_id); perms.hasThrow(permissionString); - await changeNickname(member_id, guild_id, req.body.nick); + await Member.changeNickname(member_id, guild_id, req.body.nick); res.status(200).send(); }); diff --git a/api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts b/api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts
index fad0695e..cb9bad9a 100644 --- a/api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts +++ b/api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts
@@ -1,6 +1,5 @@ -import { getPermission } from "@fosscord/util"; +import { getPermission, Member } from "@fosscord/util"; import { Request, Response, Router } from "express"; -import { addRole, removeRole } from "../../../../../../../util/Member"; const router = Router(); @@ -10,7 +9,7 @@ router.delete("/:member_id/roles/:role_id", async (req: Request, res: Response) const perms = await getPermission(req.user_id, guild_id); perms.hasThrow("MANAGE_ROLES"); - await removeRole(member_id, guild_id, role_id); + await Member.removeRole(member_id, guild_id, role_id); res.sendStatus(204); }); @@ -20,7 +19,7 @@ router.put("/:member_id/roles/:role_id", async (req: Request, res: Response) => const perms = await getPermission(req.user_id, guild_id); perms.hasThrow("MANAGE_ROLES"); - await addRole(member_id, guild_id, role_id); + await Member.addRole(member_id, guild_id, role_id); res.sendStatus(204); }); diff --git a/api/src/routes/guilds/#guild_id/members/index.ts b/api/src/routes/guilds/#guild_id/members/index.ts
index 70303436..0bfd71cb 100644 --- a/api/src/routes/guilds/#guild_id/members/index.ts +++ b/api/src/routes/guilds/#guild_id/members/index.ts
@@ -1,8 +1,7 @@ import { Request, Response, Router } from "express"; -import { GuildModel, MemberModel, toObject } from "@fosscord/util"; -import { HTTPError } from "lambert-server"; +import { Guild, Member, PublicMemberProjection } from "@fosscord/util"; import { instanceOf, Length } from "../../../../util/instanceOf"; -import { PublicMemberProjection, isMember } from "../../../../util/Member"; +import { MoreThan } from "typeorm"; const router = Router(); @@ -10,8 +9,8 @@ const router = Router(); // TODO: send over websocket router.get("/", async (req: Request, res: Response) => { const { guild_id } = req.params; - const guild = await GuildModel.findOne({ id: guild_id }).exec(); - await isMember(req.user_id, guild_id); + const guild = await Guild.findOneOrFail({ id: guild_id }); + await Member.IsInGuildOrFail(req.user_id, guild_id); try { instanceOf({ $limit: new Length(Number, 1, 1000), $after: String }, req.query, { @@ -23,16 +22,17 @@ router.get("/", async (req: Request, res: Response) => { return res.status(400).json({ code: 50035, message: "Invalid Query", success: false, errors: error }); } - // @ts-ignore - if (!req.query.limit) req.query.limit = 1; - const { limit, after } = (<unknown>req.query) as { limit: number; after: string }; - const query = after ? { id: { $gt: after } } : {}; + const { limit, after } = (<unknown>req.query) as { limit?: number; after?: string }; + const query = after ? { id: MoreThan(after) } : {}; - var members = await MemberModel.find({ guild_id, ...query }, PublicMemberProjection) - .limit(limit) - .exec(); + const members = await Member.find({ + where: { guild_id, ...query }, + select: PublicMemberProjection, + take: limit || 1, + order: { id: "ASC" } + }); - return res.json(toObject(members)); + return res.json(members); }); export default router; diff --git a/api/src/routes/guilds/#guild_id/regions.ts b/api/src/routes/guilds/#guild_id/regions.ts
index 5ec649ee..212c9bcd 100644 --- a/api/src/routes/guilds/#guild_id/regions.ts +++ b/api/src/routes/guilds/#guild_id/regions.ts
@@ -1,10 +1,15 @@ -import { Config } from "@fosscord/util"; +import {Config, Guild, Member} from "@fosscord/util"; import { Request, Response, Router } from "express"; +import {getVoiceRegions} from "../../../util/Voice"; +import {getIpAdress} from "../../../util/ipAddress"; const router = Router(); router.get("/", async (req: Request, res: Response) => { - return res.json(Config.get().regions.available); + const { guild_id } = req.params; + const guild = await Guild.findOneOrFail({ id: guild_id }); + //TODO we should use an enum for guild's features and not hardcoded strings + return res.json(await getVoiceRegions(getIpAdress(req), guild.features.includes("VIP_REGIONS"))); }); export default router; diff --git a/api/src/routes/guilds/#guild_id/roles.ts b/api/src/routes/guilds/#guild_id/roles.ts
index f095c885..f6ac8caa 100644 --- a/api/src/routes/guilds/#guild_id/roles.ts +++ b/api/src/routes/guilds/#guild_id/roles.ts
@@ -1,12 +1,9 @@ import { Request, Response, Router } from "express"; import { - RoleModel, - GuildModel, + Role, getPermission, - toObject, - UserModel, Snowflake, - MemberModel, + Member, GuildRoleCreateEvent, GuildRoleUpdateEvent, GuildRoleDeleteEvent, @@ -16,40 +13,34 @@ import { HTTPError } from "lambert-server"; import { check } from "../../../util/instanceOf"; import { RoleModifySchema } from "../../../schema/Roles"; -import { getPublicUser } from "../../../util/User"; -import { isMember } from "../../../util/Member"; const router: Router = Router(); router.get("/", async (req: Request, res: Response) => { const guild_id = req.params.guild_id; - await isMember(req.user_id, guild_id); + await Member.IsInGuildOrFail(req.user_id, guild_id); - const roles = await RoleModel.find({ guild_id: guild_id }).exec(); + const roles = await Role.find({ guild_id: guild_id }); - return res.json(toObject(roles)); + return res.json(roles); }); router.post("/", check(RoleModifySchema), async (req: Request, res: Response) => { const guild_id = req.params.guild_id; const body = req.body as RoleModifySchema; - const guild = await GuildModel.findOne({ id: guild_id }, { id: true }).exec(); - const user = await UserModel.findOne({ id: req.user_id }).exec(); - const perms = await getPermission(req.user_id, guild_id); perms.hasThrow("MANAGE_ROLES"); - if (!body.name) throw new HTTPError("You need to specify a name"); - const role = await new RoleModel({ + const role = await new Role({ ...body, id: Snowflake.generate(), guild_id: guild_id, managed: false, position: 0, tags: null, - permissions: body.permissions || 0n + permissions: String(perms.bitfield & (body.permissions || 0n)) }).save(); await emitEvent({ @@ -57,11 +48,11 @@ router.post("/", check(RoleModifySchema), async (req: Request, res: Response) => guild_id, data: { guild_id, - role: toObject(role) + role: role } } as GuildRoleCreateEvent); - res.json(toObject(role)); + res.json(role); }); router.delete("/:role_id", async (req: Request, res: Response) => { @@ -72,19 +63,20 @@ router.delete("/:role_id", async (req: Request, res: Response) => { const permissions = await getPermission(req.user_id, guild_id); permissions.hasThrow("MANAGE_ROLES"); - await RoleModel.deleteOne({ - id: role_id, - guild_id: guild_id - }).exec(); - - await emitEvent({ - event: "GUILD_ROLE_DELETE", - guild_id, - data: { + await Promise.all([ + Role.delete({ + id: role_id, + guild_id: guild_id + }), + emitEvent({ + event: "GUILD_ROLE_DELETE", guild_id, - role_id - } - } as GuildRoleDeleteEvent); + data: { + guild_id, + role_id + } + } as GuildRoleDeleteEvent) + ]); res.sendStatus(204); }); @@ -96,32 +88,24 @@ router.patch("/:role_id", check(RoleModifySchema), async (req: Request, res: Res const { role_id } = req.params; const body = req.body as RoleModifySchema; - const guild = await GuildModel.findOne({ id: guild_id }, { id: true }).exec(); - const user = await UserModel.findOne({ id: req.user_id }).exec(); - const perms = await getPermission(req.user_id, guild_id); perms.hasThrow("MANAGE_ROLES"); - const role = await RoleModel.findOneAndUpdate( - { - id: role_id, - guild_id: guild_id - }, - // @ts-ignore - body, - { new: true } - ).exec(); + const role = new Role({ ...body, id: role_id, guild_id, permissions: perms.bitfield & (body.permissions || 0n) }); - await emitEvent({ - event: "GUILD_ROLE_UPDATE", - guild_id, - data: { + await Promise.all([ + role.save(), + emitEvent({ + event: "GUILD_ROLE_UPDATE", guild_id, - role - } - } as GuildRoleUpdateEvent); - - res.json(toObject(role)); + data: { + guild_id, + role + } + } as GuildRoleUpdateEvent) + ]); + + res.json(role); }); export default router; diff --git a/api/src/routes/guilds/#guild_id/templates.ts b/api/src/routes/guilds/#guild_id/templates.ts
index e441ee12..a7613abf 100644 --- a/api/src/routes/guilds/#guild_id/templates.ts +++ b/api/src/routes/guilds/#guild_id/templates.ts
@@ -1,5 +1,5 @@ import { Request, Response, Router } from "express"; -import { TemplateModel, GuildModel, getPermission, toObject, UserModel, Snowflake } from "@fosscord/util"; +import { Guild, getPermission, Template } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { TemplateCreateSchema, TemplateModifySchema } from "../../../schema/Template"; import { check } from "../../../util/instanceOf"; @@ -7,43 +7,41 @@ import { generateCode } from "../../../util/String"; const router: Router = Router(); -const TemplateGuildProjection = { - name: true, - description: true, - region: true, - verification_level: true, - default_message_notifications: true, - explicit_content_filter: true, - preferred_locale: true, - afk_timeout: true, - roles: true, - channels: true, - afk_channel_id: true, - system_channel_id: true, - system_channel_flags: true, - icon_hash: true -}; +const TemplateGuildProjection: (keyof Guild)[] = [ + "name", + "description", + "region", + "verification_level", + "default_message_notifications", + "explicit_content_filter", + "preferred_locale", + "afk_timeout", + "roles", + // "channels", + "afk_channel_id", + "system_channel_id", + "system_channel_flags", + "icon" +]; router.get("/", async (req: Request, res: Response) => { const { guild_id } = req.params; - var templates = await TemplateModel.find({ source_guild_id: guild_id }).exec(); + var templates = await Template.find({ source_guild_id: guild_id }); - return res.json(toObject(templates)); + return res.json(templates); }); router.post("/", check(TemplateCreateSchema), async (req: Request, res: Response) => { const { guild_id } = req.params; - const guild = await GuildModel.findOne({ id: guild_id }, TemplateGuildProjection).exec(); + const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: TemplateGuildProjection }); const perms = await getPermission(req.user_id, guild_id); perms.hasThrow("MANAGE_GUILD"); - const exists = await TemplateModel.findOne({ id: guild_id }) - .exec() - .catch((e) => {}); + const exists = await Template.findOneOrFail({ id: guild_id }).catch((e) => {}); if (exists) throw new HTTPError("Template already exists", 400); - const template = await new TemplateModel({ + const template = await new Template({ ...req.body, code: generateCode(), creator_id: req.user_id, @@ -53,7 +51,7 @@ router.post("/", check(TemplateCreateSchema), async (req: Request, res: Response serialized_source_guild: guild }).save(); - res.json(toObject(template)).send(); + res.json(template); }); router.delete("/:code", async (req: Request, res: Response) => { @@ -63,41 +61,39 @@ router.delete("/:code", async (req: Request, res: Response) => { const perms = await getPermission(req.user_id, guild_id); perms.hasThrow("MANAGE_GUILD"); - const template = await TemplateModel.findOneAndDelete({ + const template = await Template.delete({ code - }).exec(); + }); - res.send(toObject(template)); + res.json(template); }); router.put("/:code", async (req: Request, res: Response) => { - const guild_id = req.params.guild_id; - const { code } = req.params; + // synchronizes the template + const { code, guild_id } = req.params; - const guild = await GuildModel.findOne({ id: guild_id }, TemplateGuildProjection).exec(); + const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: TemplateGuildProjection }); const perms = await getPermission(req.user_id, guild_id); perms.hasThrow("MANAGE_GUILD"); - const template = await TemplateModel.findOneAndUpdate({ code }, { serialized_source_guild: guild }, { new: true }).exec(); + const template = await new Template({ code, serialized_source_guild: guild }).save(); - res.json(toObject(template)).send(); + res.json(template); }); router.patch("/:code", check(TemplateModifySchema), async (req: Request, res: Response) => { + // updates the template description const { guild_id } = req.params; const { code } = req.params; + const { name, description } = req.body; const perms = await getPermission(req.user_id, guild_id); perms.hasThrow("MANAGE_GUILD"); - const template = await TemplateModel.findOneAndUpdate( - { code }, - { name: req.body.name, description: req.body.description }, - { new: true } - ).exec(); + const template = await new Template({ code, name: name, description: description }).save(); - res.json(toObject(template)).send(); + res.json(template); }); export default router; diff --git a/api/src/routes/guilds/#guild_id/vanity-url.ts b/api/src/routes/guilds/#guild_id/vanity-url.ts
index 1e659d8d..58940b42 100644 --- a/api/src/routes/guilds/#guild_id/vanity-url.ts +++ b/api/src/routes/guilds/#guild_id/vanity-url.ts
@@ -1,8 +1,7 @@ -import { ChannelModel, ChannelType, getPermission, GuildModel, InviteModel, trimSpecial } from "@fosscord/util"; +import { Channel, ChannelType, getPermission, Guild, Invite, trimSpecial } from "@fosscord/util"; import { Router, Request, Response } from "express"; import { HTTPError } from "lambert-server"; import { check, Length } from "../../../util/instanceOf"; -import { isMember } from "../../../util/Member"; const router = Router(); @@ -14,46 +13,37 @@ router.get("/", async (req: Request, res: Response) => { const permission = await getPermission(req.user_id, guild_id); permission.hasThrow("MANAGE_GUILD"); - const guild = await GuildModel.findOne({ id: guild_id }).exec(); - if (!guild.vanity_url_code) return res.json({ code: null }); - const { uses } = await InviteModel.findOne({ code: guild.vanity_url_code }).exec(); + const guild = await Guild.findOneOrFail({ where: { id: guild_id }, relations: ["vanity_url"] }); + if (!guild.vanity_url) return res.json({ code: null }); - return res.json({ code: guild.vanity_url_code, uses }); + return res.json({ code: guild.vanity_url_code, uses: guild.vanity_url.uses }); }); // TODO: check if guild is elgible for vanity url router.patch("/", check({ code: new Length(String, 0, 20) }), async (req: Request, res: Response) => { const { guild_id } = req.params; - var code = req.body.code.replace(InviteRegex); - if (!code) code = null; + const code = req.body.code.replace(InviteRegex); - const guild = await GuildModel.findOne({ id: guild_id }).exec(); - const permission = await getPermission(req.user_id, guild_id, undefined, { guild }); + await Invite.findOneOrFail({ code }); + + const guild = await Guild.findOneOrFail({ id: guild_id }); + const permission = await getPermission(req.user_id, guild_id); permission.hasThrow("MANAGE_GUILD"); - const alreadyExists = await Promise.all([ - GuildModel.findOne({ vanity_url_code: code }) - .exec() - .catch(() => null), - InviteModel.findOne({ code: code }) - .exec() - .catch(() => null) - ]); - if (alreadyExists.some((x) => x)) throw new HTTPError("Vanity url already exists", 400); + const { id } = await Channel.findOneOrFail({ guild_id, type: ChannelType.GUILD_TEXT }); + guild.vanity_url_code = code; - await GuildModel.updateOne({ id: guild_id }, { vanity_url_code: code }).exec(); - const { id } = await ChannelModel.findOne({ guild_id, type: ChannelType.GUILD_TEXT }).exec(); - await InviteModel.updateOne( - { code: guild.vanity_url_code }, - { + Promise.all([ + guild.save(), + Invite.delete({ code: guild.vanity_url_code }), + new Invite({ code: code, uses: 0, created_at: new Date(), guild_id, channel_id: id - }, - { upsert: true } - ).exec(); + }).save() + ]); return res.json({ code: code }); }); diff --git a/api/src/routes/guilds/#guild_id/welcome_screen.ts b/api/src/routes/guilds/#guild_id/welcome_screen.ts
index c717042e..defbcd40 100644 --- a/api/src/routes/guilds/#guild_id/welcome_screen.ts +++ b/api/src/routes/guilds/#guild_id/welcome_screen.ts
@@ -1,47 +1,35 @@ import { Request, Response, Router } from "express"; -import { GuildModel, getPermission, toObject, Snowflake } from "@fosscord/util"; +import { Guild, getPermission, Snowflake, Member } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { check } from "../../../util/instanceOf"; -import { isMember } from "../../../util/Member"; -import { GuildAddChannelToWelcomeScreenSchema } from "../../../schema/Guild"; -import { getPublicUser } from "../../../util/User"; +import { GuildUpdateWelcomeScreenSchema } from "../../../schema/Guild"; const router: Router = Router(); router.get("/", async (req: Request, res: Response) => { const guild_id = req.params.guild_id; - const guild = await GuildModel.findOne({ id: guild_id }); + const guild = await Guild.findOneOrFail({ id: guild_id }); - await isMember(req.user_id, guild_id); + await Member.IsInGuildOrFail(req.user_id, guild_id); - res.json(toObject(guild.welcome_screen)); + res.json(guild.welcome_screen); }); -router.post("/", check(GuildAddChannelToWelcomeScreenSchema), async (req: Request, res: Response) => { +router.patch("/", check(GuildUpdateWelcomeScreenSchema), async (req: Request, res: Response) => { const guild_id = req.params.guild_id; - const body = req.body as GuildAddChannelToWelcomeScreenSchema; + const body = req.body as GuildUpdateWelcomeScreenSchema; - const guild = await GuildModel.findOne({ id: guild_id }).exec(); - - var channelObject = { - ...body - }; + const guild = await Guild.findOneOrFail({ id: guild_id }); const perms = await getPermission(req.user_id, guild_id); perms.hasThrow("MANAGE_GUILD"); if (!guild.welcome_screen.enabled) throw new HTTPError("Welcome screen disabled", 400); - if (guild.welcome_screen.welcome_channels.some((channel) => channel.channel_id === body.channel_id)) - throw new Error("Welcome Channel exists"); - - await GuildModel.findOneAndUpdate( - { - id: guild_id - }, - { $push: { "welcome_screen.welcome_channels": channelObject } } - ).exec(); + if (body.welcome_channels) guild.welcome_screen.welcome_channels = body.welcome_channels; // TODO: check if they exist and are valid + if (body.description) guild.welcome_screen.description = body.description; + if (body.enabled != null) guild.welcome_screen.enabled = body.enabled; res.sendStatus(204); }); diff --git a/api/src/routes/guilds/#guild_id/widget.json.ts b/api/src/routes/guilds/#guild_id/widget.json.ts
index 8719bd85..ae1f0599 100644 --- a/api/src/routes/guilds/#guild_id/widget.json.ts +++ b/api/src/routes/guilds/#guild_id/widget.json.ts
@@ -1,5 +1,5 @@ import { Request, Response, Router } from "express"; -import { Config, Permissions, GuildModel, InviteModel, ChannelModel, MemberModel } from "@fosscord/util"; +import { Config, Permissions, Guild, Invite, Channel, Member } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { random } from "../../../util/RandomInviteID"; @@ -17,11 +17,12 @@ const router: Router = Router(); router.get("/", async (req: Request, res: Response) => { const { guild_id } = req.params; - const guild = await GuildModel.findOne({ id: guild_id }).exec(); + const guild = await Guild.findOneOrFail({ id: guild_id }); if (!guild.widget_enabled) throw new HTTPError("Widget Disabled", 404); // Fetch existing widget invite for widget channel - var invite = await InviteModel.findOne({ channel_id: guild.widget_channel_id, inviter_id: { $type: 10 } }).exec(); + var invite = await Invite.findOne({ channel_id: guild.widget_channel_id }); + if (guild.widget_channel_id && !invite) { // Create invite for channel if none exists // TODO: Refactor invite create code to a shared function @@ -40,87 +41,29 @@ router.get("/", async (req: Request, res: Response) => { inviter_id: null }; - invite = await new InviteModel(body).save(); + invite = await new Invite(body).save(); } // Fetch voice channels, and the @everyone permissions object - let channels: any[] = []; - await ChannelModel.find({ guild_id: guild_id, type: 2 }, { permission_overwrites: { $elemMatch: { id: guild_id } } }) - .lean() - .select("id name position permission_overwrites") - .sort({ position: 1 }) - .cursor() - .eachAsync((doc) => { - // Only return channels where @everyone has the CONNECT permission - if ( - doc.permission_overwrites === undefined || - Permissions.channelPermission(doc.permission_overwrites, Permissions.FLAGS.CONNECT) === Permissions.FLAGS.CONNECT - ) { - channels.push({ - id: doc.id, - name: doc.name, - position: doc.position - }); - } - }); + const channels = [] as any[]; + + (await Channel.find({ where: { guild_id: guild_id, type: 2 }, order: { position: "ASC" } })).filter((doc) => { + // Only return channels where @everyone has the CONNECT permission + if ( + doc.permission_overwrites === undefined || + Permissions.channelPermission(doc.permission_overwrites, Permissions.FLAGS.CONNECT) === Permissions.FLAGS.CONNECT + ) { + channels.push({ + id: doc.id, + name: doc.name, + position: doc.position + }); + } + }); // Fetch members // TODO: Understand how Discord's max 100 random member sample works, and apply to here (see top of this file) - let members: any[] = []; - await MemberModel.find({ guild_id: guild_id }) - .lean() - .populate({ path: "user", select: { _id: 0, username: 1, avatar: 1, presence: 1 } }) - .select("id user nick deaf mute") - .cursor() - .eachAsync((doc) => { - const status = doc.user?.presence?.status || "offline"; - if (status == "offline") return; - - let item = {}; - - item = { - ...item, - id: null, // this is updated during the sort outside of the query - username: doc.nick || doc.user?.username, - discriminator: "0000", // intended (https://github.com/discord/discord-api-docs/issues/1287) - avatar: null, // intended, avatar_url below will return a unique guild + user url to the avatar - status: status - }; - - const activity = doc.user?.presence?.activities?.[0]; - if (activity) { - item = { - ...item, - game: { name: activity.name } - }; - } - - // TODO: If the member is in a voice channel, return extra widget details - // Extra fields returned include deaf, mute, self_deaf, self_mute, supress, and channel_id (voice channel connected to) - // Get this from VoiceState - - // TODO: Implement a widget-avatar endpoint on the CDN, and implement logic here to request it - // Get unique avatar url for guild user, cdn to serve the actual avatar image on this url - /* - const avatar = doc.user?.avatar; - if (avatar) { - const CDN_HOST = Config.get().cdn.endpoint || "http://localhost:3003"; - const avatar_url = "/widget-avatars/" + ; - item = { - ...item, - avatar_url: avatar_url - } - } - */ - - members.push(item); - }); - - // Sort members, and update ids (Unable to do under the mongoose query due to https://mongoosejs.com/docs/faq.html#populate_sort_order) - members = members.sort((first, second) => 0 - (first.username > second.username ? -1 : 1)); - members.forEach((x, i) => { - x.id = i; - }); + let members = await Member.find({ where: { guild_id: guild_id } }); // Construct object to respond with const data = { diff --git a/api/src/routes/guilds/#guild_id/widget.png.ts b/api/src/routes/guilds/#guild_id/widget.png.ts
index 80dc9f2b..89b31153 100644 --- a/api/src/routes/guilds/#guild_id/widget.png.ts +++ b/api/src/routes/guilds/#guild_id/widget.png.ts
@@ -1,5 +1,5 @@ import { Request, Response, Router } from "express"; -import { GuildModel } from "@fosscord/util"; +import { Guild } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import fs from "fs"; import path from "path"; @@ -13,7 +13,7 @@ const router: Router = Router(); router.get("/", async (req: Request, res: Response) => { const { guild_id } = req.params; - const guild = await GuildModel.findOne({ id: guild_id }).exec(); + const guild = await Guild.findOneOrFail({ id: guild_id }); if (!guild.widget_enabled) throw new HTTPError("Unknown Guild", 404); // Fetch guild information diff --git a/api/src/routes/guilds/#guild_id/widget.ts b/api/src/routes/guilds/#guild_id/widget.ts
index 85eed5e9..fcf71402 100644 --- a/api/src/routes/guilds/#guild_id/widget.ts +++ b/api/src/routes/guilds/#guild_id/widget.ts
@@ -1,5 +1,5 @@ import { Request, Response, Router } from "express"; -import { getPermission, GuildModel } from "@fosscord/util"; +import { getPermission, Guild } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { check } from "../../../util/instanceOf"; import { WidgetModifySchema } from "../../../schema/Widget"; @@ -13,7 +13,7 @@ router.get("/", async (req: Request, res: Response) => { const perms = await getPermission(req.user_id, guild_id); perms.hasThrow("MANAGE_GUILD"); - const guild = await GuildModel.findOne({ id: guild_id }).exec(); + const guild = await Guild.findOneOrFail({ id: guild_id }); return res.json({ enabled: guild.widget_enabled || false, channel_id: guild.widget_channel_id || null }); }); @@ -26,7 +26,7 @@ router.patch("/", check(WidgetModifySchema), async (req: Request, res: Response) const perms = await getPermission(req.user_id, guild_id); perms.hasThrow("MANAGE_GUILD"); - await GuildModel.updateOne({ id: guild_id }, { widget_enabled: body.enabled, widget_channel_id: body.channel_id }).exec(); + await Guild.update({ id: guild_id }, { widget_enabled: body.enabled, widget_channel_id: body.channel_id }); // Widget invite for the widget_channel_id gets created as part of the /guilds/{guild.id}/widget.json request return res.json(body); diff --git a/api/src/routes/guilds/index.ts b/api/src/routes/guilds/index.ts
index 92feed4e..e4157384 100644 --- a/api/src/routes/guilds/index.ts +++ b/api/src/routes/guilds/index.ts
@@ -1,11 +1,8 @@ import { Router, Request, Response } from "express"; -import { RoleModel, GuildModel, Snowflake, Guild, RoleDocument, Config } from "@fosscord/util"; +import { Role, Guild, Snowflake, Config, User, Member, Channel } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { check } from "./../../util/instanceOf"; import { GuildCreateSchema } from "../../schema/Guild"; -import { getPublicUser } from "../../util/User"; -import { addMember } from "../../util/Member"; -import { createChannel } from "../../util/Channel"; const router: Router = Router(); @@ -15,58 +12,43 @@ router.post("/", check(GuildCreateSchema), async (req: Request, res: Response) = const body = req.body as GuildCreateSchema; const { maxGuilds } = Config.get().limits.user; - const user = await getPublicUser(req.user_id, { guilds: true }); - - if (user.guilds.length >= maxGuilds) { + const guild_count = await Member.count({ id: req.user_id }); + if (guild_count >= maxGuilds) { throw new HTTPError(`Maximum number of guilds reached ${maxGuilds}`, 403); } const guild_id = Snowflake.generate(); - const guild: Guild = { - name: body.name, - region: Config.get().regions.default, - owner_id: req.user_id, - icon: undefined, - afk_channel_id: undefined, - afk_timeout: 300, - application_id: undefined, - banner: undefined, - default_message_notifications: 0, - description: undefined, - splash: undefined, - discovery_splash: undefined, - explicit_content_filter: 0, - features: [], - id: guild_id, - large: undefined, - max_members: 250000, - max_presences: 250000, - max_video_channel_users: 25, - presence_count: 0, - member_count: 0, // will automatically be increased by addMember() - mfa_level: 0, - preferred_locale: "en-US", - premium_subscription_count: 0, - premium_tier: 0, - public_updates_channel_id: undefined, - rules_channel_id: undefined, - system_channel_flags: 0, - system_channel_id: undefined, - unavailable: false, - vanity_url_code: undefined, - verification_level: 0, - welcome_screen: { - enabled: false, - description: "No description", - welcome_channels: [] - }, - widget_channel_id: undefined, - widget_enabled: false - }; - const [guild_doc, role] = await Promise.all([ - new GuildModel(guild).save(), - new RoleModel({ + const [guild, role] = await Promise.all([ + Guild.insert({ + name: body.name, + region: Config.get().regions.default, + owner_id: req.user_id, + afk_timeout: 300, + default_message_notifications: 0, + explicit_content_filter: 0, + features: [], + id: guild_id, + max_members: 250000, + max_presences: 250000, + max_video_channel_users: 25, + presence_count: 0, + member_count: 0, // will automatically be increased by addMember() + mfa_level: 0, + preferred_locale: "en-US", + premium_subscription_count: 0, + premium_tier: 0, + system_channel_flags: 0, + unavailable: false, + verification_level: 0, + welcome_screen: { + enabled: false, + description: "No description", + welcome_channels: [] + }, + widget_enabled: false + }), + Role.insert({ id: guild_id, guild_id: guild_id, color: 0, @@ -74,10 +56,9 @@ router.post("/", check(GuildCreateSchema), async (req: Request, res: Response) = managed: false, mentionable: false, name: "@everyone", - permissions: 2251804225n, - position: 0, - tags: null - }).save() + permissions: String("2251804225"), + position: 0 + }) ]); if (!body.channels || !body.channels.length) body.channels = [{ id: "01", type: 0, name: "general" }]; @@ -94,16 +75,21 @@ router.post("/", check(GuildCreateSchema), async (req: Request, res: Response) = body.channels?.map((x) => { var id = ids.get(x.id) || Snowflake.generate(); - // TODO: should we abort if parent_id is a category? (or not to allow sub category channels) + // TODO: should we abort if parent_id is a category? (to disallow sub category channels) var parent_id = ids.get(x.parent_id); - return createChannel({ ...x, guild_id, id, parent_id }, req.user_id, { keepId: true, skipExistsCheck: true }); + return Channel.createChannel({ ...x, guild_id, id, parent_id }, req.user_id, { + keepId: true, + skipExistsCheck: true, + skipPermissionCheck: true, + skipEventEmit: true + }); }) ); - await addMember(req.user_id, guild_id); + await Member.addToGuild(req.user_id, guild_id); - res.status(201).json({ id: guild.id }); + res.status(201).json({ id: guild_id }); }); export default router; diff --git a/api/src/routes/guilds/templates/index.ts b/api/src/routes/guilds/templates/index.ts
index 7fed3c5d..7a8ac886 100644 --- a/api/src/routes/guilds/templates/index.ts +++ b/api/src/routes/guilds/templates/index.ts
@@ -1,18 +1,16 @@ import { Request, Response, Router } from "express"; const router: Router = Router(); -import { TemplateModel, GuildModel, toObject, UserModel, RoleModel, Snowflake, Guild, Config } from "@fosscord/util"; +import { Template, Guild, Role, Snowflake, Config, User, Member } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { GuildTemplateCreateSchema } from "../../../schema/Guild"; -import { getPublicUser } from "../../../util/User"; import { check } from "../../../util/instanceOf"; -import { addMember } from "../../../util/Member"; router.get("/:code", async (req: Request, res: Response) => { const { code } = req.params; - const template = await TemplateModel.findOne({ code: code }).exec(); + const template = await Template.findOneOrFail({ code: code }); - res.json(toObject(template)).send(); + res.json(template); }); router.post("/:code", check(GuildTemplateCreateSchema), async (req: Request, res: Response) => { @@ -20,26 +18,24 @@ router.post("/:code", check(GuildTemplateCreateSchema), async (req: Request, res const body = req.body as GuildTemplateCreateSchema; const { maxGuilds } = Config.get().limits.user; - const user = await getPublicUser(req.user_id, { guilds: true }); - if (user.guilds.length >= maxGuilds) { + const guild_count = await Member.count({ id: req.user_id }); + if (guild_count >= maxGuilds) { throw new HTTPError(`Maximum number of guilds reached ${maxGuilds}`, 403); } - const template = await TemplateModel.findOne({ code: code }).exec(); + const template = await Template.findOneOrFail({ code: code }); const guild_id = Snowflake.generate(); - const guild: Guild = { - ...body, - ...template.serialized_source_guild, - id: guild_id, - owner_id: req.user_id - }; - - const [guild_doc, role] = await Promise.all([ - new GuildModel(guild).save(), - new RoleModel({ + const [guild, role] = await Promise.all([ + new Guild({ + ...body, + ...template.serialized_source_guild, + id: guild_id, + owner_id: req.user_id + }).save(), + new Role({ id: guild_id, guild_id: guild_id, color: 0, @@ -53,7 +49,7 @@ router.post("/:code", check(GuildTemplateCreateSchema), async (req: Request, res }).save() ]); - await addMember(req.user_id, guild_id, { guild: guild_doc }); + await Member.addToGuild(req.user_id, guild_id); res.status(201).json({ id: guild.id }); });