Finish server routes.

This commit is contained in:
Paul
2021-07-11 18:45:09 +01:00
parent a0904b9909
commit a4cd54d579
12 changed files with 1514 additions and 6340 deletions
+960 -6301
View File
File diff suppressed because it is too large Load Diff
+17
View File
@@ -0,0 +1,17 @@
# Revolt API
### Tip
For faster compile times when working on API routes, comment out the categories you don't care about.
```ts
// src/routes/index.ts
export async function load() {
// await import('./core.js');
// await import('./users.js');
// await import('./channels.js');
await import('./servers.js');
}
await load();
```
+2 -2
View File
@@ -28,13 +28,13 @@ async function generate(): Promise<Document> {
],
components: {
securitySchemes: {
userId: {
'User ID': {
type: "apiKey",
in: "header",
name: "x-user-id",
description: "User ID is found when calling `/auth/login`.\n"
},
sessionToken: {
'Session Token': {
type: "apiKey",
in: "header",
name: "x-session-token",
+6 -4
View File
@@ -13,10 +13,12 @@ export default async function() {
let definitions: { [key: string]: TJS.Definition } = {};
for (let type of types) {
const defn = generator?.getSchemaForSymbol(type);
if (defn) {
definitions[type] = await convert(defn);
}
try {
const defn = generator.getSchemaForSymbol(type);
if (defn) {
definitions[type] = await convert(defn);
}
} catch (err) {}
}
return definitions;
+2 -2
View File
@@ -55,8 +55,8 @@ export function routeAuthenticated(summary: string, description: string, obj: Om
...route(summary, description, obj),
security: [
{
userId: [],
sessionToken: []
'User ID': [],
'Session Token': []
}
]
}
+9 -2
View File
@@ -34,14 +34,18 @@ resource('/channels/:channel', {
import type { Status } from './Users';
import type { AutumnId } from './_common';
interface ${'EditChannels'} {
interface ${'EditChannel'} {
/**
* Channel name
* @minLength 1
* @maxLength 32
**/
name: string;
/**
* Channel description
* @minLength 0
* @maxLength 1024
**/
description?: string;
@@ -59,7 +63,10 @@ resource('/channels/:channel', {
delete: routeAuthenticated(
"Close Channel",
"Deletes a server channel, leaves a group or closes a DM.",
await success("Deleted Channel")
{
...channelParams,
...await success("Deleted Channel")
}
)
});
//#endregion
+1
View File
@@ -2,6 +2,7 @@ export async function load() {
await import('./core.js');
await import('./users.js');
await import('./channels.js');
await import('./servers.js');
}
await load();
+407
View File
@@ -0,0 +1,407 @@
import { body, parameter, ref, success } from "../openapi/generators.js";
import { group, resource, route, routeAuthenticated, tag } from "../openapi/paths.js";
import { schema } from "../typescript.js";
group("Servers");
//#region Server Information
tag("Server Information", "Query and fetch servers on Revolt");
const serverParams = {
parameters: [
await parameter('server', 'Server ID', ref("Id"))
]
}
resource('/servers/:server', {
get: routeAuthenticated(
"Fetch Server",
"Retrieve a server.",
{
...serverParams,
...await success(
"Retrieved server.",
ref("Server")
)
}
),
patch: routeAuthenticated(
"Edit Server",
"Edit a server object.",
{
...serverParams,
...await body("Requested changes to server object.", schema`
import type { Category, SystemMessageChannels } from './Servers';
import type { AutumnId } from './_common';
interface ${'EditServer'} {
/**
* Server name
* @minLength 1
* @maxLength 32
**/
name: string;
/**
* Server description
* @minLength 0
* @maxLength 1024
**/
description?: string;
icon?: AutumnId;
banner?: AutumnId;
/**
* Server categories
*/
categories?: Category[];
/**
* System message channels
*/
system_messages?: SystemMessageChannels;
/**
* Field to remove from channel object
*/
remove?: 'Icon' | 'Banner' | 'Description';
}
`),
...await success("Succesfully changed channel object.")
}
),
delete: routeAuthenticated(
"Delete / Leave Server",
"Deletes a server if owner otherwise leaves.",
{
...serverParams,
...await success("Deleted Server")
}
)
});
resource('/servers/create', {
post: routeAuthenticated(
"Create Server",
"Create a new server.",
{
...await body("Server Data", schema`
import { Id, Nonce } from './_common';
interface ${'ServerData'} {
/**
* Group name
* @minLength 1
* @maxLength 32
*/
name: string;
/**
* Group description
* @minLength 0
* @maxLength 1024
*/
description?: string;
nonce: Nonce;
}
`),
...await success('Server', ref("Server"))
}
)
});
resource('/servers/:server/channels', {
post: routeAuthenticated(
"Create Channel",
"Create a new Text or Voice channel.",
{
...serverParams,
...await body("Channel Data", schema`
import { Id, Nonce } from './_common';
interface ${'ChannelData'} {
/**
* Channel type
*/
type: 'Text' | 'Voice';
/**
* Channel name
* @minLength 1
* @maxLength 32
*/
name: string;
/**
* Channel description
* @minLength 0
* @maxLength 1024
*/
description?: string;
nonce: Nonce;
}
`),
...success("Channel", ref("Channel"))
}
)
});
resource('/servers/:server/invites', {
get: routeAuthenticated(
"Fetch Invites",
"Fetch all server invites.",
{
...serverParams,
...success("Server Invites", schema`
import { Id } from './_common';
type ${'ServerInvites'} = {
/**
* Invite Code
*/
code: string;
/**
* ID of the user who created this invite.
*/
creator: Id;
/**
* ID of the channel this invite is for.
*/
channel: Id;
}
`)
}
)
});
//#endregion
//#region Server Members
tag("Server Members", "Find and edit server members");
const memberParams = {
parameters: [
await parameter('server', 'Server ID', ref("Id")),
await parameter('member', 'Member ID', ref("Id"))
]
}
resource('/servers/:server/members/:member', {
get: routeAuthenticated(
"Fetch Member",
"Retrieve a member.",
{
...memberParams,
...await success(
"Retrieved member.",
ref("Member")
)
}
),
patch: routeAuthenticated(
"Edit Member",
"Edit a member object.",
{
...serverParams,
...await body("Requested changes to server object.", schema`
import type { AutumnId, Id } from './_common';
interface ${'EditMember'} {
/**
* Member nickname
* @minLength 1
* @maxLength 32
**/
nickname: string;
avatar?: AutumnId;
/**
* Array of role IDs
*/
roles?: Id[];
/**
* Field to remove from channel object
*/
remove?: 'Nickname' | 'Avatar';
}
`),
...await success("Succesfully changed member object.")
}
),
delete: routeAuthenticated(
"Kick Member",
"Removes a member from the server.",
await success("Removed Member")
)
});
resource('/servers/:server/members', {
get: route(
"Fetch Members",
"Fetch all server members.",
{
...serverParams,
...await success(
"Server Members",
schema`
import { Member } from './Servers';
import { User } from './Users';
interface ${'ServerMembers'} {
members: Member[],
users: User[]
}
`
)
}
)
});
resource('/servers/:server/bans/:member', {
put: routeAuthenticated(
"Ban User",
"Ban a user by their ID.",
{
...memberParams,
...await body("Ban Data", schema`
interface ${'BanData'} {
/**
* Ban reason
* @minLength 1
* @maxLength 1024
*/
reason?: string
}
`),
...await success("Banned user.")
}
),
delete: routeAuthenticated(
"Unban User",
"Removes a user's ban.",
{
...memberParams,
...await success("Unbanned user.")
}
)
});
resource('/servers/:server/bans', {
get: routeAuthenticated(
"Fetch Bans",
"Fetch all bans on server.",
{
...serverParams,
...await success("Bans", schema`
import { Ban } from './Servers';
type ${'ServerBans'} = Ban[];
`)
}
)
});
//#endregion
//#region Server Permissions
tag("Server Permissions", "Manage permissions for servers");
const roleParams = {
parameters: [
await parameter('channel', 'Channel ID', ref("Id")),
await parameter('role', 'Role ID', ref("Id"))
]
}
const serverPermissions = await body("Server Permissions", schema`
interface ${'ServerPermissions'} {
/**
* Permission values
*/
permissions: {
/**
* Server permission
*/
server: number,
/**
* Channel permission
*/
channel: number
}
}
`)
resource('/servers/:server/permissions/:role', {
put: routeAuthenticated(
"Set Role Permission",
"Sets permissions for the specified role in this server.",
{
...roleParams,
...serverPermissions,
...await success("Successfully updated permissions.")
}
)
});
resource('/servers/:server/permissions/default', {
put: routeAuthenticated(
"Set Default Permission",
"Sets permissions for the default role in this server.",
{
...serverParams,
...serverPermissions,
...await success("Successfully updated permissions.")
}
)
});
resource('/servers/:server/roles', {
post: routeAuthenticated(
"Create Role",
"Creates a new server role.",
{
...serverParams,
...await body("Role Data", schema`
interface ${'RoleData'} {
/**
* Role name
* @minLength 1
* @maxLength 32
*/
name: string;
}
`),
...await success("New Role", schema`
import { Id } from './_common';
import { PermissionTuple } from './Servers';
interface ${'NewRole'} {
/**
* Role ID
*/
id: Id;
permissions: PermissionTuple;
}
`)
}
)
});
resource('/servers/:server/roles/:role', {
delete: routeAuthenticated(
"Delete Role",
"Deletes a server role by ID.",
{
...roleParams,
...await success("Successfully deleted role.")
}
)
});
//#endregion
+1 -1
View File
File diff suppressed because one or more lines are too long
+16
View File
@@ -3,9 +3,25 @@ import type { Id } from "./_common";
export type ServerInvite = {
type: 'Server'
/**
* Invite Code
*/
_id: Id
/**
* ID of the server this invite is for.
*/
server: Id
/**
* ID of the user who created this invite.
*/
creator: Id
/**
* ID of the channel this invite is for.
*/
channel: Id
}
+70 -25
View File
@@ -1,22 +1,24 @@
import type { Attachment } from './Autumn';
import type { Id } from './_common';
import type { Id, Nonce } from './_common';
export type MemberCompositeKey = {
server: Id,
server: Id
user: Id
}
export type Member = {
_id: MemberCompositeKey,
_id: MemberCompositeKey
nickname?: string,
avatar?: Attachment,
nickname?: string
avatar?: Attachment
roles?: Id[]
}
export type Ban = {
_id: MemberCompositeKey,
_id: MemberCompositeKey
reason?: string
}
@@ -29,46 +31,89 @@ export type PermissionTuple = [
]
export type Role = {
name: string,
permissions: PermissionTuple,
name: string
permissions: PermissionTuple
colour?: string
}
export type Category = {
id: Id,
title: string,
id: Id
title: string
channels: string[]
}
export type SystemMessageChannels = {
/** Channel ID where user join events should be sent */
user_joined?: Id,
user_joined?: Id
/** Channel ID where user leave events should be sent */
user_left?: Id,
user_left?: Id
/** Channel ID where user kick events should be sent */
user_kicked?: Id,
user_kicked?: Id
/** Channel ID where user ban events should be sent */
user_banned?: Id,
user_banned?: Id
}
export type Server = {
/**
* Server ID
*/
_id: Id,
nonce?: string,
owner: string,
_id: Id
name: string,
description?: string,
nonce?: Nonce
channels: string[],
categories?: Category[],
system_messages?: SystemMessageChannels,
/**
* User ID of server owner
*/
owner: Id
roles?: { [key: string]: Role },
default_permissions: PermissionTuple,
/**
* Server name
*/
name: string
icon?: Attachment,
/**
* Server description
*/
description?: string
/**
* Array of server channel IDs
*/
channels: Id[]
/**
* Array of server categories
*/
categories?: Category[]
/**
* System message channels
*
* Each type of system message will be sent into the respective channel ID.
*/
system_messages?: SystemMessageChannels
/**
* Server roles
*/
roles?: { [key: string]: Role }
/**
* Default permissions for all members
*/
default_permissions: PermissionTuple
/**
* Server icon
*/
icon?: Attachment
/**
* Server banner
*/
banner?: Attachment
}
+23 -3
View File
@@ -1,8 +1,28 @@
interface JoinData {
import type { Status } from './Users';
import type { AutumnId } from './_common';
interface EditUser {
status?: Status;
/**
* Voso Token
* User profile data
**/
profile?: {
/**
* Text to set as user profile description
* @maxLength 2000
*/
content?: string;
background?: AutumnId;
}
avatar?: AutumnId;
/**
* Field to remove from user object
*/
token: string;
remove?: 'ProfileContent' | 'ProfileBackground' | 'StatusText' | 'Avatar';
}