Move schemas to /src/util/schemas

This commit is contained in:
Madeline 2022-09-26 22:08:14 +10:00
parent 186f28516c
commit 849b257db7
94 changed files with 18692 additions and 18808 deletions

File diff suppressed because it is too large Load Diff

340
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -72,15 +72,16 @@
"sqlite3": "^5.1.1", "sqlite3": "^5.1.1",
"typeorm": "^0.3.10", "typeorm": "^0.3.10",
"typescript-json-schema": "^0.50.1", "typescript-json-schema": "^0.50.1",
"ws": "^8.9.0" "ws": "^8.9.0",
},
"optionalDependencies": {
"@aws-sdk/client-s3": "^3.178.0", "@aws-sdk/client-s3": "^3.178.0",
"@sentry/node": "^7.13.0", "@sentry/node": "^7.13.0",
"@sentry/tracing": "^7.13.0", "@sentry/tracing": "^7.13.0",
"@yukikaze-bot/erlpack": "^1.0.1",
"amqplib": "^0.10.3" "amqplib": "^0.10.3"
}, },
"optionalDependencies": {
"@yukikaze-bot/erlpack": "^1.0.1"
},
"_moduleAliases": { "_moduleAliases": {
"@fosscord/api": "dist/api", "@fosscord/api": "dist/api",
"@fosscord/cdn": "dist/cdn", "@fosscord/cdn": "dist/cdn",

View File

@ -3,7 +3,6 @@
const path = require("path"); const path = require("path");
const fs = require("fs"); const fs = require("fs");
const TJS = require("typescript-json-schema"); const TJS = require("typescript-json-schema");
require("missing-native-js-functions");
const schemaPath = path.join(__dirname, "..", "assets", "schemas.json"); const schemaPath = path.join(__dirname, "..", "assets", "schemas.json");
const settings = { const settings = {

View File

@ -1,21 +1,12 @@
import { Request, Response, Router } from "express"; import { Request, Response, Router } from "express";
import { route, getIpAdress, verifyCaptcha } from "@fosscord/api"; import { route, getIpAdress, verifyCaptcha } from "@fosscord/api";
import bcrypt from "bcrypt"; 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"; import crypto from "crypto";
const router: Router = Router(); const router: Router = Router();
export default 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) => { router.post("/", route({ body: "LoginSchema" }), async (req: Request, res: Response) => {
const { login, password, captcha_key, undelete } = req.body as LoginSchema; const { login, password, captcha_key, undelete } = req.body as LoginSchema;
const email = adjustEmail(login); const email = adjustEmail(login);

View File

@ -1,17 +1,10 @@
import { Router, Request, Response } from "express"; import { Router, Request, Response } from "express";
import { route } from "@fosscord/api"; 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 { verifyToken } from "node-2fa";
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
const router = Router(); 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) => { router.post("/", route({ body: "TotpSchema" }), async (req: Request, res: Response) => {
const { code, ticket, gift_code_sku_id, login_source } = req.body as TotpSchema; const { code, ticket, gift_code_sku_id, login_source } = req.body as TotpSchema;

View File

@ -1,40 +1,11 @@
import { Request, Response, Router } from "express"; 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 { route, getIpAdress, IPAnalysis, isProxy, verifyCaptcha } from "@fosscord/api";
import "missing-native-js-functions";
import bcrypt from "bcrypt"; import bcrypt from "bcrypt";
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
const router: Router = Router(); 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) => { router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Response) => {
const body = req.body as RegisterSchema; const body = req.body as RegisterSchema;
const { register, security } = Config.get(); const { register, security } = Config.get();

View File

@ -1,13 +1,9 @@
import { Router, Request, Response } from "express"; import { Router, Request, Response } from "express";
import { route } from "@fosscord/api"; import { route } from "@fosscord/api";
import { FieldErrors, User } from "@fosscord/util"; import { FieldErrors, User, BackupCodesChallengeSchema } from "@fosscord/util";
import bcrypt from "bcrypt"; import bcrypt from "bcrypt";
const router = Router(); const router = Router();
export interface BackupCodesChallengeSchema {
password: string;
}
router.post("/", route({ body: "BackupCodesChallengeSchema" }), async (req: Request, res: Response) => { router.post("/", route({ body: "BackupCodesChallengeSchema" }), async (req: Request, res: Response) => {
const { password } = req.body as BackupCodesChallengeSchema; const { password } = req.body as BackupCodesChallengeSchema;

View File

@ -1,12 +1,12 @@
import { import {
Channel, Channel,
ChannelDeleteEvent, ChannelDeleteEvent,
ChannelPermissionOverwriteType,
ChannelType, ChannelType,
ChannelUpdateEvent, ChannelUpdateEvent,
emitEvent, emitEvent,
Recipient, Recipient,
handleFile handleFile,
ChannelModifySchema
} from "@fosscord/util"; } from "@fosscord/util";
import { Request, Response, Router } from "express"; import { Request, Response, Router } from "express";
import { route } from "@fosscord/api"; import { route } from "@fosscord/api";
@ -47,35 +47,6 @@ router.delete("/", route({ permission: "MANAGE_CHANNELS" }), async (req: Request
res.send(channel); 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) => { router.patch("/", route({ body: "ChannelModifySchema", permission: "MANAGE_CHANNELS" }), async (req: Request, res: Response) => {
var payload = req.body as ChannelModifySchema; var payload = req.body as ChannelModifySchema;
const { channel_id } = req.params; const { channel_id } = req.params;

View File

@ -7,18 +7,6 @@ import { isTextChannel } from "./messages";
const router: Router = Router(); 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" }), router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INSTANT_INVITE", right: "CREATE_INVITES" }),
async (req: Request, res: Response) => { async (req: Request, res: Response) => {
const { user_id } = req; const { user_id } = req;

View File

@ -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 { Request, Response, Router } from "express";
import { route } from "@fosscord/api"; import { route } from "@fosscord/api";
@ -8,11 +8,6 @@ const router = Router();
// TODO: send read state event to all channel members // TODO: send read state event to all channel members
// TODO: advance-only notification cursor // TODO: advance-only notification cursor
export interface MessageAcknowledgeSchema {
manual?: boolean;
mention_count?: number;
}
router.post("/", route({ body: "MessageAcknowledgeSchema" }), async (req: Request, res: Response) => { router.post("/", route({ body: "MessageAcknowledgeSchema" }), async (req: Request, res: Response) => {
const { channel_id, message_id } = req.params; const { channel_id, message_id } = req.params;

View File

@ -1,8 +1,6 @@
import { import {
Attachment, Attachment,
Channel, Channel,
Embed,
DiscordApiErrors,
emitEvent, emitEvent,
FosscordApiErrors, FosscordApiErrors,
getPermission, getPermission,
@ -12,13 +10,13 @@ import {
MessageDeleteEvent, MessageDeleteEvent,
MessageUpdateEvent, MessageUpdateEvent,
Snowflake, Snowflake,
uploadFile uploadFile,
MessageCreateSchema,
} from "@fosscord/util"; } from "@fosscord/util";
import { Router, Response, Request } from "express"; import { Router, Response, Request } from "express";
import multer from "multer"; import multer from "multer";
import { route } from "@fosscord/api"; import { route } from "@fosscord/api";
import { handleMessage, postHandleMessage } from "@fosscord/api"; import { handleMessage, postHandleMessage } from "@fosscord/api";
import { MessageCreateSchema } from "../index";
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
const router = Router(); const router = Router();

View File

@ -2,16 +2,11 @@ import { Router, Response, Request } from "express";
import { Channel, Config, emitEvent, getPermission, getRights, MessageDeleteBulkEvent, Message } from "@fosscord/util"; import { Channel, Config, emitEvent, getPermission, getRights, MessageDeleteBulkEvent, Message } from "@fosscord/util";
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
import { route } from "@fosscord/api"; import { route } from "@fosscord/api";
import { In } from "typeorm";
const router: Router = Router(); const router: Router = Router();
export default router; export default router;
export interface BulkDeleteSchema {
messages: string[];
}
// should users be able to bulk delete messages or only bots? ANSWER: all users // 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 // 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 // https://discord.com/developers/docs/resources/channel#bulk-delete-messages

View File

@ -5,16 +5,15 @@ import {
ChannelType, ChannelType,
Config, Config,
DmChannelDTO, DmChannelDTO,
Embed,
emitEvent, emitEvent,
getPermission, getPermission,
getRights,
Message, Message,
MessageCreateEvent, MessageCreateEvent,
Snowflake, Snowflake,
uploadFile, uploadFile,
Member, Member,
Role, Role,
MessageCreateSchema,
} from "@fosscord/util"; } from "@fosscord/util";
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
import { handleMessage, postHandleMessage, route } from "@fosscord/api"; import { handleMessage, postHandleMessage, route } from "@fosscord/api";
@ -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 // https://discord.com/developers/docs/resources/channel#create-message
// get messages // get messages
router.get("/", async (req: Request, res: Response) => { router.get("/", async (req: Request, res: Response) => {

View File

@ -3,33 +3,21 @@ import { route } from "@fosscord/api";
import { isTextChannel } from "./messages"; import { isTextChannel } from "./messages";
import { FindManyOptions, Between, Not } from "typeorm"; import { FindManyOptions, Between, Not } from "typeorm";
import { import {
Attachment,
Channel, Channel,
Config, Config,
Embed,
DiscordApiErrors,
emitEvent, emitEvent,
FosscordApiErrors,
getPermission, getPermission,
getRights, getRights,
Message, Message,
MessageDeleteBulkEvent, MessageDeleteBulkEvent,
Snowflake, PurgeSchema,
uploadFile
} from "@fosscord/util"; } from "@fosscord/util";
import { Router, Response, Request } from "express"; import { Router, Response, Request } from "express";
import multer from "multer";
import { handleMessage, postHandleMessage } from "@fosscord/api";
const router: Router = Router(); const router: Router = Router();
export default router; export default router;
export interface PurgeSchema {
before: string;
after: string;
}
/** /**
TODO: apply the delete bit by bit to prevent client and database stress TODO: apply the delete bit by bit to prevent client and database stress
**/ **/

View File

@ -1,19 +1,12 @@
import { Router, Response, Request } from "express"; import { Router, Response, Request } from "express";
import { route } from "@fosscord/api"; 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 { HTTPError } from "lambert-server";
import { isTextChannel } from "./messages/index"; import { isTextChannel } from "./messages/index";
import { DiscordApiErrors } from "@fosscord/util"; import { DiscordApiErrors } from "@fosscord/util";
const router: Router = Router(); const router: Router = Router();
// TODO: webhooks
export interface WebhookCreateSchema {
/**
* @maxLength 80
*/
name: string;
avatar: string;
}
//TODO: implement webhooks //TODO: implement webhooks
router.get("/", route({}), async (req: Request, res: Response) => { router.get("/", route({}), async (req: Request, res: Response) => {
res.json([]); res.json([]);

View File

@ -1,8 +1,5 @@
import { Router, Response, Request } from "express"; 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 { route } from "@fosscord/api";
import { ChannelModifySchema } from "../../channels/#channel_id";
const router = Router(); const router = Router();
//TODO: implement audit logs //TODO: implement audit logs

View File

@ -1,30 +1,8 @@
import { Request, Response, Router } from "express"; 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 { HTTPError } from "lambert-server";
import { getIpAdress, route } from "@fosscord/api"; 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(); const router: Router = Router();
/* TODO: Deleting the secrets is just a temporary go-around. Views should be implemented for both safety and better handling. */ /* TODO: Deleting the secrets is just a temporary go-around. Views should be implemented for both safety and better handling. */

View File

@ -1,8 +1,7 @@
import { Router, Response, Request } from "express"; 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 { HTTPError } from "lambert-server";
import { route } from "@fosscord/api"; import { route } from "@fosscord/api";
import { ChannelModifySchema } from "../../channels/#channel_id";
const router = Router(); const router = Router();
router.get("/", route({}), async (req: Request, res: Response) => { router.get("/", route({}), async (req: Request, res: Response) => {

View File

@ -1,21 +1,9 @@
import { Router, Request, Response } from "express"; 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"; import { route } from "@fosscord/api";
const router = Router(); 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) => { router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id } = req.params; const { guild_id } = req.params;

View File

@ -1,9 +1,7 @@
import { Request, Response, Router } from "express"; 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 { HTTPError } from "lambert-server";
import { route } from "@fosscord/api"; import { route } from "@fosscord/api";
import "missing-native-js-functions";
import { GuildCreateSchema } from "../index";
const router = Router(); const router = Router();

View File

@ -1,8 +1,5 @@
import { Router, Response, Request } from "express"; 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 { route } from "@fosscord/api";
import { ChannelModifySchema } from "../../channels/#channel_id";
const router = Router(); const router = Router();
//TODO: implement integrations list //TODO: implement integrations list

View File

@ -1,15 +1,9 @@
import { Request, Response, Router } from "express"; import { Request, Response, Router } from "express";
import { Member, getPermission, getRights, Role, GuildMemberUpdateEvent, emitEvent, Sticker, Emoji, Rights, Guild } from "@fosscord/util"; import { Member, getPermission, getRights, Role, GuildMemberUpdateEvent, emitEvent, Sticker, Emoji, Guild, MemberChangeSchema } from "@fosscord/util";
import { HTTPError } from "lambert-server";
import { route } from "@fosscord/api"; import { route } from "@fosscord/api";
const router = Router(); const router = Router();
export interface MemberChangeSchema {
roles?: string[];
nick?: string;
}
router.get("/", route({}), async (req: Request, res: Response) => { router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id, member_id } = req.params; const { guild_id, member_id } = req.params;
await Member.IsInGuildOrFail(req.user_id, guild_id); await Member.IsInGuildOrFail(req.user_id, guild_id);

View File

@ -4,10 +4,6 @@ import { Request, Response, Router } from "express";
const router = Router(); const router = Router();
export interface MemberNickChangeSchema {
nick: string;
}
router.patch("/", route({ body: "MemberNickChangeSchema" }), async (req: Request, res: Response) => { router.patch("/", route({ body: "MemberNickChangeSchema" }), async (req: Request, res: Response) => {
var { guild_id, member_id } = req.params; var { guild_id, member_id } = req.params;
var permissionString: PermissionResolvable = "MANAGE_NICKNAMES"; var permissionString: PermissionResolvable = "MANAGE_NICKNAMES";

View File

@ -62,13 +62,6 @@ router.get("/", route({}), async (req: Request, res: Response) => {
res.send({ pruned: members.length }); 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) => { router.post("/", route({ permission: "KICK_MEMBERS", right: "KICK_BAN_MEMBERS" }), async (req: Request, res: Response) => {
const days = parseInt(req.body.days); const days = parseInt(req.body.days);

View File

@ -1,8 +1,7 @@
import { Router, Request, Response } from "express"; 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 { route } from "@fosscord/api";
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
import { RoleModifySchema } from "../";
const router = Router(); const router = Router();

View File

@ -5,28 +5,15 @@ import {
Member, Member,
GuildRoleCreateEvent, GuildRoleCreateEvent,
GuildRoleUpdateEvent, GuildRoleUpdateEvent,
GuildRoleDeleteEvent,
emitEvent, emitEvent,
Config, Config,
DiscordApiErrors, DiscordApiErrors,
handleFile RoleModifySchema,
} from "@fosscord/util"; } from "@fosscord/util";
import { HTTPError } from "lambert-server";
import { route } from "@fosscord/api"; import { route } from "@fosscord/api";
const router: Router = Router(); 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 = { export type RolePositionUpdateSchema = {
id: string; id: string;
position: number; position: number;

View File

@ -1,13 +1,13 @@
import { import {
emitEvent, emitEvent,
GuildStickersUpdateEvent, GuildStickersUpdateEvent,
handleFile,
Member, Member,
Snowflake, Snowflake,
Sticker, Sticker,
StickerFormatType, StickerFormatType,
StickerType, StickerType,
uploadFile uploadFile,
ModifyGuildStickerSchema,
} from "@fosscord/util"; } from "@fosscord/util";
import { Router, Request, Response } from "express"; import { Router, Request, Response } from "express";
import { route } from "@fosscord/api"; 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 } })); 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( router.patch(
"/:sticker_id", "/:sticker_id",
route({ body: "ModifyGuildStickerSchema", permission: "MANAGE_EMOJIS_AND_STICKERS" }), route({ body: "ModifyGuildStickerSchema", permission: "MANAGE_EMOJIS_AND_STICKERS" }),

View File

@ -23,16 +23,6 @@ const TemplateGuildProjection: (keyof Guild)[] = [
"icon" "icon"
]; ];
export interface TemplateCreateSchema {
name: string;
description?: string;
}
export interface TemplateModifySchema {
name: string;
description?: string;
}
router.get("/", route({}), async (req: Request, res: Response) => { router.get("/", route({}), async (req: Request, res: Response) => {
const { guild_id } = req.params; const { guild_id } = req.params;

View File

@ -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 { Router, Request, Response } from "express";
import { route } from "@fosscord/api"; import { route } from "@fosscord/api";
import { HTTPError } from "lambert-server"; 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) => { router.patch("/", route({ body: "VanityUrlSchema", permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => {
const { guild_id } = req.params; const { guild_id } = req.params;
const body = req.body as VanityUrlSchema; const body = req.body as VanityUrlSchema;

View File

@ -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 { route } from "@fosscord/api";
import { Request, Response, Router } from "express"; import { Request, Response, Router } from "express";
const router = Router(); const router = Router();
//TODO need more testing when community guild and voice stage channel are working //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) => { router.patch("/", route({ body: "VoiceStateUpdateSchema" }), async (req: Request, res: Response) => {
const body = req.body as VoiceStateUpdateSchema; const body = req.body as VoiceStateUpdateSchema;
var { guild_id, user_id } = req.params; var { guild_id, user_id } = req.params;

View File

@ -1,8 +1,5 @@
import { Router, Response, Request } from "express"; 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 { route } from "@fosscord/api";
import { ChannelModifySchema } from "../../channels/#channel_id";
const router = Router(); const router = Router();
//TODO: implement webhooks //TODO: implement webhooks

View File

@ -1,21 +1,10 @@
import { Request, Response, Router } from "express"; 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 { HTTPError } from "lambert-server";
import { route } from "@fosscord/api"; import { route } from "@fosscord/api";
const router: Router = Router(); 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) => { router.get("/", route({}), async (req: Request, res: Response) => {
const guild_id = req.params.guild_id; const guild_id = req.params.guild_id;

View File

@ -1,12 +1,7 @@
import { Request, Response, Router } from "express"; import { Request, Response, Router } from "express";
import { Guild } from "@fosscord/util"; import { Guild, WidgetModifySchema } from "@fosscord/util";
import { route } from "@fosscord/api"; 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(); const router: Router = Router();
// https://discord.com/developers/docs/resources/guild#get-guild-widget-settings // https://discord.com/developers/docs/resources/guild#get-guild-widget-settings

View File

@ -1,23 +1,9 @@
import { Router, Request, Response } from "express"; 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 { route } from "@fosscord/api";
import { ChannelModifySchema } from "../channels/#channel_id";
const router: Router = Router(); 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 //TODO: create default channel
router.post("/", route({ body: "GuildCreateSchema", right: "CREATE_GUILDS" }), async (req: Request, res: Response) => { router.post("/", route({ body: "GuildCreateSchema", right: "CREATE_GUILDS" }), async (req: Request, res: Response) => {

View File

@ -1,15 +1,10 @@
import { Request, Response, Router } from "express"; 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 { route } from "@fosscord/api";
import { DiscordApiErrors } from "@fosscord/util"; import { DiscordApiErrors } from "@fosscord/util";
import fetch from "node-fetch"; import fetch from "node-fetch";
const router: Router = Router(); const router: Router = Router();
export interface GuildTemplateCreateSchema {
name: string;
avatar?: string | null;
}
router.get("/:code", route({}), async (req: Request, res: Response) => { router.get("/:code", route({}), async (req: Request, res: Response) => {
const { allowDiscordTemplates, allowRaws, enabled } = Config.get().templates; const { allowDiscordTemplates, allowRaws, enabled } = Config.get().templates;
if (!enabled) res.json({ code: 403, message: "Template creation & usage is disabled on this instance." }).sendStatus(403); if (!enabled) res.json({ code: 403, message: "Template creation & usage is disabled on this instance." }).sendStatus(403);

View File

@ -1,5 +1,5 @@
import { Request, Response, Router } from "express"; 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"; import { route } from "@fosscord/api";
const router: Router = Router(); 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])))); 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) => { router.post("/", route({ body: "DmChannelCreateSchema" }), async (req: Request, res: Response) => {
const body = req.body as DmChannelCreateSchema; const body = req.body as DmChannelCreateSchema;
res.json(await Channel.createDMChannel(body.recipients, req.user_id, body.name)); res.json(await Channel.createDMChannel(body.recipients, req.user_id, body.name));

View File

@ -1,31 +1,11 @@
import { Router, Request, Response } from "express"; 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 { route } from "@fosscord/api";
import bcrypt from "bcrypt"; import bcrypt from "bcrypt";
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
const router: Router = Router(); 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) => { router.get("/", route({}), async (req: Request, res: Response) => {
res.json(await User.findOne({ select: PrivateUserProjection, where: { id: req.user_id } })); res.json(await User.findOne({ select: PrivateUserProjection, where: { id: req.user_id } }));
}); });

View File

@ -1,15 +1,9 @@
import { Router, Request, Response } from "express"; import { Router, Request, Response } from "express";
import { route } from "@fosscord/api"; import { route } from "@fosscord/api";
import { BackupCode, generateMfaBackupCodes, User } from "@fosscord/util"; import { BackupCode, generateMfaBackupCodes, User, CodesVerificationSchema } from "@fosscord/util";
const router = Router(); const router = Router();
export interface CodesVerificationSchema {
key: string;
nonce: string;
regenerate?: boolean;
}
router.post("/", route({ body: "CodesVerificationSchema" }), async (req: Request, res: Response) => { router.post("/", route({ body: "CodesVerificationSchema" }), async (req: Request, res: Response) => {
const { key, nonce, regenerate } = req.body as CodesVerificationSchema; const { key, nonce, regenerate } = req.body as CodesVerificationSchema;

View File

@ -1,15 +1,10 @@
import { Router, Request, Response } from "express"; import { Router, Request, Response } from "express";
import { route } from "@fosscord/api"; 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"; import bcrypt from "bcrypt";
const router = Router(); const router = Router();
export interface MfaCodesSchema {
password: string;
regenerate?: boolean;
}
// TODO: This route is replaced with users/@me/mfa/codes-verification in newer clients // TODO: This route is replaced with users/@me/mfa/codes-verification in newer clients
router.post("/", route({ body: "MfaCodesSchema" }), async (req: Request, res: Response) => { router.post("/", route({ body: "MfaCodesSchema" }), async (req: Request, res: Response) => {

View File

@ -2,14 +2,10 @@ import { Router, Request, Response } from "express";
import { route } from "@fosscord/api"; import { route } from "@fosscord/api";
import { verifyToken } from 'node-2fa'; import { verifyToken } from 'node-2fa';
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
import { User, generateToken, BackupCode } from "@fosscord/util"; import { User, generateToken, BackupCode, TotpDisableSchema } from "@fosscord/util";
const router = Router(); const router = Router();
export interface TotpDisableSchema {
code: string;
}
router.post("/", route({ body: "TotpDisableSchema" }), async (req: Request, res: Response) => { router.post("/", route({ body: "TotpDisableSchema" }), async (req: Request, res: Response) => {
const body = req.body as TotpDisableSchema; const body = req.body as TotpDisableSchema;

View File

@ -1,19 +1,12 @@
import { Router, Request, Response } from "express"; 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 { route } from "@fosscord/api";
import bcrypt from "bcrypt"; import bcrypt from "bcrypt";
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
import { verifyToken } from 'node-2fa'; import { verifyToken } from 'node-2fa';
import crypto from "crypto";
const router = Router(); const router = Router();
export interface TotpEnableSchema {
password: string;
code?: string;
secret?: string;
}
router.post("/", route({ body: "TotpEnableSchema" }), async (req: Request, res: Response) => { router.post("/", route({ body: "TotpEnableSchema" }), async (req: Request, res: Response) => {
const body = req.body as TotpEnableSchema; const body = req.body as TotpEnableSchema;

View File

@ -37,10 +37,6 @@ router.get("/", route({}), async (req: Request, res: Response) => {
return res.json(related_users); return res.json(related_users);
}); });
export interface RelationshipPutSchema {
type?: RelationshipType;
}
router.put("/:id", route({ body: "RelationshipPutSchema" }), async (req: Request, res: Response) => { router.put("/:id", route({ body: "RelationshipPutSchema" }), async (req: Request, res: Response) => {
return await updateRelationship( return await updateRelationship(
req, 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) => { router.post("/", route({ body: "RelationshipPostSchema" }), async (req: Request, res: Response) => {
return await updateRelationship( return await updateRelationship(
req, req,

View File

@ -22,11 +22,11 @@ import {
Attachment, Attachment,
Config, Config,
Sticker, Sticker,
MessageCreateSchema,
} from "@fosscord/util"; } from "@fosscord/util";
import { HTTPError } from "lambert-server"; import { HTTPError } from "lambert-server";
import fetch from "node-fetch"; import fetch from "node-fetch";
import cheerio from "cheerio"; import cheerio from "cheerio";
import { MessageCreateSchema } from "../../routes/channels/#channel_id/messages";
import { In } from "typeorm"; import { In } from "typeorm";
const allow_empty = false; const allow_empty = false;
// TODO: check webhook, application, system author, stickers // TODO: check webhook, application, system author, stickers

View File

@ -36,7 +36,7 @@ export async function Message(this: WebSocket, buffer: WS.Data) {
data = bigIntJson.parse(buffer as string); data = bigIntJson.parse(buffer as string);
} }
else if (typeof buffer == "string") { else if (typeof buffer == "string") {
data = bigIntJson.parse(buffer as string) data = bigIntJson.parse(buffer as string);
} }
else return; else return;
@ -51,14 +51,14 @@ export async function Message(this: WebSocket, buffer: WS.Data) {
return; return;
} }
// const transaction = Sentry.startTransaction({ const transaction = Sentry.startTransaction({
// op: OPCODES[data.op], op: OPCODES[data.op],
// name: `GATEWAY ${OPCODES[data.op]}`, name: `GATEWAY ${OPCODES[data.op]}`,
// data: { data: {
// ...data.d, ...data.d,
// token: data?.d?.token ? "[Redacted]" : undefined, token: data?.d?.token ? "[Redacted]" : undefined,
// }, },
// }); });
try { try {
var ret = await OPCodeHandler.call(this, data); var ret = await OPCodeHandler.call(this, data);
@ -66,7 +66,7 @@ export async function Message(this: WebSocket, buffer: WS.Data) {
return ret; return ret;
} catch (error) { } catch (error) {
Sentry.captureException(error); Sentry.captureException(error);
// transaction.finish(); transaction.finish();
console.error(`Error: Op ${data.op}`, error); console.error(`Error: Op ${data.op}`, error);
// if (!this.CLOSED && this.CLOSING) // if (!this.CLOSED && this.CLOSING)
return this.close(CLOSECODES.Unknown_error); return this.close(CLOSECODES.Unknown_error);

View File

@ -20,12 +20,12 @@ import {
PresenceUpdateEvent, PresenceUpdateEvent,
DefaultUserGuildSettings, DefaultUserGuildSettings,
UserGuildSettings, UserGuildSettings,
IdentifySchema,
} from "@fosscord/util"; } from "@fosscord/util";
import { Send } from "../util/Send"; import { Send } from "../util/Send";
import { CLOSECODES, OPCODES } from "../util/Constants"; import { CLOSECODES, OPCODES } from "../util/Constants";
import { genSessionId } from "../util/SessionUtils"; import { genSessionId } from "../util/SessionUtils";
import { setupListener } from "../listener/listener"; import { setupListener } from "../listener/listener";
import { IdentifySchema } from "../schema/Identify";
// import experiments from "./experiments.json"; // import experiments from "./experiments.json";
const experiments: any = []; const experiments: any = [];
import { check } from "./instanceOf"; import { check } from "./instanceOf";

View File

@ -1,6 +1,5 @@
import { getDatabase, getPermission, listenEvent, Member, Role, Session } from "@fosscord/util"; import { getDatabase, getPermission, listenEvent, Member, Role, Session, LazyRequestSchema } from "@fosscord/util";
import { WebSocket, Payload, handlePresenceUpdate, OPCODES, Send } from "@fosscord/gateway"; import { WebSocket, Payload, handlePresenceUpdate, OPCODES, Send } from "@fosscord/gateway";
import { LazyRequest } from "../schema/LazyRequest";
import { check } from "./instanceOf"; import { check } from "./instanceOf";
// TODO: only show roles/members that have access to this channel // TODO: only show roles/members that have access to this channel
@ -137,8 +136,8 @@ async function getMembers(guild_id: string, range: [number, number]) {
export async function onLazyRequest(this: WebSocket, { d }: Payload) { export async function onLazyRequest(this: WebSocket, { d }: Payload) {
// TODO: check data // TODO: check data
check.call(this, LazyRequest, d); check.call(this, LazyRequestSchema, d);
const { guild_id, typing, channels, activities } = d as LazyRequest; const { guild_id, typing, channels, activities } = d as LazyRequestSchema;
const channel_id = Object.keys(channels || {}).first(); const channel_id = Object.keys(channels || {}).first();
if (!channel_id) return; if (!channel_id) return;

View File

@ -1,6 +1,5 @@
import { WebSocket, Payload } from "@fosscord/gateway"; import { WebSocket, Payload } from "@fosscord/gateway";
import { emitEvent, PresenceUpdateEvent, Session, User } from "@fosscord/util"; import { emitEvent, PresenceUpdateEvent, Session, User, ActivitySchema } from "@fosscord/util";
import { ActivitySchema } from "../schema/Activity";
import { check } from "./instanceOf"; import { check } from "./instanceOf";
export async function onPresenceUpdate(this: WebSocket, { d }: Payload) { export async function onPresenceUpdate(this: WebSocket, { d }: Payload) {

View File

@ -1,4 +1,3 @@
import { VoiceStateUpdateSchema } from "../schema/VoiceStateUpdateSchema";
import { Payload, WebSocket } from "@fosscord/gateway"; import { Payload, WebSocket } from "@fosscord/gateway";
import { genVoiceToken } from "../util/SessionUtils"; import { genVoiceToken } from "../util/SessionUtils";
import { check } from "./instanceOf"; import { check } from "./instanceOf";
@ -11,6 +10,7 @@ import {
VoiceServerUpdateEvent, VoiceServerUpdateEvent,
VoiceState, VoiceState,
VoiceStateUpdateEvent, VoiceStateUpdateEvent,
VoiceStateUpdateSchema,
} from "@fosscord/util"; } from "@fosscord/util";
// TODO: check if a voice server is setup // TODO: check if a voice server is setup
// Notice: Bot users respect the voice channel's user limit, if set. When the voice channel is full, you will not receive the Voice State Update or Voice Server Update events in response to your own Voice State Update. Having MANAGE_CHANNELS permission bypasses this limit and allows you to join regardless of the channel being full or not. // Notice: Bot users respect the voice channel's user limit, if set. When the voice channel is full, you will not receive the Voice State Update or Voice Server Update events in response to your own Voice State Update. Having MANAGE_CHANNELS permission bypasses this limit and allows you to join regardless of the channel being full or not.

View File

@ -0,0 +1,3 @@
export interface BackupCodesChallengeSchema {
password: string;
}

View File

@ -0,0 +1,4 @@
export interface BanCreateSchema {
delete_message_days?: string;
reason?: string;
};

View File

@ -0,0 +1,7 @@
export interface BanModeratorSchema {
id: string;
user_id: string;
guild_id: string;
executor_id: string;
reason?: string | undefined;
};

View File

@ -0,0 +1,8 @@
export interface BanRegistrySchema {
id: string;
user_id: string;
guild_id: string;
executor_id: string;
ip?: string;
reason?: string | undefined;
};

View File

@ -0,0 +1,3 @@
export interface BulkDeleteSchema {
messages: string[];
}

View File

@ -0,0 +1,30 @@
import { ChannelPermissionOverwriteType, ChannelType } from "@fosscord/util";
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;
}

View File

@ -0,0 +1,5 @@
export interface CodesVerificationSchema {
key: string;
nonce: string;
regenerate?: boolean;
}

View File

@ -0,0 +1,4 @@
export interface DmChannelCreateSchema {
name?: string;
recipients: string[];
}

View File

@ -0,0 +1,6 @@
export interface EmojiCreateSchema {
name?: string;
image: string;
require_colons?: boolean | null;
roles?: string[];
}

View File

@ -0,0 +1,4 @@
export interface EmojiModifySchema {
name?: string;
roles?: string[];
}

View File

@ -0,0 +1,14 @@
import { ChannelModifySchema } from ".";
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;
}

View File

@ -0,0 +1,4 @@
export interface GuildTemplateCreateSchema {
name: string;
avatar?: string | null;
}

View File

@ -0,0 +1,10 @@
export interface GuildUpdateWelcomeScreenSchema {
welcome_channels?: {
channel_id: string;
description: string;
emoji_id?: string;
emoji_name?: string;
}[];
enabled?: boolean;
description?: string;
}

View File

@ -1,4 +1,4 @@
import { ActivitySchema } from "./Activity"; import { ActivitySchema } from "@fosscord/util";
export const IdentifySchema = { export const IdentifySchema = {
token: String, token: String,

View File

@ -0,0 +1,11 @@
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;
}

View File

@ -1,4 +1,4 @@
export interface LazyRequest { export interface LazyRequestSchema {
guild_id: string; guild_id: string;
channels?: Record<string, [number, number][]>; channels?: Record<string, [number, number][]>;
activities?: boolean; activities?: boolean;
@ -8,7 +8,7 @@ export interface LazyRequest {
thread_member_lists?: any[]; thread_member_lists?: any[];
} }
export const LazyRequest = { export const LazyRequestSchema = {
guild_id: String, guild_id: String,
$activities: Boolean, $activities: Boolean,
$channels: Object, $channels: Object,

View File

@ -0,0 +1,8 @@
export interface LoginSchema {
login: string;
password: string;
undelete?: boolean;
captcha_key?: string;
login_source?: string;
gift_code_sku_id?: string;
}

View File

@ -0,0 +1,4 @@
export interface MemberChangeSchema {
roles?: string[];
nick?: string;
}

View File

@ -0,0 +1,3 @@
export interface MemberNickChangeSchema {
nick: string;
}

View File

@ -0,0 +1,4 @@
export interface MessageAcknowledgeSchema {
manual?: boolean;
mention_count?: number;
}

View File

@ -0,0 +1,33 @@
import { Embed } from "@fosscord/util";
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[];
}

View File

@ -0,0 +1,4 @@
export interface MfaCodesSchema {
password: string;
regenerate?: boolean;
}

View File

@ -0,0 +1,15 @@
export interface ModifyGuildStickerSchema {
/**
* @minLength 2
* @maxLength 30
*/
name: string;
/**
* @maxLength 100
*/
description?: string;
/**
* @maxLength 200
*/
tags: string;
}

View File

@ -0,0 +1,6 @@
export interface PruneSchema {
/**
* @min 0
*/
days: number;
}

View File

@ -0,0 +1,4 @@
export interface PurgeSchema {
before: string;
after: string;
}

View File

@ -0,0 +1,27 @@
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;
}

View File

@ -0,0 +1,4 @@
export interface RelationshipPostSchema {
discriminator: string;
username: string;
}

View File

@ -0,0 +1,5 @@
import { RelationshipType } from "@fosscord/util";
export interface RelationshipPutSchema {
type?: RelationshipType;
}

View File

@ -0,0 +1,10 @@
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;
}

View File

@ -0,0 +1,19 @@
export interface SelectProtocolSchema {
protocol: "webrtc" | "udp";
data:
| string
| {
address: string;
port: number;
mode: string;
};
sdp?: string;
codecs?: {
name: "opus" | "VP8" | "VP9" | "H264";
type: "audio" | "video";
priority: number;
payload_type: number;
rtx_payload_type?: number | null;
}[];
rtc_connection_id?: string; // uuid
}

View File

@ -0,0 +1,4 @@
export interface TemplateCreateSchema {
name: string;
description?: string;
}

View File

@ -0,0 +1,4 @@
export interface TemplateModifySchema {
name: string;
description?: string;
}

View File

@ -0,0 +1,3 @@
export interface TotpDisableSchema {
code: string;
}

View File

@ -0,0 +1,5 @@
export interface TotpEnableSchema {
password: string;
code?: string;
secret?: string;
}

View File

@ -0,0 +1,6 @@
export interface TotpSchema {
code: string,
ticket: string,
gift_code_sku_id?: string | null,
login_source?: string | null,
}

View File

@ -0,0 +1,19 @@
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;
}

View File

@ -0,0 +1,7 @@
export interface VanityUrlSchema {
/**
* @minLength 1
* @maxLength 20
*/
code?: string;
}

View File

@ -0,0 +1,12 @@
export interface VoiceIdentifySchema {
server_id: string;
user_id: string;
session_id: string;
token: string;
video?: boolean;
streams?: {
type: string;
rid: string;
quality: number;
}[];
}

View File

@ -1,12 +1,4 @@
export const VoiceStateUpdateSchema = { //TODO need more testing when community guild and voice stage channel are working
$guild_id: String,
$channel_id: String,
self_mute: Boolean,
self_deaf: Boolean,
$self_video: Boolean, //required in docs but bots don't always send it
$preferred_region: String,
};
export interface VoiceStateUpdateSchema { export interface VoiceStateUpdateSchema {
guild_id?: string; guild_id?: string;
channel_id?: string; channel_id?: string;
@ -14,4 +6,17 @@ export interface VoiceStateUpdateSchema {
self_deaf: boolean; self_deaf: boolean;
self_video?: boolean; self_video?: boolean;
preferred_region?: string; preferred_region?: string;
request_to_speak_timestamp?: Date;
suppress?: boolean;
} }
export const VoiceStateUpdateSchema = {
$guild_id: String,
$channel_id: String,
self_mute: Boolean,
self_deaf: Boolean,
$self_video: Boolean, //required in docs but bots don't always send it
$preferred_region: String,
$request_to_speak_timestamp: Date,
$suppress: Boolean,
};

View File

@ -0,0 +1,17 @@
export interface VoiceVideoSchema {
audio_ssrc: number;
video_ssrc: number;
rtx_ssrc?: number;
user_id?: string;
streams?: {
type: "video" | "audio";
rid: string;
ssrc: number;
active: boolean;
quality: number;
rtx_ssrc: number;
max_bitrate: number;
max_framerate: number;
max_resolution: { type: string; width: number; height: number; };
}[];
}

View File

@ -0,0 +1,8 @@
// TODO: webhooks
export interface WebhookCreateSchema {
/**
* @maxLength 80
*/
name: string;
avatar: string;
}

View File

@ -0,0 +1,4 @@
export interface WidgetModifySchema {
enabled: boolean; // whether the widget is enabled
channel_id: string; // the widget channel id
}

View File

@ -1,2 +1,41 @@
export * from "./Validator"; export * from "./Validator";
export * from "./voice"; export * from "./SelectProtocolSchema";
export * from "./LoginSchema";
export * from "./RegisterSchema";
export * from "./TotpSchema";
export * from "./BackupCodesChallengeSchema";
export * from "./ChannelModifySchema";
export * from "./InviteCreateSchema";
export * from "./PurgeSchema";
export * from "./WebhookCreateSchema";
export * from "./MessageCreateSchema";
export * from "./MessageAcknowledgeSchema";
export * from "./GuildCreateSchema";
export * from "./BanCreateSchema";
export * from "./BanModeratorSchema";
export * from "./BanRegistrySchema";
export * from "./EmojiCreateSchema";
export * from "./EmojiModifySchema";
export * from "./ModifyGuildStickerSchema";
export * from "./TemplateCreateSchema";
export * from "./TemplateModifySchema";
export * from "./VanityUrlSchema";
export * from "./GuildUpdateWelcomeScreenSchema";
export * from "./WidgetModifySchema";
export * from "./MemberChangeSchema";
export * from "./RoleModifySchema";
export * from "./GuildTemplateCreateSchema";
export * from "./DmChannelCreateSchema";
export * from "./UserModifySchema";
export * from "./RelationshipPostSchema";
export * from "./RelationshipPutSchema";
export * from "./CodesVerificationSchema";
export * from "./MfaCodesSchema";
export * from "./TotpDisableSchema";
export * from "./TotpEnableSchema";
export * from "./VoiceIdentifySchema";
export * from "./VoiceStateUpdateSchema";
export * from "./VoiceVideoSchema";
export * from "./IdentifySchema";
export * from "./ActivitySchema";
export * from "./LazyRequestSchema";

View File

@ -1,69 +0,0 @@
export interface VoiceVideoSchema {
audio_ssrc: number;
video_ssrc: number;
rtx_ssrc?: number;
user_id?: string;
streams?: {
type: "video" | "audio";
rid: string;
ssrc: number;
active: boolean;
quality: number;
rtx_ssrc: number;
max_bitrate: number;
max_framerate: number;
max_resolution: { type: string; width: number; height: number; };
}[];
}
export const VoiceStateUpdateSchema = {
$guild_id: String,
$channel_id: String,
self_mute: Boolean,
self_deaf: Boolean,
self_video: Boolean
};
//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;
}
export interface VoiceIdentifySchema {
server_id: string;
user_id: string;
session_id: string;
token: string;
video?: boolean;
streams?: {
type: string;
rid: string;
quality: number;
}[];
}
export interface SelectProtocolSchema {
protocol: "webrtc" | "udp";
data:
| string
| {
address: string;
port: number;
mode: string;
};
sdp?: string;
codecs?: {
name: "opus" | "VP8" | "VP9" | "H264";
type: "audio" | "video";
priority: number;
payload_type: number;
rtx_payload_type?: number | null;
}[];
rtc_connection_id?: string; // uuid
}