summary refs log tree commit diff
path: root/src/api
diff options
context:
space:
mode:
authorMadeline <46743919+MaddyUnderStars@users.noreply.github.com>2022-09-26 22:08:14 +1000
committerMadeline <46743919+MaddyUnderStars@users.noreply.github.com>2022-09-26 22:08:14 +1000
commit849b257db7d43c2f1d13d9620ce7f6ba9dfd3e50 (patch)
tree37c9af175c98116a0f48ca2d5c8b74f291b3ce85 /src/api
parentFix scripts/benchmark/connections.js (diff)
downloadserver-849b257db7d43c2f1d13d9620ce7f6ba9dfd3e50.tar.xz
Move schemas to /src/util/schemas
Diffstat (limited to 'src/api')
-rw-r--r--src/api/routes/auth/login.ts11
-rw-r--r--src/api/routes/auth/mfa/totp.ts9
-rw-r--r--src/api/routes/auth/register.ts31
-rw-r--r--src/api/routes/auth/verify/view-backup-codes-challenge.ts6
-rw-r--r--src/api/routes/channels/#channel_id/index.ts33
-rw-r--r--src/api/routes/channels/#channel_id/invites.ts12
-rw-r--r--src/api/routes/channels/#channel_id/messages/#message_id/ack.ts7
-rw-r--r--src/api/routes/channels/#channel_id/messages/#message_id/index.ts6
-rw-r--r--src/api/routes/channels/#channel_id/messages/bulk-delete.ts5
-rw-r--r--src/api/routes/channels/#channel_id/messages/index.ts35
-rw-r--r--src/api/routes/channels/#channel_id/purge.ts14
-rw-r--r--src/api/routes/channels/#channel_id/webhooks.ts11
-rw-r--r--src/api/routes/guilds/#guild_id/audit-logs.ts3
-rw-r--r--src/api/routes/guilds/#guild_id/bans.ts24
-rw-r--r--src/api/routes/guilds/#guild_id/channels.ts3
-rw-r--r--src/api/routes/guilds/#guild_id/emojis.ts14
-rw-r--r--src/api/routes/guilds/#guild_id/index.ts4
-rw-r--r--src/api/routes/guilds/#guild_id/integrations.ts3
-rw-r--r--src/api/routes/guilds/#guild_id/members/#member_id/index.ts8
-rw-r--r--src/api/routes/guilds/#guild_id/members/#member_id/nick.ts4
-rw-r--r--src/api/routes/guilds/#guild_id/prune.ts7
-rw-r--r--src/api/routes/guilds/#guild_id/roles/#role_id/index.ts3
-rw-r--r--src/api/routes/guilds/#guild_id/roles/index.ts15
-rw-r--r--src/api/routes/guilds/#guild_id/stickers.ts20
-rw-r--r--src/api/routes/guilds/#guild_id/templates.ts10
-rw-r--r--src/api/routes/guilds/#guild_id/vanity-url.ts10
-rw-r--r--src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts12
-rw-r--r--src/api/routes/guilds/#guild_id/webhooks.ts3
-rw-r--r--src/api/routes/guilds/#guild_id/welcome-screen.ts13
-rw-r--r--src/api/routes/guilds/#guild_id/widget.ts7
-rw-r--r--src/api/routes/guilds/index.ts16
-rw-r--r--src/api/routes/guilds/templates/index.ts7
-rw-r--r--src/api/routes/users/@me/channels.ts7
-rw-r--r--src/api/routes/users/@me/index.ts22
-rw-r--r--src/api/routes/users/@me/mfa/codes-verification.ts8
-rw-r--r--src/api/routes/users/@me/mfa/codes.ts7
-rw-r--r--src/api/routes/users/@me/mfa/totp/disable.ts6
-rw-r--r--src/api/routes/users/@me/mfa/totp/enable.ts9
-rw-r--r--src/api/routes/users/@me/relationships.ts9
-rw-r--r--src/api/util/handlers/Message.ts2
40 files changed, 35 insertions, 401 deletions
diff --git a/src/api/routes/auth/login.ts b/src/api/routes/auth/login.ts
index bcaccb30..9bed5aab 100644
--- a/src/api/routes/auth/login.ts
+++ b/src/api/routes/auth/login.ts
@@ -1,21 +1,12 @@
 import { Request, Response, Router } from "express";
 import { route, getIpAdress, verifyCaptcha } from "@fosscord/api";
 import bcrypt from "bcrypt";
-import { Config, User, generateToken, adjustEmail, FieldErrors } from "@fosscord/util";
+import { Config, User, generateToken, adjustEmail, FieldErrors, LoginSchema } from "@fosscord/util";
 import crypto from "crypto";
 
 const router: Router = Router();
 export default router;
 
-export interface LoginSchema {
-	login: string;
-	password: string;
-	undelete?: boolean;
-	captcha_key?: string;
-	login_source?: string;
-	gift_code_sku_id?: string;
-}
-
 router.post("/", route({ body: "LoginSchema" }), async (req: Request, res: Response) => {
 	const { login, password, captcha_key, undelete } = req.body as LoginSchema;
 	const email = adjustEmail(login);
diff --git a/src/api/routes/auth/mfa/totp.ts b/src/api/routes/auth/mfa/totp.ts
index 50b9e9c8..96a48b66 100644
--- a/src/api/routes/auth/mfa/totp.ts
+++ b/src/api/routes/auth/mfa/totp.ts
@@ -1,17 +1,10 @@
 import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
-import { BackupCode, FieldErrors, generateToken, User } from "@fosscord/util";
+import { BackupCode, generateToken, User, TotpSchema } from "@fosscord/util";
 import { verifyToken } from "node-2fa";
 import { HTTPError } from "lambert-server";
 const router = Router();
 
-export interface TotpSchema {
-	code: string,
-	ticket: string,
-	gift_code_sku_id?: string | null,
-	login_source?: string | null,
-}
-
 router.post("/", route({ body: "TotpSchema" }), async (req: Request, res: Response) => {
 	const { code, ticket, gift_code_sku_id, login_source } = req.body as TotpSchema;
 
diff --git a/src/api/routes/auth/register.ts b/src/api/routes/auth/register.ts
index b7122dad..84f8f838 100644
--- a/src/api/routes/auth/register.ts
+++ b/src/api/routes/auth/register.ts
@@ -1,40 +1,11 @@
 import { Request, Response, Router } from "express";
-import { Config, generateToken, Invite, FieldErrors, User, adjustEmail } from "@fosscord/util";
+import { Config, generateToken, Invite, FieldErrors, User, adjustEmail, RegisterSchema } from "@fosscord/util";
 import { route, getIpAdress, IPAnalysis, isProxy, verifyCaptcha } from "@fosscord/api";
-import "missing-native-js-functions";
 import bcrypt from "bcrypt";
 import { HTTPError } from "lambert-server";
 
 const router: Router = Router();
 
-export interface RegisterSchema {
-	/**
-	 * @minLength 2
-	 * @maxLength 32
-	 */
-	username: string;
-	/**
-	 * @minLength 1
-	 * @maxLength 72
-	 */
-	password?: string;
-	consent: boolean;
-	/**
-	 * @TJS-format email
-	 */
-	email?: string;
-	fingerprint?: string;
-	invite?: string;
-	/**
-	 * @TJS-type string
-	 */
-	date_of_birth?: Date; // "2000-04-03"
-	gift_code_sku_id?: string;
-	captcha_key?: string;
-
-	promotional_email_opt_in?: boolean;
-}
-
 router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Response) => {
 	const body = req.body as RegisterSchema;
 	const { register, security } = Config.get();
diff --git a/src/api/routes/auth/verify/view-backup-codes-challenge.ts b/src/api/routes/auth/verify/view-backup-codes-challenge.ts
index 36bfeb0c..24de8ec5 100644
--- a/src/api/routes/auth/verify/view-backup-codes-challenge.ts
+++ b/src/api/routes/auth/verify/view-backup-codes-challenge.ts
@@ -1,13 +1,9 @@
 import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
-import { FieldErrors, User } from "@fosscord/util";
+import { FieldErrors, User, BackupCodesChallengeSchema } from "@fosscord/util";
 import bcrypt from "bcrypt";
 const router = Router();
 
-export interface BackupCodesChallengeSchema {
-	password: string;
-}
-
 router.post("/", route({ body: "BackupCodesChallengeSchema" }), async (req: Request, res: Response) => {
 	const { password } = req.body as BackupCodesChallengeSchema;
 
diff --git a/src/api/routes/channels/#channel_id/index.ts b/src/api/routes/channels/#channel_id/index.ts
index 0340a616..8dbefe1b 100644
--- a/src/api/routes/channels/#channel_id/index.ts
+++ b/src/api/routes/channels/#channel_id/index.ts
@@ -1,12 +1,12 @@
 import {
 	Channel,
 	ChannelDeleteEvent,
-	ChannelPermissionOverwriteType,
 	ChannelType,
 	ChannelUpdateEvent,
 	emitEvent,
 	Recipient,
-	handleFile
+	handleFile,
+	ChannelModifySchema
 } from "@fosscord/util";
 import { Request, Response, Router } from "express";
 import { route } from "@fosscord/api";
@@ -47,35 +47,6 @@ router.delete("/", route({ permission: "MANAGE_CHANNELS" }), async (req: Request
 	res.send(channel);
 });
 
-export interface ChannelModifySchema {
-	/**
-	 * @maxLength 100
-	 */
-	name?: string;
-	type?: ChannelType;
-	topic?: string;
-	icon?: string | null;
-	bitrate?: number;
-	user_limit?: number;
-	rate_limit_per_user?: number;
-	position?: number;
-	permission_overwrites?: {
-		id: string;
-		type: ChannelPermissionOverwriteType;
-		allow: string;
-		deny: string;
-	}[];
-	parent_id?: string;
-	id?: string; // is not used (only for guild create)
-	nsfw?: boolean;
-	rtc_region?: string;
-	default_auto_archive_duration?: number;
-	default_reaction_emoji?: string | null;
-	flags?: number;
-	default_thread_rate_limit_per_user?: number;
-	video_quality_mode?: number;
-}
-
 router.patch("/", route({ body: "ChannelModifySchema", permission: "MANAGE_CHANNELS" }), async (req: Request, res: Response) => {
 	var payload = req.body as ChannelModifySchema;
 	const { channel_id } = req.params;
diff --git a/src/api/routes/channels/#channel_id/invites.ts b/src/api/routes/channels/#channel_id/invites.ts
index fd8339ad..246a2c69 100644
--- a/src/api/routes/channels/#channel_id/invites.ts
+++ b/src/api/routes/channels/#channel_id/invites.ts
@@ -7,18 +7,6 @@ import { isTextChannel } from "./messages";
 
 const router: Router = Router();
 
-export interface InviteCreateSchema {
-	target_user_id?: string;
-	target_type?: string;
-	validate?: string; // ? what is this
-	max_age?: number;
-	max_uses?: number;
-	temporary?: boolean;
-	unique?: boolean;
-	target_user?: string;
-	target_user_type?: number;
-}
-
 router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INSTANT_INVITE", right: "CREATE_INVITES" }),
 	async (req: Request, res: Response) => {
 		const { user_id } = req;
diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/ack.ts b/src/api/routes/channels/#channel_id/messages/#message_id/ack.ts
index 3abae7ce..bedd453c 100644
--- a/src/api/routes/channels/#channel_id/messages/#message_id/ack.ts
+++ b/src/api/routes/channels/#channel_id/messages/#message_id/ack.ts
@@ -1,4 +1,4 @@
-import { emitEvent, getPermission, MessageAckEvent, ReadState, Snowflake } from "@fosscord/util";
+import { emitEvent, getPermission, MessageAckEvent, ReadState } from "@fosscord/util";
 import { Request, Response, Router } from "express";
 import { route } from "@fosscord/api";
 
@@ -8,11 +8,6 @@ const router = Router();
 // TODO: send read state event to all channel members
 // TODO: advance-only notification cursor
 
-export interface MessageAcknowledgeSchema {
-	manual?: boolean;
-	mention_count?: number;
-}
-
 router.post("/", route({ body: "MessageAcknowledgeSchema" }), async (req: Request, res: Response) => {
 	const { channel_id, message_id } = req.params;
 
diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/index.ts b/src/api/routes/channels/#channel_id/messages/#message_id/index.ts
index a02a9abe..46b0d6bd 100644
--- a/src/api/routes/channels/#channel_id/messages/#message_id/index.ts
+++ b/src/api/routes/channels/#channel_id/messages/#message_id/index.ts
@@ -1,8 +1,6 @@
 import {
 	Attachment,
 	Channel,
-	Embed,
-	DiscordApiErrors,
 	emitEvent,
 	FosscordApiErrors,
 	getPermission,
@@ -12,13 +10,13 @@ import {
 	MessageDeleteEvent,
 	MessageUpdateEvent,
 	Snowflake,
-	uploadFile
+	uploadFile,
+	MessageCreateSchema,
 } from "@fosscord/util";
 import { Router, Response, Request } from "express";
 import multer from "multer";
 import { route } from "@fosscord/api";
 import { handleMessage, postHandleMessage } from "@fosscord/api";
-import { MessageCreateSchema } from "../index";
 import { HTTPError } from "lambert-server";
 
 const router = Router();
diff --git a/src/api/routes/channels/#channel_id/messages/bulk-delete.ts b/src/api/routes/channels/#channel_id/messages/bulk-delete.ts
index b6fd37f4..6493c16a 100644
--- a/src/api/routes/channels/#channel_id/messages/bulk-delete.ts
+++ b/src/api/routes/channels/#channel_id/messages/bulk-delete.ts
@@ -2,16 +2,11 @@ import { Router, Response, Request } from "express";
 import { Channel, Config, emitEvent, getPermission, getRights, MessageDeleteBulkEvent, Message } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
-import { In } from "typeorm";
 
 const router: Router = Router();
 
 export default router;
 
-export interface BulkDeleteSchema {
-	messages: string[];
-}
-
 // should users be able to bulk delete messages or only bots? ANSWER: all users
 // should this request fail, if you provide messages older than 14 days/invalid ids? ANSWER: NO
 // https://discord.com/developers/docs/resources/channel#bulk-delete-messages
diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts
index 154dc8ed..bee93e80 100644
--- a/src/api/routes/channels/#channel_id/messages/index.ts
+++ b/src/api/routes/channels/#channel_id/messages/index.ts
@@ -5,16 +5,15 @@ import {
 	ChannelType,
 	Config,
 	DmChannelDTO,
-	Embed,
 	emitEvent,
 	getPermission,
-	getRights,
 	Message,
 	MessageCreateEvent,
 	Snowflake,
 	uploadFile,
 	Member,
 	Role,
+	MessageCreateSchema,
 } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { handleMessage, postHandleMessage, route } from "@fosscord/api";
@@ -50,38 +49,6 @@ export function isTextChannel(type: ChannelType): boolean {
 	}
 }
 
-export interface MessageCreateSchema {
-	type?: number;
-	content?: string;
-	nonce?: string;
-	channel_id?: string;
-	tts?: boolean;
-	flags?: string;
-	embeds?: Embed[];
-	embed?: Embed;
-	// TODO: ^ embed is deprecated in favor of embeds (https://discord.com/developers/docs/resources/channel#message-object)
-	allowed_mentions?: {
-		parse?: string[];
-		roles?: string[];
-		users?: string[];
-		replied_user?: boolean;
-	};
-	message_reference?: {
-		message_id: string;
-		channel_id: string;
-		guild_id?: string;
-		fail_if_not_exists?: boolean;
-	};
-	payload_json?: string;
-	file?: any;
-	/**
-	TODO: we should create an interface for attachments
-	TODO: OpenWAAO<-->attachment-style metadata conversion
-	**/
-	attachments?: any[];
-	sticker_ids?: string[];
-}
-
 // https://discord.com/developers/docs/resources/channel#create-message
 // get messages
 router.get("/", async (req: Request, res: Response) => {
diff --git a/src/api/routes/channels/#channel_id/purge.ts b/src/api/routes/channels/#channel_id/purge.ts
index bfac27ee..9fe6b658 100644
--- a/src/api/routes/channels/#channel_id/purge.ts
+++ b/src/api/routes/channels/#channel_id/purge.ts
@@ -3,33 +3,21 @@ import { route } from "@fosscord/api";
 import { isTextChannel } from "./messages";
 import { FindManyOptions, Between, Not } from "typeorm";
 import {
-	Attachment,
 	Channel,
 	Config,
-	Embed,
-	DiscordApiErrors,
 	emitEvent,
-	FosscordApiErrors,
 	getPermission,
 	getRights,
 	Message,
 	MessageDeleteBulkEvent,
-	Snowflake,
-	uploadFile
+	PurgeSchema,
 } from "@fosscord/util";
 import { Router, Response, Request } from "express";
-import multer from "multer";
-import { handleMessage, postHandleMessage } from "@fosscord/api";
 
 const router: Router = Router();
 
 export default router;
 
-export interface PurgeSchema {
-	before: string;
-	after: string;
-}
-
 /**
 TODO: apply the delete bit by bit to prevent client and database stress
 **/
diff --git a/src/api/routes/channels/#channel_id/webhooks.ts b/src/api/routes/channels/#channel_id/webhooks.ts
index 93f70a41..99c104ca 100644
--- a/src/api/routes/channels/#channel_id/webhooks.ts
+++ b/src/api/routes/channels/#channel_id/webhooks.ts
@@ -1,19 +1,12 @@
 import { Router, Response, Request } from "express";
 import { route } from "@fosscord/api";
-import { Channel, Config, getPermission, trimSpecial, Webhook } from "@fosscord/util";
+import { Channel, Config, trimSpecial, Webhook } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { isTextChannel } from "./messages/index";
 import { DiscordApiErrors } from "@fosscord/util";
 
 const router: Router = Router();
-// TODO: webhooks
-export interface WebhookCreateSchema {
-	/**
-	 * @maxLength 80
-	 */
-	name: string;
-	avatar: string;
-}
+
 //TODO: implement webhooks
 router.get("/", route({}), async (req: Request, res: Response) => {
 	res.json([]);
diff --git a/src/api/routes/guilds/#guild_id/audit-logs.ts b/src/api/routes/guilds/#guild_id/audit-logs.ts
index a4f2f800..b54835fc 100644
--- a/src/api/routes/guilds/#guild_id/audit-logs.ts
+++ b/src/api/routes/guilds/#guild_id/audit-logs.ts
@@ -1,8 +1,5 @@
 import { Router, Response, Request } from "express";
-import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../../channels/#channel_id";
 const router = Router();
 
 //TODO: implement audit logs
diff --git a/src/api/routes/guilds/#guild_id/bans.ts b/src/api/routes/guilds/#guild_id/bans.ts
index 51d3ca67..ed00f9c0 100644
--- a/src/api/routes/guilds/#guild_id/bans.ts
+++ b/src/api/routes/guilds/#guild_id/bans.ts
@@ -1,30 +1,8 @@
 import { Request, Response, Router } from "express";
-import { DiscordApiErrors, emitEvent, GuildBanAddEvent, GuildBanRemoveEvent, Ban, User, Member } from "@fosscord/util";
+import { DiscordApiErrors, emitEvent, GuildBanAddEvent, GuildBanRemoveEvent, Ban, User, Member, BanRegistrySchema, BanModeratorSchema } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { getIpAdress, route } from "@fosscord/api";
 
-export interface BanCreateSchema {
-	delete_message_days?: string;
-	reason?: string;
-};
-
-export interface BanRegistrySchema {
-	id: string;
-	user_id: string;
-	guild_id: string;
-	executor_id: string;
-	ip?: string;
-	reason?: string | undefined;
-};
-
-export interface BanModeratorSchema {
-	id: string;
-	user_id: string;
-	guild_id: string;
-	executor_id: string;
-	reason?: string | undefined;
-};
-
 const router: Router = Router();
 
 /* TODO: Deleting the secrets is just a temporary go-around. Views should be implemented for both safety and better handling. */
diff --git a/src/api/routes/guilds/#guild_id/channels.ts b/src/api/routes/guilds/#guild_id/channels.ts
index 11f727fc..7a5b50d1 100644
--- a/src/api/routes/guilds/#guild_id/channels.ts
+++ b/src/api/routes/guilds/#guild_id/channels.ts
@@ -1,8 +1,7 @@
 import { Router, Response, Request } from "express";
-import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
+import { Channel, ChannelUpdateEvent, emitEvent, ChannelModifySchema } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../../channels/#channel_id";
 const router = Router();
 
 router.get("/", route({}), async (req: Request, res: Response) => {
diff --git a/src/api/routes/guilds/#guild_id/emojis.ts b/src/api/routes/guilds/#guild_id/emojis.ts
index 75998e04..cf9d742a 100644
--- a/src/api/routes/guilds/#guild_id/emojis.ts
+++ b/src/api/routes/guilds/#guild_id/emojis.ts
@@ -1,21 +1,9 @@
 import { Router, Request, Response } from "express";
-import { Config, DiscordApiErrors, emitEvent, Emoji, GuildEmojisUpdateEvent, handleFile, Member, Snowflake, User } from "@fosscord/util";
+import { Config, DiscordApiErrors, emitEvent, Emoji, GuildEmojisUpdateEvent, handleFile, Member, Snowflake, User, EmojiCreateSchema, EmojiModifySchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 
 const router = Router();
 
-export interface EmojiCreateSchema {
-	name?: string;
-	image: string;
-	require_colons?: boolean | null;
-	roles?: string[];
-}
-
-export interface EmojiModifySchema {
-	name?: string;
-	roles?: string[];
-}
-
 router.get("/", route({}), async (req: Request, res: Response) => {
 	const { guild_id } = req.params;
 
diff --git a/src/api/routes/guilds/#guild_id/index.ts b/src/api/routes/guilds/#guild_id/index.ts
index 45bbe348..afeb0938 100644
--- a/src/api/routes/guilds/#guild_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/index.ts
@@ -1,9 +1,7 @@
 import { Request, Response, Router } from "express";
-import { DiscordApiErrors, emitEvent, getPermission, getRights, Guild, GuildUpdateEvent, handleFile, Member } from "@fosscord/util";
+import { DiscordApiErrors, emitEvent, getPermission, getRights, Guild, GuildUpdateEvent, handleFile, Member, GuildCreateSchema } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
-import "missing-native-js-functions";
-import { GuildCreateSchema } from "../index";
 
 const router = Router();
 
diff --git a/src/api/routes/guilds/#guild_id/integrations.ts b/src/api/routes/guilds/#guild_id/integrations.ts
index abf997c9..a8e78062 100644
--- a/src/api/routes/guilds/#guild_id/integrations.ts
+++ b/src/api/routes/guilds/#guild_id/integrations.ts
@@ -1,8 +1,5 @@
 import { Router, Response, Request } from "express";
-import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../../channels/#channel_id";
 const router = Router();
 
 //TODO: implement integrations list
diff --git a/src/api/routes/guilds/#guild_id/members/#member_id/index.ts b/src/api/routes/guilds/#guild_id/members/#member_id/index.ts
index d785eb00..407619d3 100644
--- a/src/api/routes/guilds/#guild_id/members/#member_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/members/#member_id/index.ts
@@ -1,15 +1,9 @@
 import { Request, Response, Router } from "express";
-import { Member, getPermission, getRights, Role, GuildMemberUpdateEvent, emitEvent, Sticker, Emoji, Rights, Guild } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { Member, getPermission, getRights, Role, GuildMemberUpdateEvent, emitEvent, Sticker, Emoji, Guild, MemberChangeSchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 
 const router = Router();
 
-export interface MemberChangeSchema {
-	roles?: string[];
-	nick?: string;
-}
-
 router.get("/", route({}), async (req: Request, res: Response) => {
 	const { guild_id, member_id } = req.params;
 	await Member.IsInGuildOrFail(req.user_id, guild_id);
diff --git a/src/api/routes/guilds/#guild_id/members/#member_id/nick.ts b/src/api/routes/guilds/#guild_id/members/#member_id/nick.ts
index 27f7f65d..edd47605 100644
--- a/src/api/routes/guilds/#guild_id/members/#member_id/nick.ts
+++ b/src/api/routes/guilds/#guild_id/members/#member_id/nick.ts
@@ -4,10 +4,6 @@ import { Request, Response, Router } from "express";
 
 const router = Router();
 
-export interface MemberNickChangeSchema {
-	nick: string;
-}
-
 router.patch("/", route({ body: "MemberNickChangeSchema" }), async (req: Request, res: Response) => {
 	var { guild_id, member_id } = req.params;
 	var permissionString: PermissionResolvable = "MANAGE_NICKNAMES";
diff --git a/src/api/routes/guilds/#guild_id/prune.ts b/src/api/routes/guilds/#guild_id/prune.ts
index cf3466f1..2e674349 100644
--- a/src/api/routes/guilds/#guild_id/prune.ts
+++ b/src/api/routes/guilds/#guild_id/prune.ts
@@ -62,13 +62,6 @@ router.get("/", route({}), async (req: Request, res: Response) => {
 	res.send({ pruned: members.length });
 });
 
-export interface PruneSchema {
-	/**
-	 * @min 0
-	 */
-	days: number;
-}
-
 router.post("/", route({ permission: "KICK_MEMBERS", right: "KICK_BAN_MEMBERS" }), async (req: Request, res: Response) => {
 	const days = parseInt(req.body.days);
 
diff --git a/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts b/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts
index a01068c0..87cf5261 100644
--- a/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts
@@ -1,8 +1,7 @@
 import { Router, Request, Response } from "express";
-import { Role, Member, GuildRoleUpdateEvent, GuildRoleDeleteEvent, emitEvent, handleFile } from "@fosscord/util";
+import { Role, Member, GuildRoleUpdateEvent, GuildRoleDeleteEvent, emitEvent, handleFile, RoleModifySchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 import { HTTPError } from "lambert-server";
-import { RoleModifySchema } from "../";
 
 const router = Router();
 
diff --git a/src/api/routes/guilds/#guild_id/roles/index.ts b/src/api/routes/guilds/#guild_id/roles/index.ts
index 7e839f08..c5a86400 100644
--- a/src/api/routes/guilds/#guild_id/roles/index.ts
+++ b/src/api/routes/guilds/#guild_id/roles/index.ts
@@ -5,28 +5,15 @@ import {
 	Member,
 	GuildRoleCreateEvent,
 	GuildRoleUpdateEvent,
-	GuildRoleDeleteEvent,
 	emitEvent,
 	Config,
 	DiscordApiErrors,
-	handleFile
+	RoleModifySchema,
 } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
 
 const router: Router = Router();
 
-export interface RoleModifySchema {
-	name?: string;
-	permissions?: string;
-	color?: number;
-	hoist?: boolean; // whether the role should be displayed separately in the sidebar
-	mentionable?: boolean; // whether the role should be mentionable
-	position?: number;
-	icon?: string;
-	unicode_emoji?: string;
-}
-
 export type RolePositionUpdateSchema = {
 	id: string;
 	position: number;
diff --git a/src/api/routes/guilds/#guild_id/stickers.ts b/src/api/routes/guilds/#guild_id/stickers.ts
index 7a4e71ee..fc0f49ab 100644
--- a/src/api/routes/guilds/#guild_id/stickers.ts
+++ b/src/api/routes/guilds/#guild_id/stickers.ts
@@ -1,13 +1,13 @@
 import {
 	emitEvent,
 	GuildStickersUpdateEvent,
-	handleFile,
 	Member,
 	Snowflake,
 	Sticker,
 	StickerFormatType,
 	StickerType,
-	uploadFile
+	uploadFile,
+	ModifyGuildStickerSchema,
 } from "@fosscord/util";
 import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
@@ -82,22 +82,6 @@ router.get("/:sticker_id", route({}), async (req: Request, res: Response) => {
 	res.json(await Sticker.findOneOrFail({ where: { guild_id, id: sticker_id } }));
 });
 
-export interface ModifyGuildStickerSchema {
-	/**
-	 * @minLength 2
-	 * @maxLength 30
-	 */
-	name: string;
-	/**
-	 * @maxLength 100
-	 */
-	description?: string;
-	/**
-	 * @maxLength 200
-	 */
-	tags: string;
-}
-
 router.patch(
 	"/:sticker_id",
 	route({ body: "ModifyGuildStickerSchema", permission: "MANAGE_EMOJIS_AND_STICKERS" }),
diff --git a/src/api/routes/guilds/#guild_id/templates.ts b/src/api/routes/guilds/#guild_id/templates.ts
index 0444c402..628321f5 100644
--- a/src/api/routes/guilds/#guild_id/templates.ts
+++ b/src/api/routes/guilds/#guild_id/templates.ts
@@ -23,16 +23,6 @@ const TemplateGuildProjection: (keyof Guild)[] = [
 	"icon"
 ];
 
-export interface TemplateCreateSchema {
-	name: string;
-	description?: string;
-}
-
-export interface TemplateModifySchema {
-	name: string;
-	description?: string;
-}
-
 router.get("/", route({}), async (req: Request, res: Response) => {
 	const { guild_id } = req.params;
 
diff --git a/src/api/routes/guilds/#guild_id/vanity-url.ts b/src/api/routes/guilds/#guild_id/vanity-url.ts
index 040bc1fd..d1fe4726 100644
--- a/src/api/routes/guilds/#guild_id/vanity-url.ts
+++ b/src/api/routes/guilds/#guild_id/vanity-url.ts
@@ -1,4 +1,4 @@
-import { Channel, ChannelType, getPermission, Guild, Invite, trimSpecial } from "@fosscord/util";
+import { Channel, ChannelType, Guild, Invite, VanityUrlSchema } from "@fosscord/util";
 import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
 import { HTTPError } from "lambert-server";
@@ -24,14 +24,6 @@ router.get("/", route({ permission: "MANAGE_GUILD" }), async (req: Request, res:
 	}
 });
 
-export interface VanityUrlSchema {
-	/**
-	 * @minLength 1
-	 * @maxLength 20
-	 */
-	code?: string;
-}
-
 router.patch("/", route({ body: "VanityUrlSchema", permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => {
 	const { guild_id } = req.params;
 	const body = req.body as VanityUrlSchema;
diff --git a/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts b/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts
index b7fdfecd..006e997f 100644
--- a/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts
@@ -1,20 +1,10 @@
-import { Channel, ChannelType, DiscordApiErrors, emitEvent, getPermission, VoiceState, VoiceStateUpdateEvent } from "@fosscord/util";
+import { Channel, ChannelType, DiscordApiErrors, emitEvent, getPermission, VoiceState, VoiceStateUpdateEvent, VoiceStateUpdateSchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 import { Request, Response, Router } from "express";
 
 const router = Router();
 //TODO need more testing when community guild and voice stage channel are working
 
-export interface VoiceStateUpdateSchema {
-	channel_id: string;
-	guild_id?: string;
-	suppress?: boolean;
-	request_to_speak_timestamp?: Date;
-	self_mute?: boolean;
-	self_deaf?: boolean;
-	self_video?: boolean;
-}
-
 router.patch("/", route({ body: "VoiceStateUpdateSchema" }), async (req: Request, res: Response) => {
 	const body = req.body as VoiceStateUpdateSchema;
 	var { guild_id, user_id } = req.params;
diff --git a/src/api/routes/guilds/#guild_id/webhooks.ts b/src/api/routes/guilds/#guild_id/webhooks.ts
index 8b2febea..9c4e8a8d 100644
--- a/src/api/routes/guilds/#guild_id/webhooks.ts
+++ b/src/api/routes/guilds/#guild_id/webhooks.ts
@@ -1,8 +1,5 @@
 import { Router, Response, Request } from "express";
-import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../../channels/#channel_id";
 const router = Router();
 
 //TODO: implement webhooks
diff --git a/src/api/routes/guilds/#guild_id/welcome-screen.ts b/src/api/routes/guilds/#guild_id/welcome-screen.ts
index a57255f0..57da062d 100644
--- a/src/api/routes/guilds/#guild_id/welcome-screen.ts
+++ b/src/api/routes/guilds/#guild_id/welcome-screen.ts
@@ -1,21 +1,10 @@
 import { Request, Response, Router } from "express";
-import { Guild, getPermission, Snowflake, Member } from "@fosscord/util";
+import { Guild, Member, GuildUpdateWelcomeScreenSchema } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
 
 const router: Router = Router();
 
-export interface GuildUpdateWelcomeScreenSchema {
-	welcome_channels?: {
-		channel_id: string;
-		description: string;
-		emoji_id?: string;
-		emoji_name?: string;
-	}[];
-	enabled?: boolean;
-	description?: string;
-}
-
 router.get("/", route({}), async (req: Request, res: Response) => {
 	const guild_id = req.params.guild_id;
 
diff --git a/src/api/routes/guilds/#guild_id/widget.ts b/src/api/routes/guilds/#guild_id/widget.ts
index 103f84a3..dbb4cc0c 100644
--- a/src/api/routes/guilds/#guild_id/widget.ts
+++ b/src/api/routes/guilds/#guild_id/widget.ts
@@ -1,12 +1,7 @@
 import { Request, Response, Router } from "express";
-import { Guild } from "@fosscord/util";
+import { Guild, WidgetModifySchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 
-export interface WidgetModifySchema {
-	enabled: boolean; // whether the widget is enabled
-	channel_id: string; // the widget channel id
-}
-
 const router: Router = Router();
 
 // https://discord.com/developers/docs/resources/guild#get-guild-widget-settings
diff --git a/src/api/routes/guilds/index.ts b/src/api/routes/guilds/index.ts
index d44cd735..0807cb96 100644
--- a/src/api/routes/guilds/index.ts
+++ b/src/api/routes/guilds/index.ts
@@ -1,23 +1,9 @@
 import { Router, Request, Response } from "express";
-import { Role, Guild, Snowflake, Config, getRights, Member, Channel, DiscordApiErrors, handleFile } from "@fosscord/util";
+import { Role, Guild, Config, getRights, Member, DiscordApiErrors, GuildCreateSchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../channels/#channel_id";
 
 const router: Router = Router();
 
-export interface GuildCreateSchema {
-	/**
-	 * @maxLength 100
-	 */
-	name?: string;
-	region?: string;
-	icon?: string | null;
-	channels?: ChannelModifySchema[];
-	guild_template_code?: string;
-	system_channel_id?: string;
-	rules_channel_id?: string;
-}
-
 //TODO: create default channel
 
 router.post("/", route({ body: "GuildCreateSchema", right: "CREATE_GUILDS" }), async (req: Request, res: Response) => {
diff --git a/src/api/routes/guilds/templates/index.ts b/src/api/routes/guilds/templates/index.ts
index e281214f..4e7abcc5 100644
--- a/src/api/routes/guilds/templates/index.ts
+++ b/src/api/routes/guilds/templates/index.ts
@@ -1,15 +1,10 @@
 import { Request, Response, Router } from "express";
-import { Template, Guild, Role, Snowflake, Config, User, Member } from "@fosscord/util";
+import { Template, Guild, Role, Snowflake, Config, Member, GuildTemplateCreateSchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 import { DiscordApiErrors } from "@fosscord/util";
 import fetch from "node-fetch";
 const router: Router = Router();
 
-export interface GuildTemplateCreateSchema {
-	name: string;
-	avatar?: string | null;
-}
-
 router.get("/:code", route({}), async (req: Request, res: Response) => {
 	const { allowDiscordTemplates, allowRaws, enabled } = Config.get().templates;
 	if (!enabled) res.json({ code: 403, message: "Template creation & usage is disabled on this instance." }).sendStatus(403);
diff --git a/src/api/routes/users/@me/channels.ts b/src/api/routes/users/@me/channels.ts
index 78f531e1..ad483529 100644
--- a/src/api/routes/users/@me/channels.ts
+++ b/src/api/routes/users/@me/channels.ts
@@ -1,5 +1,5 @@
 import { Request, Response, Router } from "express";
-import { Recipient, DmChannelDTO, Channel } from "@fosscord/util";
+import { Recipient, DmChannelDTO, Channel, DmChannelCreateSchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 
 const router: Router = Router();
@@ -12,11 +12,6 @@ router.get("/", route({}), async (req: Request, res: Response) => {
 	res.json(await Promise.all(recipients.map((r) => DmChannelDTO.from(r.channel, [req.user_id]))));
 });
 
-export interface DmChannelCreateSchema {
-	name?: string;
-	recipients: string[];
-}
-
 router.post("/", route({ body: "DmChannelCreateSchema" }), async (req: Request, res: Response) => {
 	const body = req.body as DmChannelCreateSchema;
 	res.json(await Channel.createDMChannel(body.recipients, req.user_id, body.name));
diff --git a/src/api/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts
index 36b62b55..e849b72a 100644
--- a/src/api/routes/users/@me/index.ts
+++ b/src/api/routes/users/@me/index.ts
@@ -1,31 +1,11 @@
 import { Router, Request, Response } from "express";
-import { User, PrivateUserProjection, emitEvent, UserUpdateEvent, handleFile, FieldErrors, adjustEmail, Config } from "@fosscord/util";
+import { User, PrivateUserProjection, emitEvent, UserUpdateEvent, handleFile, FieldErrors, adjustEmail, Config, UserModifySchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 import bcrypt from "bcrypt";
 import { HTTPError } from "lambert-server";
 
 const router: Router = Router();
 
-export interface UserModifySchema {
-	/**
-	 * @minLength 1
-	 * @maxLength 100
-	 */
-	username?: string;
-	avatar?: string | null;
-	/**
-	 * @maxLength 1024
-	 */
-	bio?: string;
-	accent_color?: number;
-	banner?: string | null;
-	password?: string;
-	new_password?: string;
-	code?: string;
-	email?: string;
-	discriminator?: string;
-}
-
 router.get("/", route({}), async (req: Request, res: Response) => {
 	res.json(await User.findOne({ select: PrivateUserProjection, where: { id: req.user_id } }));
 });
diff --git a/src/api/routes/users/@me/mfa/codes-verification.ts b/src/api/routes/users/@me/mfa/codes-verification.ts
index 09000d07..071c71fa 100644
--- a/src/api/routes/users/@me/mfa/codes-verification.ts
+++ b/src/api/routes/users/@me/mfa/codes-verification.ts
@@ -1,15 +1,9 @@
 import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
-import { BackupCode, generateMfaBackupCodes, User } from "@fosscord/util";
+import { BackupCode, generateMfaBackupCodes, User, CodesVerificationSchema } from "@fosscord/util";
 
 const router = Router();
 
-export interface CodesVerificationSchema {
-	key: string;
-	nonce: string;
-	regenerate?: boolean;
-}
-
 router.post("/", route({ body: "CodesVerificationSchema" }), async (req: Request, res: Response) => {
 	const { key, nonce, regenerate } = req.body as CodesVerificationSchema;
 
diff --git a/src/api/routes/users/@me/mfa/codes.ts b/src/api/routes/users/@me/mfa/codes.ts
index 67bd3d5b..58466b9c 100644
--- a/src/api/routes/users/@me/mfa/codes.ts
+++ b/src/api/routes/users/@me/mfa/codes.ts
@@ -1,15 +1,10 @@
 import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
-import { BackupCode, FieldErrors, generateMfaBackupCodes, User } from "@fosscord/util";
+import { BackupCode, FieldErrors, generateMfaBackupCodes, User, MfaCodesSchema } from "@fosscord/util";
 import bcrypt from "bcrypt";
 
 const router = Router();
 
-export interface MfaCodesSchema {
-	password: string;
-	regenerate?: boolean;
-}
-
 // TODO: This route is replaced with users/@me/mfa/codes-verification in newer clients
 
 router.post("/", route({ body: "MfaCodesSchema" }), async (req: Request, res: Response) => {
diff --git a/src/api/routes/users/@me/mfa/totp/disable.ts b/src/api/routes/users/@me/mfa/totp/disable.ts
index 2d385fda..2fe9355c 100644
--- a/src/api/routes/users/@me/mfa/totp/disable.ts
+++ b/src/api/routes/users/@me/mfa/totp/disable.ts
@@ -2,14 +2,10 @@ import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
 import { verifyToken } from 'node-2fa';
 import { HTTPError } from "lambert-server";
-import { User, generateToken, BackupCode } from "@fosscord/util";
+import { User, generateToken, BackupCode, TotpDisableSchema } from "@fosscord/util";
 
 const router = Router();
 
-export interface TotpDisableSchema {
-	code: string;
-}
-
 router.post("/", route({ body: "TotpDisableSchema" }), async (req: Request, res: Response) => {
 	const body = req.body as TotpDisableSchema;
 
diff --git a/src/api/routes/users/@me/mfa/totp/enable.ts b/src/api/routes/users/@me/mfa/totp/enable.ts
index e4ce9ce0..adafe180 100644
--- a/src/api/routes/users/@me/mfa/totp/enable.ts
+++ b/src/api/routes/users/@me/mfa/totp/enable.ts
@@ -1,19 +1,12 @@
 import { Router, Request, Response } from "express";
-import { User, generateToken, BackupCode, generateMfaBackupCodes } from "@fosscord/util";
+import { User, generateToken, generateMfaBackupCodes, TotpEnableSchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 import bcrypt from "bcrypt";
 import { HTTPError } from "lambert-server";
 import { verifyToken } from 'node-2fa';
-import crypto from "crypto";
 
 const router = Router();
 
-export interface TotpEnableSchema {
-	password: string;
-	code?: string;
-	secret?: string;
-}
-
 router.post("/", route({ body: "TotpEnableSchema" }), async (req: Request, res: Response) => {
 	const body = req.body as TotpEnableSchema;
 
diff --git a/src/api/routes/users/@me/relationships.ts b/src/api/routes/users/@me/relationships.ts
index 00d4da0b..cd33704d 100644
--- a/src/api/routes/users/@me/relationships.ts
+++ b/src/api/routes/users/@me/relationships.ts
@@ -37,10 +37,6 @@ router.get("/", route({}), async (req: Request, res: Response) => {
 	return res.json(related_users);
 });
 
-export interface RelationshipPutSchema {
-	type?: RelationshipType;
-}
-
 router.put("/:id", route({ body: "RelationshipPutSchema" }), async (req: Request, res: Response) => {
 	return await updateRelationship(
 		req,
@@ -50,11 +46,6 @@ router.put("/:id", route({ body: "RelationshipPutSchema" }), async (req: Request
 	);
 });
 
-export interface RelationshipPostSchema {
-	discriminator: string;
-	username: string;
-}
-
 router.post("/", route({ body: "RelationshipPostSchema" }), async (req: Request, res: Response) => {
 	return await updateRelationship(
 		req,
diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts
index 7e91fb7b..0d29c2e6 100644
--- a/src/api/util/handlers/Message.ts
+++ b/src/api/util/handlers/Message.ts
@@ -22,11 +22,11 @@ import {
 	Attachment,
 	Config,
 	Sticker,
+	MessageCreateSchema,
 } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import fetch from "node-fetch";
 import cheerio from "cheerio";
-import { MessageCreateSchema } from "../../routes/channels/#channel_id/messages";
 import { In } from "typeorm";
 const allow_empty = false;
 // TODO: check webhook, application, system author, stickers