summary refs log tree commit diff
diff options
context:
space:
mode:
authorMadeline <46743919+MaddyUnderStars@users.noreply.github.com>2022-12-18 23:45:29 +1100
committerMadeline <46743919+MaddyUnderStars@users.noreply.github.com>2022-12-18 23:45:29 +1100
commit970e67fe6505015dc55f41e365e1ad2d2876d215 (patch)
tree3a2104d77e9786feaa8518ee0a096fcff7bde3b2
parentWhoops (diff)
downloadserver-970e67fe6505015dc55f41e365e1ad2d2876d215.tar.xz
Refactor applications
-rw-r--r--assets/client_test/developers.html2
-rw-r--r--assets/schemas.json1569
-rw-r--r--src/api/routes/applications/#id/bot/index.ts113
-rw-r--r--src/api/routes/applications/#id/index.ts51
-rw-r--r--src/api/routes/applications/index.ts24
-rw-r--r--src/util/entities/Application.ts1
-rw-r--r--src/util/schemas/ApplicationCreateSchema.ts4
-rw-r--r--src/util/schemas/ApplicationModifySchema.ts14
-rw-r--r--src/util/schemas/BotModifySchema.ts4
-rw-r--r--src/util/schemas/Validator.ts1
-rw-r--r--src/util/schemas/index.ts5
11 files changed, 1702 insertions, 86 deletions
diff --git a/assets/client_test/developers.html b/assets/client_test/developers.html
index fbe0193c..47fb0f4b 100644
--- a/assets/client_test/developers.html
+++ b/assets/client_test/developers.html
@@ -18,7 +18,7 @@
 			API_VERSION: 9,
 			API_ENDPOINT: "/api",
 			WEBAPP_ENDPOINT: "",
-			CDN_HOST: `${location.hostname}:3003`,
+			CDN_HOST: `${location.host}`, // TODO: make this file auto populate from config?
 
 			BRAINTREE_KEY: "production_5st77rrc_49pp2rp4phym7387",
 			STRIPE_KEY: "pk_live_CUQtlpQUF0vufWpnpUmQvcdi",
diff --git a/assets/schemas.json b/assets/schemas.json
index 368d22fc..1fe87326 100644
--- a/assets/schemas.json
+++ b/assets/schemas.json
@@ -21631,6 +21631,1575 @@
         },
         "$schema": "http://json-schema.org/draft-07/schema#"
     },
+    "BotModifySchema": {
+        "type": "object",
+        "properties": {
+            "avatar": {
+                "type": "string"
+            },
+            "username": {
+                "type": "string"
+            }
+        },
+        "additionalProperties": false,
+        "definitions": {
+            "ChannelPermissionOverwriteType": {
+                "enum": [
+                    0,
+                    1,
+                    2
+                ],
+                "type": "number"
+            },
+            "Embed": {
+                "type": "object",
+                "properties": {
+                    "title": {
+                        "type": "string"
+                    },
+                    "type": {
+                        "enum": [
+                            "article",
+                            "gifv",
+                            "image",
+                            "link",
+                            "rich",
+                            "video"
+                        ],
+                        "type": "string"
+                    },
+                    "description": {
+                        "type": "string"
+                    },
+                    "url": {
+                        "type": "string"
+                    },
+                    "timestamp": {
+                        "type": "string",
+                        "format": "date-time"
+                    },
+                    "color": {
+                        "type": "integer"
+                    },
+                    "footer": {
+                        "type": "object",
+                        "properties": {
+                            "text": {
+                                "type": "string"
+                            },
+                            "icon_url": {
+                                "type": "string"
+                            },
+                            "proxy_icon_url": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false,
+                        "required": [
+                            "text"
+                        ]
+                    },
+                    "image": {
+                        "$ref": "#/definitions/EmbedImage"
+                    },
+                    "thumbnail": {
+                        "$ref": "#/definitions/EmbedImage"
+                    },
+                    "video": {
+                        "$ref": "#/definitions/EmbedImage"
+                    },
+                    "provider": {
+                        "type": "object",
+                        "properties": {
+                            "name": {
+                                "type": "string"
+                            },
+                            "url": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "author": {
+                        "type": "object",
+                        "properties": {
+                            "name": {
+                                "type": "string"
+                            },
+                            "url": {
+                                "type": "string"
+                            },
+                            "icon_url": {
+                                "type": "string"
+                            },
+                            "proxy_icon_url": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "fields": {
+                        "type": "array",
+                        "items": {
+                            "type": "object",
+                            "properties": {
+                                "name": {
+                                    "type": "string"
+                                },
+                                "value": {
+                                    "type": "string"
+                                },
+                                "inline": {
+                                    "type": "boolean"
+                                }
+                            },
+                            "additionalProperties": false,
+                            "required": [
+                                "name",
+                                "value"
+                            ]
+                        }
+                    }
+                },
+                "additionalProperties": false
+            },
+            "EmbedImage": {
+                "type": "object",
+                "properties": {
+                    "url": {
+                        "type": "string"
+                    },
+                    "proxy_url": {
+                        "type": "string"
+                    },
+                    "height": {
+                        "type": "integer"
+                    },
+                    "width": {
+                        "type": "integer"
+                    }
+                },
+                "additionalProperties": false
+            },
+            "ChannelModifySchema": {
+                "type": "object",
+                "properties": {
+                    "name": {
+                        "maxLength": 100,
+                        "type": "string"
+                    },
+                    "type": {
+                        "enum": [
+                            0,
+                            1,
+                            10,
+                            11,
+                            12,
+                            13,
+                            14,
+                            15,
+                            2,
+                            255,
+                            3,
+                            33,
+                            34,
+                            35,
+                            4,
+                            5,
+                            6,
+                            64,
+                            7,
+                            8,
+                            9
+                        ],
+                        "type": "number"
+                    },
+                    "topic": {
+                        "type": "string"
+                    },
+                    "icon": {
+                        "type": [
+                            "null",
+                            "string"
+                        ]
+                    },
+                    "bitrate": {
+                        "type": "integer"
+                    },
+                    "user_limit": {
+                        "type": "integer"
+                    },
+                    "rate_limit_per_user": {
+                        "type": "integer"
+                    },
+                    "position": {
+                        "type": "integer"
+                    },
+                    "permission_overwrites": {
+                        "type": "array",
+                        "items": {
+                            "type": "object",
+                            "properties": {
+                                "id": {
+                                    "type": "string"
+                                },
+                                "type": {
+                                    "$ref": "#/definitions/ChannelPermissionOverwriteType"
+                                },
+                                "allow": {
+                                    "type": "string"
+                                },
+                                "deny": {
+                                    "type": "string"
+                                }
+                            },
+                            "additionalProperties": false,
+                            "required": [
+                                "allow",
+                                "deny",
+                                "id",
+                                "type"
+                            ]
+                        }
+                    },
+                    "parent_id": {
+                        "type": "string"
+                    },
+                    "id": {
+                        "type": "string"
+                    },
+                    "nsfw": {
+                        "type": "boolean"
+                    },
+                    "rtc_region": {
+                        "type": "string"
+                    },
+                    "default_auto_archive_duration": {
+                        "type": "integer"
+                    },
+                    "default_reaction_emoji": {
+                        "type": [
+                            "null",
+                            "string"
+                        ]
+                    },
+                    "flags": {
+                        "type": "integer"
+                    },
+                    "default_thread_rate_limit_per_user": {
+                        "type": "integer"
+                    },
+                    "video_quality_mode": {
+                        "type": "integer"
+                    }
+                },
+                "additionalProperties": false
+            },
+            "ActivitySchema": {
+                "type": "object",
+                "properties": {
+                    "afk": {
+                        "type": "boolean"
+                    },
+                    "status": {
+                        "$ref": "#/definitions/Status"
+                    },
+                    "activities": {
+                        "type": "array",
+                        "items": {
+                            "$ref": "#/definitions/Activity"
+                        }
+                    },
+                    "since": {
+                        "type": "integer"
+                    }
+                },
+                "additionalProperties": false,
+                "required": [
+                    "status"
+                ]
+            },
+            "Status": {
+                "enum": [
+                    "dnd",
+                    "idle",
+                    "invisible",
+                    "offline",
+                    "online"
+                ],
+                "type": "string"
+            },
+            "Activity": {
+                "type": "object",
+                "properties": {
+                    "name": {
+                        "type": "string"
+                    },
+                    "type": {
+                        "$ref": "#/definitions/ActivityType"
+                    },
+                    "url": {
+                        "type": "string"
+                    },
+                    "created_at": {
+                        "type": "integer"
+                    },
+                    "timestamps": {
+                        "type": "object",
+                        "properties": {
+                            "start": {
+                                "type": "integer"
+                            },
+                            "end": {
+                                "type": "integer"
+                            }
+                        },
+                        "additionalProperties": false,
+                        "required": [
+                            "end",
+                            "start"
+                        ]
+                    },
+                    "application_id": {
+                        "type": "string"
+                    },
+                    "details": {
+                        "type": "string"
+                    },
+                    "state": {
+                        "type": "string"
+                    },
+                    "emoji": {
+                        "type": "object",
+                        "properties": {
+                            "name": {
+                                "type": "string"
+                            },
+                            "id": {
+                                "type": "string"
+                            },
+                            "animated": {
+                                "type": "boolean"
+                            }
+                        },
+                        "additionalProperties": false,
+                        "required": [
+                            "animated",
+                            "name"
+                        ]
+                    },
+                    "party": {
+                        "type": "object",
+                        "properties": {
+                            "id": {
+                                "type": "string"
+                            },
+                            "size": {
+                                "type": "array",
+                                "items": [
+                                    {
+                                        "type": "integer"
+                                    }
+                                ],
+                                "minItems": 1,
+                                "maxItems": 1
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "assets": {
+                        "type": "object",
+                        "properties": {
+                            "large_image": {
+                                "type": "string"
+                            },
+                            "large_text": {
+                                "type": "string"
+                            },
+                            "small_image": {
+                                "type": "string"
+                            },
+                            "small_text": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "secrets": {
+                        "type": "object",
+                        "properties": {
+                            "join": {
+                                "type": "string"
+                            },
+                            "spectate": {
+                                "type": "string"
+                            },
+                            "match": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "instance": {
+                        "type": "boolean"
+                    },
+                    "flags": {
+                        "type": "string"
+                    },
+                    "id": {
+                        "type": "string"
+                    },
+                    "sync_id": {
+                        "type": "string"
+                    },
+                    "metadata": {
+                        "type": "object",
+                        "properties": {
+                            "context_uri": {
+                                "type": "string"
+                            },
+                            "album_id": {
+                                "type": "string"
+                            },
+                            "artist_ids": {
+                                "type": "array",
+                                "items": {
+                                    "type": "string"
+                                }
+                            }
+                        },
+                        "additionalProperties": false,
+                        "required": [
+                            "album_id",
+                            "artist_ids"
+                        ]
+                    },
+                    "session_id": {
+                        "type": "string"
+                    }
+                },
+                "additionalProperties": false,
+                "required": [
+                    "flags",
+                    "name",
+                    "session_id",
+                    "type"
+                ]
+            },
+            "ActivityType": {
+                "enum": [
+                    0,
+                    1,
+                    2,
+                    4,
+                    5
+                ],
+                "type": "number"
+            },
+            "Record<string,[number,number][]>": {
+                "type": "object",
+                "additionalProperties": false
+            },
+            "Partial<ChannelOverride>": {
+                "type": "object",
+                "properties": {
+                    "message_notifications": {
+                        "type": "integer"
+                    },
+                    "mute_config": {
+                        "$ref": "#/definitions/MuteConfig"
+                    },
+                    "muted": {
+                        "type": "boolean"
+                    },
+                    "channel_id": {
+                        "type": [
+                            "null",
+                            "string"
+                        ]
+                    }
+                },
+                "additionalProperties": false
+            },
+            "MuteConfig": {
+                "type": "object",
+                "properties": {
+                    "end_time": {
+                        "type": "integer"
+                    },
+                    "selected_time_window": {
+                        "type": "integer"
+                    }
+                },
+                "additionalProperties": false,
+                "required": [
+                    "end_time",
+                    "selected_time_window"
+                ]
+            }
+        },
+        "$schema": "http://json-schema.org/draft-07/schema#"
+    },
+    "ApplicationModifySchema": {
+        "type": "object",
+        "properties": {
+            "description": {
+                "type": "string"
+            },
+            "icon": {
+                "type": "string"
+            },
+            "interactions_endpoint_url": {
+                "type": "string"
+            },
+            "max_participants": {
+                "type": [
+                    "null",
+                    "integer"
+                ]
+            },
+            "name": {
+                "type": "string"
+            },
+            "privacy_policy_url": {
+                "type": "string"
+            },
+            "role_connections_verification_url": {
+                "type": "string"
+            },
+            "tags": {
+                "type": "array",
+                "items": {
+                    "type": "string"
+                }
+            },
+            "terms_of_service_url": {
+                "type": "string"
+            },
+            "bot_public": {
+                "type": "boolean"
+            },
+            "bot_require_code_grant": {
+                "type": "boolean"
+            },
+            "flags": {
+                "type": "integer"
+            }
+        },
+        "additionalProperties": false,
+        "definitions": {
+            "ChannelPermissionOverwriteType": {
+                "enum": [
+                    0,
+                    1,
+                    2
+                ],
+                "type": "number"
+            },
+            "Embed": {
+                "type": "object",
+                "properties": {
+                    "title": {
+                        "type": "string"
+                    },
+                    "type": {
+                        "enum": [
+                            "article",
+                            "gifv",
+                            "image",
+                            "link",
+                            "rich",
+                            "video"
+                        ],
+                        "type": "string"
+                    },
+                    "description": {
+                        "type": "string"
+                    },
+                    "url": {
+                        "type": "string"
+                    },
+                    "timestamp": {
+                        "type": "string",
+                        "format": "date-time"
+                    },
+                    "color": {
+                        "type": "integer"
+                    },
+                    "footer": {
+                        "type": "object",
+                        "properties": {
+                            "text": {
+                                "type": "string"
+                            },
+                            "icon_url": {
+                                "type": "string"
+                            },
+                            "proxy_icon_url": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false,
+                        "required": [
+                            "text"
+                        ]
+                    },
+                    "image": {
+                        "$ref": "#/definitions/EmbedImage"
+                    },
+                    "thumbnail": {
+                        "$ref": "#/definitions/EmbedImage"
+                    },
+                    "video": {
+                        "$ref": "#/definitions/EmbedImage"
+                    },
+                    "provider": {
+                        "type": "object",
+                        "properties": {
+                            "name": {
+                                "type": "string"
+                            },
+                            "url": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "author": {
+                        "type": "object",
+                        "properties": {
+                            "name": {
+                                "type": "string"
+                            },
+                            "url": {
+                                "type": "string"
+                            },
+                            "icon_url": {
+                                "type": "string"
+                            },
+                            "proxy_icon_url": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "fields": {
+                        "type": "array",
+                        "items": {
+                            "type": "object",
+                            "properties": {
+                                "name": {
+                                    "type": "string"
+                                },
+                                "value": {
+                                    "type": "string"
+                                },
+                                "inline": {
+                                    "type": "boolean"
+                                }
+                            },
+                            "additionalProperties": false,
+                            "required": [
+                                "name",
+                                "value"
+                            ]
+                        }
+                    }
+                },
+                "additionalProperties": false
+            },
+            "EmbedImage": {
+                "type": "object",
+                "properties": {
+                    "url": {
+                        "type": "string"
+                    },
+                    "proxy_url": {
+                        "type": "string"
+                    },
+                    "height": {
+                        "type": "integer"
+                    },
+                    "width": {
+                        "type": "integer"
+                    }
+                },
+                "additionalProperties": false
+            },
+            "ChannelModifySchema": {
+                "type": "object",
+                "properties": {
+                    "name": {
+                        "maxLength": 100,
+                        "type": "string"
+                    },
+                    "type": {
+                        "enum": [
+                            0,
+                            1,
+                            10,
+                            11,
+                            12,
+                            13,
+                            14,
+                            15,
+                            2,
+                            255,
+                            3,
+                            33,
+                            34,
+                            35,
+                            4,
+                            5,
+                            6,
+                            64,
+                            7,
+                            8,
+                            9
+                        ],
+                        "type": "number"
+                    },
+                    "topic": {
+                        "type": "string"
+                    },
+                    "icon": {
+                        "type": [
+                            "null",
+                            "string"
+                        ]
+                    },
+                    "bitrate": {
+                        "type": "integer"
+                    },
+                    "user_limit": {
+                        "type": "integer"
+                    },
+                    "rate_limit_per_user": {
+                        "type": "integer"
+                    },
+                    "position": {
+                        "type": "integer"
+                    },
+                    "permission_overwrites": {
+                        "type": "array",
+                        "items": {
+                            "type": "object",
+                            "properties": {
+                                "id": {
+                                    "type": "string"
+                                },
+                                "type": {
+                                    "$ref": "#/definitions/ChannelPermissionOverwriteType"
+                                },
+                                "allow": {
+                                    "type": "string"
+                                },
+                                "deny": {
+                                    "type": "string"
+                                }
+                            },
+                            "additionalProperties": false,
+                            "required": [
+                                "allow",
+                                "deny",
+                                "id",
+                                "type"
+                            ]
+                        }
+                    },
+                    "parent_id": {
+                        "type": "string"
+                    },
+                    "id": {
+                        "type": "string"
+                    },
+                    "nsfw": {
+                        "type": "boolean"
+                    },
+                    "rtc_region": {
+                        "type": "string"
+                    },
+                    "default_auto_archive_duration": {
+                        "type": "integer"
+                    },
+                    "default_reaction_emoji": {
+                        "type": [
+                            "null",
+                            "string"
+                        ]
+                    },
+                    "flags": {
+                        "type": "integer"
+                    },
+                    "default_thread_rate_limit_per_user": {
+                        "type": "integer"
+                    },
+                    "video_quality_mode": {
+                        "type": "integer"
+                    }
+                },
+                "additionalProperties": false
+            },
+            "ActivitySchema": {
+                "type": "object",
+                "properties": {
+                    "afk": {
+                        "type": "boolean"
+                    },
+                    "status": {
+                        "$ref": "#/definitions/Status"
+                    },
+                    "activities": {
+                        "type": "array",
+                        "items": {
+                            "$ref": "#/definitions/Activity"
+                        }
+                    },
+                    "since": {
+                        "type": "integer"
+                    }
+                },
+                "additionalProperties": false,
+                "required": [
+                    "status"
+                ]
+            },
+            "Status": {
+                "enum": [
+                    "dnd",
+                    "idle",
+                    "invisible",
+                    "offline",
+                    "online"
+                ],
+                "type": "string"
+            },
+            "Activity": {
+                "type": "object",
+                "properties": {
+                    "name": {
+                        "type": "string"
+                    },
+                    "type": {
+                        "$ref": "#/definitions/ActivityType"
+                    },
+                    "url": {
+                        "type": "string"
+                    },
+                    "created_at": {
+                        "type": "integer"
+                    },
+                    "timestamps": {
+                        "type": "object",
+                        "properties": {
+                            "start": {
+                                "type": "integer"
+                            },
+                            "end": {
+                                "type": "integer"
+                            }
+                        },
+                        "additionalProperties": false,
+                        "required": [
+                            "end",
+                            "start"
+                        ]
+                    },
+                    "application_id": {
+                        "type": "string"
+                    },
+                    "details": {
+                        "type": "string"
+                    },
+                    "state": {
+                        "type": "string"
+                    },
+                    "emoji": {
+                        "type": "object",
+                        "properties": {
+                            "name": {
+                                "type": "string"
+                            },
+                            "id": {
+                                "type": "string"
+                            },
+                            "animated": {
+                                "type": "boolean"
+                            }
+                        },
+                        "additionalProperties": false,
+                        "required": [
+                            "animated",
+                            "name"
+                        ]
+                    },
+                    "party": {
+                        "type": "object",
+                        "properties": {
+                            "id": {
+                                "type": "string"
+                            },
+                            "size": {
+                                "type": "array",
+                                "items": [
+                                    {
+                                        "type": "integer"
+                                    }
+                                ],
+                                "minItems": 1,
+                                "maxItems": 1
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "assets": {
+                        "type": "object",
+                        "properties": {
+                            "large_image": {
+                                "type": "string"
+                            },
+                            "large_text": {
+                                "type": "string"
+                            },
+                            "small_image": {
+                                "type": "string"
+                            },
+                            "small_text": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "secrets": {
+                        "type": "object",
+                        "properties": {
+                            "join": {
+                                "type": "string"
+                            },
+                            "spectate": {
+                                "type": "string"
+                            },
+                            "match": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "instance": {
+                        "type": "boolean"
+                    },
+                    "flags": {
+                        "type": "string"
+                    },
+                    "id": {
+                        "type": "string"
+                    },
+                    "sync_id": {
+                        "type": "string"
+                    },
+                    "metadata": {
+                        "type": "object",
+                        "properties": {
+                            "context_uri": {
+                                "type": "string"
+                            },
+                            "album_id": {
+                                "type": "string"
+                            },
+                            "artist_ids": {
+                                "type": "array",
+                                "items": {
+                                    "type": "string"
+                                }
+                            }
+                        },
+                        "additionalProperties": false,
+                        "required": [
+                            "album_id",
+                            "artist_ids"
+                        ]
+                    },
+                    "session_id": {
+                        "type": "string"
+                    }
+                },
+                "additionalProperties": false,
+                "required": [
+                    "flags",
+                    "name",
+                    "session_id",
+                    "type"
+                ]
+            },
+            "ActivityType": {
+                "enum": [
+                    0,
+                    1,
+                    2,
+                    4,
+                    5
+                ],
+                "type": "number"
+            },
+            "Record<string,[number,number][]>": {
+                "type": "object",
+                "additionalProperties": false
+            },
+            "Partial<ChannelOverride>": {
+                "type": "object",
+                "properties": {
+                    "message_notifications": {
+                        "type": "integer"
+                    },
+                    "mute_config": {
+                        "$ref": "#/definitions/MuteConfig"
+                    },
+                    "muted": {
+                        "type": "boolean"
+                    },
+                    "channel_id": {
+                        "type": [
+                            "null",
+                            "string"
+                        ]
+                    }
+                },
+                "additionalProperties": false
+            },
+            "MuteConfig": {
+                "type": "object",
+                "properties": {
+                    "end_time": {
+                        "type": "integer"
+                    },
+                    "selected_time_window": {
+                        "type": "integer"
+                    }
+                },
+                "additionalProperties": false,
+                "required": [
+                    "end_time",
+                    "selected_time_window"
+                ]
+            }
+        },
+        "$schema": "http://json-schema.org/draft-07/schema#"
+    },
+    "ApplicationCreateSchema": {
+        "type": "object",
+        "properties": {
+            "name": {
+                "type": "string"
+            },
+            "team_id": {
+                "type": [
+                    "string",
+                    "integer"
+                ]
+            }
+        },
+        "additionalProperties": false,
+        "required": [
+            "name"
+        ],
+        "definitions": {
+            "ChannelPermissionOverwriteType": {
+                "enum": [
+                    0,
+                    1,
+                    2
+                ],
+                "type": "number"
+            },
+            "Embed": {
+                "type": "object",
+                "properties": {
+                    "title": {
+                        "type": "string"
+                    },
+                    "type": {
+                        "enum": [
+                            "article",
+                            "gifv",
+                            "image",
+                            "link",
+                            "rich",
+                            "video"
+                        ],
+                        "type": "string"
+                    },
+                    "description": {
+                        "type": "string"
+                    },
+                    "url": {
+                        "type": "string"
+                    },
+                    "timestamp": {
+                        "type": "string",
+                        "format": "date-time"
+                    },
+                    "color": {
+                        "type": "integer"
+                    },
+                    "footer": {
+                        "type": "object",
+                        "properties": {
+                            "text": {
+                                "type": "string"
+                            },
+                            "icon_url": {
+                                "type": "string"
+                            },
+                            "proxy_icon_url": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false,
+                        "required": [
+                            "text"
+                        ]
+                    },
+                    "image": {
+                        "$ref": "#/definitions/EmbedImage"
+                    },
+                    "thumbnail": {
+                        "$ref": "#/definitions/EmbedImage"
+                    },
+                    "video": {
+                        "$ref": "#/definitions/EmbedImage"
+                    },
+                    "provider": {
+                        "type": "object",
+                        "properties": {
+                            "name": {
+                                "type": "string"
+                            },
+                            "url": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "author": {
+                        "type": "object",
+                        "properties": {
+                            "name": {
+                                "type": "string"
+                            },
+                            "url": {
+                                "type": "string"
+                            },
+                            "icon_url": {
+                                "type": "string"
+                            },
+                            "proxy_icon_url": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "fields": {
+                        "type": "array",
+                        "items": {
+                            "type": "object",
+                            "properties": {
+                                "name": {
+                                    "type": "string"
+                                },
+                                "value": {
+                                    "type": "string"
+                                },
+                                "inline": {
+                                    "type": "boolean"
+                                }
+                            },
+                            "additionalProperties": false,
+                            "required": [
+                                "name",
+                                "value"
+                            ]
+                        }
+                    }
+                },
+                "additionalProperties": false
+            },
+            "EmbedImage": {
+                "type": "object",
+                "properties": {
+                    "url": {
+                        "type": "string"
+                    },
+                    "proxy_url": {
+                        "type": "string"
+                    },
+                    "height": {
+                        "type": "integer"
+                    },
+                    "width": {
+                        "type": "integer"
+                    }
+                },
+                "additionalProperties": false
+            },
+            "ChannelModifySchema": {
+                "type": "object",
+                "properties": {
+                    "name": {
+                        "maxLength": 100,
+                        "type": "string"
+                    },
+                    "type": {
+                        "enum": [
+                            0,
+                            1,
+                            10,
+                            11,
+                            12,
+                            13,
+                            14,
+                            15,
+                            2,
+                            255,
+                            3,
+                            33,
+                            34,
+                            35,
+                            4,
+                            5,
+                            6,
+                            64,
+                            7,
+                            8,
+                            9
+                        ],
+                        "type": "number"
+                    },
+                    "topic": {
+                        "type": "string"
+                    },
+                    "icon": {
+                        "type": [
+                            "null",
+                            "string"
+                        ]
+                    },
+                    "bitrate": {
+                        "type": "integer"
+                    },
+                    "user_limit": {
+                        "type": "integer"
+                    },
+                    "rate_limit_per_user": {
+                        "type": "integer"
+                    },
+                    "position": {
+                        "type": "integer"
+                    },
+                    "permission_overwrites": {
+                        "type": "array",
+                        "items": {
+                            "type": "object",
+                            "properties": {
+                                "id": {
+                                    "type": "string"
+                                },
+                                "type": {
+                                    "$ref": "#/definitions/ChannelPermissionOverwriteType"
+                                },
+                                "allow": {
+                                    "type": "string"
+                                },
+                                "deny": {
+                                    "type": "string"
+                                }
+                            },
+                            "additionalProperties": false,
+                            "required": [
+                                "allow",
+                                "deny",
+                                "id",
+                                "type"
+                            ]
+                        }
+                    },
+                    "parent_id": {
+                        "type": "string"
+                    },
+                    "id": {
+                        "type": "string"
+                    },
+                    "nsfw": {
+                        "type": "boolean"
+                    },
+                    "rtc_region": {
+                        "type": "string"
+                    },
+                    "default_auto_archive_duration": {
+                        "type": "integer"
+                    },
+                    "default_reaction_emoji": {
+                        "type": [
+                            "null",
+                            "string"
+                        ]
+                    },
+                    "flags": {
+                        "type": "integer"
+                    },
+                    "default_thread_rate_limit_per_user": {
+                        "type": "integer"
+                    },
+                    "video_quality_mode": {
+                        "type": "integer"
+                    }
+                },
+                "additionalProperties": false
+            },
+            "ActivitySchema": {
+                "type": "object",
+                "properties": {
+                    "afk": {
+                        "type": "boolean"
+                    },
+                    "status": {
+                        "$ref": "#/definitions/Status"
+                    },
+                    "activities": {
+                        "type": "array",
+                        "items": {
+                            "$ref": "#/definitions/Activity"
+                        }
+                    },
+                    "since": {
+                        "type": "integer"
+                    }
+                },
+                "additionalProperties": false,
+                "required": [
+                    "status"
+                ]
+            },
+            "Status": {
+                "enum": [
+                    "dnd",
+                    "idle",
+                    "invisible",
+                    "offline",
+                    "online"
+                ],
+                "type": "string"
+            },
+            "Activity": {
+                "type": "object",
+                "properties": {
+                    "name": {
+                        "type": "string"
+                    },
+                    "type": {
+                        "$ref": "#/definitions/ActivityType"
+                    },
+                    "url": {
+                        "type": "string"
+                    },
+                    "created_at": {
+                        "type": "integer"
+                    },
+                    "timestamps": {
+                        "type": "object",
+                        "properties": {
+                            "start": {
+                                "type": "integer"
+                            },
+                            "end": {
+                                "type": "integer"
+                            }
+                        },
+                        "additionalProperties": false,
+                        "required": [
+                            "end",
+                            "start"
+                        ]
+                    },
+                    "application_id": {
+                        "type": "string"
+                    },
+                    "details": {
+                        "type": "string"
+                    },
+                    "state": {
+                        "type": "string"
+                    },
+                    "emoji": {
+                        "type": "object",
+                        "properties": {
+                            "name": {
+                                "type": "string"
+                            },
+                            "id": {
+                                "type": "string"
+                            },
+                            "animated": {
+                                "type": "boolean"
+                            }
+                        },
+                        "additionalProperties": false,
+                        "required": [
+                            "animated",
+                            "name"
+                        ]
+                    },
+                    "party": {
+                        "type": "object",
+                        "properties": {
+                            "id": {
+                                "type": "string"
+                            },
+                            "size": {
+                                "type": "array",
+                                "items": [
+                                    {
+                                        "type": "integer"
+                                    }
+                                ],
+                                "minItems": 1,
+                                "maxItems": 1
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "assets": {
+                        "type": "object",
+                        "properties": {
+                            "large_image": {
+                                "type": "string"
+                            },
+                            "large_text": {
+                                "type": "string"
+                            },
+                            "small_image": {
+                                "type": "string"
+                            },
+                            "small_text": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "secrets": {
+                        "type": "object",
+                        "properties": {
+                            "join": {
+                                "type": "string"
+                            },
+                            "spectate": {
+                                "type": "string"
+                            },
+                            "match": {
+                                "type": "string"
+                            }
+                        },
+                        "additionalProperties": false
+                    },
+                    "instance": {
+                        "type": "boolean"
+                    },
+                    "flags": {
+                        "type": "string"
+                    },
+                    "id": {
+                        "type": "string"
+                    },
+                    "sync_id": {
+                        "type": "string"
+                    },
+                    "metadata": {
+                        "type": "object",
+                        "properties": {
+                            "context_uri": {
+                                "type": "string"
+                            },
+                            "album_id": {
+                                "type": "string"
+                            },
+                            "artist_ids": {
+                                "type": "array",
+                                "items": {
+                                    "type": "string"
+                                }
+                            }
+                        },
+                        "additionalProperties": false,
+                        "required": [
+                            "album_id",
+                            "artist_ids"
+                        ]
+                    },
+                    "session_id": {
+                        "type": "string"
+                    }
+                },
+                "additionalProperties": false,
+                "required": [
+                    "flags",
+                    "name",
+                    "session_id",
+                    "type"
+                ]
+            },
+            "ActivityType": {
+                "enum": [
+                    0,
+                    1,
+                    2,
+                    4,
+                    5
+                ],
+                "type": "number"
+            },
+            "Record<string,[number,number][]>": {
+                "type": "object",
+                "additionalProperties": false
+            },
+            "Partial<ChannelOverride>": {
+                "type": "object",
+                "properties": {
+                    "message_notifications": {
+                        "type": "integer"
+                    },
+                    "mute_config": {
+                        "$ref": "#/definitions/MuteConfig"
+                    },
+                    "muted": {
+                        "type": "boolean"
+                    },
+                    "channel_id": {
+                        "type": [
+                            "null",
+                            "string"
+                        ]
+                    }
+                },
+                "additionalProperties": false
+            },
+            "MuteConfig": {
+                "type": "object",
+                "properties": {
+                    "end_time": {
+                        "type": "integer"
+                    },
+                    "selected_time_window": {
+                        "type": "integer"
+                    }
+                },
+                "additionalProperties": false,
+                "required": [
+                    "end_time",
+                    "selected_time_window"
+                ]
+            }
+        },
+        "$schema": "http://json-schema.org/draft-07/schema#"
+    },
     "ActivitySchema": {
         "$ref": "#/definitions/ActivitySchema",
         "definitions": {
diff --git a/src/api/routes/applications/#id/bot/index.ts b/src/api/routes/applications/#id/bot/index.ts
index ad2399b8..ed5d6a70 100644
--- a/src/api/routes/applications/#id/bot/index.ts
+++ b/src/api/routes/applications/#id/bot/index.ts
@@ -1,81 +1,78 @@
 import { Request, Response, Router } from "express";
 import { route } from "@fosscord/api";
-import { Application, Config, FieldErrors, generateToken, OrmUtils, Snowflake, trimSpecial, User } from "@fosscord/util";
+import { Application, generateToken, User, BotModifySchema, handleFile, DiscordApiErrors } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { verifyToken } from "node-2fa";
 
 const router: Router = Router();
 
 router.post("/", route({}), async (req: Request, res: Response) => {
-	const app = await Application.findOne({where: {id: req.params.id}});
-	if(!app) return res.status(404);
-	const username = trimSpecial(app.name);
-	const discriminator = await User.generateDiscriminator(username);
-	if (!discriminator) {
-		// We've failed to generate a valid and unused discriminator
-		throw FieldErrors({
-			username: {
-				code: "USERNAME_TOO_MANY_USERS",
-				message: req?.t("auth:register.USERNAME_TOO_MANY_USERS"),
-			},
-		});
-	}
-
-	const user = OrmUtils.mergeDeep(new User(), {
-		created_at: new Date(),
-		username: username,
-		discriminator,
-		id: app.id,
-		bot: true,
-		system: false,
-		premium_since: new Date(),
-		desktop: false,
-		mobile: false,
-		premium: true,
-		premium_type: 2,
-		bio: app.description,
-		mfa_enabled: false,
-		totp_secret: "",
-		totp_backup_codes: [],
-		verified: true,
-		disabled: false,
-		deleted: false,
-		email: null,
-		rights: Config.get().security.defaultRights,
-		nsfw_allowed: true,
-		public_flags: "0",
-		flags: "0",
-		data: {
-			hash: null,
-			valid_tokens_since: new Date(),
-		},
-		settings: {},
-		extended_settings: {},
-		fingerprints: [],
-		notes: {},
+	const app = await Application.findOneOrFail({ where: { id: req.params.id }, relations: ["owner"] });
+
+	if (app.owner.id != req.user_id)
+		throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
+
+	const user = await User.register({
+		username: app.name,
+		password: undefined,
+		req,
 	});
+
+	user.id = app.id;
+	user.premium_since = new Date();
+	user.bot = true;
+
 	await user.save();
-	app.bot = user;
+
+	// flags is NaN here?
+	app.assign({ bot: user, flags: app.flags || 0 });
+
 	await app.save();
-	res.send().status(204)
+
+	res.send().status(204);
 });
 
 router.post("/reset", route({}), async (req: Request, res: Response) => {
-	let bot = await User.findOne({where: {id: req.params.id}});
-	let owner = await User.findOne({where: {id: req.user_id}});
-	if(!bot) return res.status(404);
-	if(owner?.totp_secret && (!req.body.code || verifyToken(owner.totp_secret, req.body.code))) {
+	let bot = await User.findOneOrFail({ where: { id: req.params.id } });
+	let owner = await User.findOneOrFail({ where: { id: req.user_id } });
+
+	if (owner.id != req.user_id)
+		throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
+
+	if (owner.totp_secret && (!req.body.code || verifyToken(owner.totp_secret, req.body.code)))
 		throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
-	}
+
 	bot.data = { hash: undefined, valid_tokens_since: new Date() };
+
 	await bot.save();
+
 	let token = await generateToken(bot.id);
-	res.json({token}).status(200);
+
+	res.json({ token }).status(200);
 });
 
-router.patch("/", route({}), async (req: Request, res: Response) => {
-	delete req.body.avatar;
-	let app = OrmUtils.mergeDeep(await User.findOne({where: {id: req.params.id}}), req.body);
+router.patch("/", route({ body: "BotModifySchema" }), async (req: Request, res: Response) => {
+	const body = req.body as BotModifySchema;
+	if (!body.avatar?.trim()) delete body.avatar;
+
+	const app = await Application.findOneOrFail({ where: { id: req.params.id }, relations: ["bot", "owner"] });
+
+	if (!app.bot)
+		throw DiscordApiErrors.BOT_ONLY_ENDPOINT;
+
+	if (app.owner.id != req.user_id)
+		throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
+
+	if (body.avatar)
+		body.avatar = await handleFile(
+			`/avatars/${app.id}`,
+			body.avatar as string,
+		);
+
+	app.bot.assign(body);
+
+	app.bot.save();
+
 	await app.save();
 	res.json(app).status(200);
 });
diff --git a/src/api/routes/applications/#id/index.ts b/src/api/routes/applications/#id/index.ts
index 0aced582..79df256a 100644
--- a/src/api/routes/applications/#id/index.ts
+++ b/src/api/routes/applications/#id/index.ts
@@ -1,28 +1,55 @@
 import { Request, Response, Router } from "express";
 import { route } from "@fosscord/api";
-import { Application, OrmUtils, Team, trimSpecial, User } from "@fosscord/util";
+import { Application, OrmUtils, DiscordApiErrors, ApplicationModifySchema, User } from "@fosscord/util";
+import { verifyToken } from "node-2fa";
+import { HTTPError } from "lambert-server";
 
 const router: Router = Router();
 
 router.get("/", route({}), async (req: Request, res: Response) => {
-	let results = await Application.findOne({where: {id: req.params.id}, relations: ["owner", "bot"] });
-	res.json(results).status(200);
+	const app = await Application.findOneOrFail({ where: { id: req.params.id }, relations: ["owner", "bot"] });
+	if (app.owner.id != req.user_id)
+		throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
+
+	return res.json(app);
 });
 
-router.patch("/", route({}), async (req: Request, res: Response) => {
-	delete req.body.icon;
-	let app = OrmUtils.mergeDeep(await Application.findOne({where: {id: req.params.id}, relations: ["owner", "bot"]}), req.body);
-	if(app.bot) {
-		app.bot.bio = req.body.description
-		app.bot?.save();
+router.patch("/", route({ body: "ApplicationModifySchema" }), async (req: Request, res: Response) => {
+	const body = req.body as ApplicationModifySchema;
+
+	const app = await Application.findOneOrFail({ where: { id: req.params.id }, relations: ["owner", "bot"] });
+
+	if (app.owner.id != req.user_id)
+		throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
+
+	if (app.owner.totp_secret && (!req.body.code || verifyToken(app.owner.totp_secret, req.body.code)))
+		throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
+
+	if (app.bot) {
+		app.bot.assign({ bio: body.description });
+		await app.bot.save();
 	}
-	if(req.body.tags) app.tags = req.body.tags;
+
+	app.assign(body);
+
 	await app.save();
-	res.json(app).status(200);
+
+	return res.json(app);
 });
 
 router.post("/delete", route({}), async (req: Request, res: Response) => {
-	await Application.delete(req.params.id);
+	const app = await Application.findOneOrFail({ where: { id: req.params.id }, relations: ["bot", "owner"] });
+	if (app.owner.id != req.user_id)
+		throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
+
+	if (app.owner.totp_secret && (!req.body.code || verifyToken(app.owner.totp_secret, req.body.code)))
+		throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
+
+	if (app.bot)
+		await User.delete({ id: app.bot.id });
+
+	await Application.delete({ id: app.id });
+
 	res.send().status(200);
 });
 
diff --git a/src/api/routes/applications/index.ts b/src/api/routes/applications/index.ts
index 41ce35b5..70af84e6 100644
--- a/src/api/routes/applications/index.ts
+++ b/src/api/routes/applications/index.ts
@@ -1,35 +1,31 @@
 import { Request, Response, Router } from "express";
 import { route } from "@fosscord/api";
-import { Application, OrmUtils, Team, trimSpecial, User } from "@fosscord/util";
+import { Application, ApplicationCreateSchema, trimSpecial, User } from "@fosscord/util";
 
 const router: Router = Router();
 
-export interface ApplicationCreateSchema {
-	name: string;
-	team_id?: string | number;
-}
-
 router.get("/", route({}), async (req: Request, res: Response) => {
-	//TODO
-	let results = await Application.find({where: {owner: {id: req.user_id}}, relations: ["owner", "bot"] });
+	let results = await Application.find({ where: { owner: { id: req.user_id } }, relations: ["owner", "bot"] });
 	res.json(results).status(200);
 });
 
-router.post("/", route({}), async (req: Request, res: Response) => {
+router.post("/", route({ body: "ApplicationCreateSchema" }), async (req: Request, res: Response) => {
 	const body = req.body as ApplicationCreateSchema;
-	const user = await User.findOne({where: {id: req.user_id}})
-	if(!user) res.status(420);
-	let app = OrmUtils.mergeDeep(new Application(), {
+	const user = await User.findOneOrFail({ where: { id: req.user_id } });
+
+	const app = Application.create({
 		name: trimSpecial(body.name),
 		description: "",
 		bot_public: true,
 		bot_require_code_grant: false,
 		owner: user,
 		verify_key: "IMPLEMENTME",
-		flags: ""
+		flags: 0,
 	});
+
 	await app.save();
-	res.json(app).status(200);
+
+	res.json(app);
 });
 
 export default router;
\ No newline at end of file
diff --git a/src/util/entities/Application.ts b/src/util/entities/Application.ts
index 28381579..861c5bdd 100644
--- a/src/util/entities/Application.ts
+++ b/src/util/entities/Application.ts
@@ -37,6 +37,7 @@ export class Application extends BaseClass {
 	@ManyToOne(() => User)
 	owner: User;
 	
+	// TODO: enum this? https://discord.com/developers/docs/resources/application#application-object-application-flags
 	@Column()
 	flags: number = 0;
 	
diff --git a/src/util/schemas/ApplicationCreateSchema.ts b/src/util/schemas/ApplicationCreateSchema.ts
new file mode 100644
index 00000000..6a021b46
--- /dev/null
+++ b/src/util/schemas/ApplicationCreateSchema.ts
@@ -0,0 +1,4 @@
+export interface ApplicationCreateSchema {
+	name: string;
+	team_id?: string | number;
+}
\ No newline at end of file
diff --git a/src/util/schemas/ApplicationModifySchema.ts b/src/util/schemas/ApplicationModifySchema.ts
new file mode 100644
index 00000000..ab23d57e
--- /dev/null
+++ b/src/util/schemas/ApplicationModifySchema.ts
@@ -0,0 +1,14 @@
+export interface ApplicationModifySchema {
+	description?: string;
+	icon?: string;
+	interactions_endpoint_url?: string;
+	max_participants?: number | null;
+	name?: string;
+	privacy_policy_url?: string;
+	role_connections_verification_url?: string;
+	tags?: string[];
+	terms_of_service_url?: string;
+	bot_public?: boolean;
+	bot_require_code_grant?: boolean;
+	flags?: number;
+}
\ No newline at end of file
diff --git a/src/util/schemas/BotModifySchema.ts b/src/util/schemas/BotModifySchema.ts
new file mode 100644
index 00000000..b801ab27
--- /dev/null
+++ b/src/util/schemas/BotModifySchema.ts
@@ -0,0 +1,4 @@
+export interface BotModifySchema {
+	avatar?: string;
+	username?: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/Validator.ts b/src/util/schemas/Validator.ts
index e85cdf7b..9b7f0eca 100644
--- a/src/util/schemas/Validator.ts
+++ b/src/util/schemas/Validator.ts
@@ -22,6 +22,7 @@ export const ajv = new Ajv({
 	messages: true,
 	strict: true,
 	strictRequired: true,
+	allowUnionTypes: true,
 });
 
 addFormats(ajv);
diff --git a/src/util/schemas/index.ts b/src/util/schemas/index.ts
index 780022c6..58565496 100644
--- a/src/util/schemas/index.ts
+++ b/src/util/schemas/index.ts
@@ -45,4 +45,7 @@ export * from "./UserGuildSettingsSchema";
 export * from "./GatewayPayloadSchema";
 export * from "./RolePositionUpdateSchema";
 export * from "./ChannelReorderSchema";
-export * from "./UserSettingsSchema";
\ No newline at end of file
+export * from "./UserSettingsSchema";
+export * from "./BotModifySchema";
+export * from "./ApplicationModifySchema";
+export * from "./ApplicationCreateSchema";
\ No newline at end of file