diff options
author | lonkaars <l.leblansch@gmail.com> | 2021-04-16 16:36:58 +0200 |
---|---|---|
committer | lonkaars <l.leblansch@gmail.com> | 2021-04-16 16:36:58 +0200 |
commit | b9e1d1537bb9b8b178d9d6cb7aca06d8cfc068a4 (patch) | |
tree | 8fce0b45620b886be983fa6dc13c365dabf8f7ba | |
parent | b9a935cf545db36d714b44fdea96f448de67271e (diff) |
complete api documentation in api/readme.md
-rw-r--r-- | api/game/accept.py | 2 | ||||
-rw-r--r-- | api/readme.md | 335 |
2 files changed, 246 insertions, 91 deletions
diff --git a/api/game/accept.py b/api/game/accept.py index bf63c46..1f73fd1 100644 --- a/api/game/accept.py +++ b/api/game/accept.py @@ -14,7 +14,7 @@ join_game = Blueprint('game_accept', __name__) # join a game by game_id (public or private) @join_game.route('/accept', methods=['POST']) -@auth_required("user") +@auth_required("user") #FIXME: this doesn't work haha i don't know when i wrote this def index(game_id): if cursor.execute("select status from games where game_id = ?", [game_id]).fetchone()[0] != "wait_for_opponent": diff --git a/api/readme.md b/api/readme.md index fbaeba1..f46c812 100644 --- a/api/readme.md +++ b/api/readme.md @@ -1,10 +1,6 @@ # API -This is the subdirectory for the API. You can find the API reference in -[this](https://docs.google.com/spreadsheets/d/1mDN9IUqRIMjr_9RmLxKybjIgVuaUadalmPEFnG-XeJg/edit?usp=sharing) -Google Docs document. - -## Endpoint reference (WIP) +## Endpoint reference API return type classes are mostly defined in api/api.ts @@ -15,7 +11,7 @@ API return type classes are mostly defined in api/api.ts <th>method</th> <th>description</th> <th>parameters</th> -<th>authorization</th> +<th>minimal authorization</th> <th>response</th> </tr> </thead> @@ -78,20 +74,35 @@ API return type classes are mostly defined in api/api.ts <tr> <td>/user/info</td> -<td><code>GET|POST</code></td> -<td>get user info by username or id note: avatar is a uri to a 256x256 .png image</td> +<td><code>POST</code></td> +<td>get user info by id</td> <td> ```ts -{ id?: userID } +{ id: userID } ``` </td> -<td><code>none|user</code></td> +<td><code>none</code></td> +<td> + +```ts +{ userInfo } +``` + +</td> +</tr> + +<tr> +<td>/user/info</td> +<td><code>GET</code></td> +<td></td> +<td><code>none</code></td> +<td><code>user</code></td> <td> ```ts -userInfo; +{ userInfo } ``` </td> @@ -99,16 +110,16 @@ userInfo; <tr> <td>/user/games</td> -<td><code>GET|POST</code></td> +<td><code>POST</code></td> <td>get games of user</td> <td> ```ts -{ id?: userID } +{ id: userID } ``` </td> -<td><code>none|user</code></td> +<td><code>none</code></td> <td> ```ts @@ -122,17 +133,38 @@ userInfo; </tr> <tr> -<td>/user/avatar</td> +<td>/user/games</td> <td><code>GET</code></td> -<td>fetch avatar as .png</td> +<td></td> +<td><code>none</code></td> +<td><code>user</code></td> <td> ```ts -{ id?: userID } +{ + games: Array<gameInfo>, + totals: userGameTotals +} ``` </td> -<td><code>none|user</code></td> +</tr> + +<tr> +<td>/user/avatar?id=</td> +<td><code>GET</code></td> +<td>fetch avatar as .png using url parameter</td> +<td><code>none</code></td> +<td><code>none</code></td> +<td>PNG image</td> +</tr> + +<tr> +<td>/user/avatar</td> +<td><code>GET</code></td> +<td>fetch avatar as .png</td> +<td><code>none</code></td> +<td><code>user</code></td> <td>PNG image</td> </tr> @@ -149,10 +181,7 @@ returns error when image is not .png or larger than 256x256 <td> ```ts -{ - image: - base64PNG; -} +{ image: base64PNG; } ``` </td> @@ -169,10 +198,7 @@ returns error when image is not .png or larger than 256x256 <td> ```ts -{ - preferences: - userPreferences; -} +{ preferences: userPreferences; } ``` </td> @@ -185,10 +211,7 @@ returns error when image is not .png or larger than 256x256 <td> ```ts -{ - newPreferences: - userPreferences; -} +{ newPreferences: userPreferences; } ``` </td> @@ -198,7 +221,7 @@ returns error when image is not .png or larger than 256x256 <tr> <td>/user/password</td> -<td>POST</td> +<td><code>POST</code></td> <td>update password</td> <td> @@ -216,7 +239,7 @@ returns error when image is not .png or larger than 256x256 <tr> <td>/user/email</td> -<td>POST</td> +<td><code>POST</code></td> <td>update email</td> <td> @@ -234,7 +257,7 @@ returns error when image is not .png or larger than 256x256 <tr> <td>/user/username</td> -<td>POST</td> +<td><code>POST</code></td> <td>update username</td> <td> @@ -257,10 +280,7 @@ returns error when image is not .png or larger than 256x256 <td> ```ts -{ - status: - string; -} +{ status: string; } ``` </td> @@ -269,123 +289,253 @@ returns error when image is not .png or larger than 256x256 </tr> <tr> -<td>/user/searchFriends</td> -<td><code>POST</code></td> -<td>search user's friend list</td> -<td></td> -<td></td> -</tr> - -<tr> <td>/social/request</td> <td><code>POST</code></td> <td>send a friend request to a user by user id</td> -<td></td> -<td></td> +<td> + +```ts +{ id: userID } +``` + +</td> +<td><code>user</code></td> +<td><code>none</code></td> </tr> <tr> <td>/social/accept</td> <td><code>POST</code></td> <td>accept a friend request</td> -<td></td> -<td></td> +<td> + +```ts +{ id: userID } +``` + +</td> +<td><code>user</code></td> +<td><code>none</code></td> </tr> <tr> <td>/social/remove</td> <td><code>POST</code></td> <td>remove a friend from your friend list or delete a friend request from a user</td> -<td></td> -<td></td> +<td> + +```ts +{ id: userID } +``` + +</td> +<td><code>user</code></td> +<td><code>none</code></td> </tr> <tr> <td>/social/search</td> <td><code>POST</code></td> <td>search for users by username or status</td> -<td></td> -<td></td> +<td> + +```ts +{ query: string } +``` + +</td> +<td><code>none</code></td> +<td> + +```ts +{ results: Array<userInfo> } +``` + +</td> </tr> <tr> <td>/social/block</td> <td><code>POST</code></td> <td>block a user</td> -<td></td> -<td></td> +<td> + +```ts +{ id: userID } +``` + +</td> +<td><code>user</code></td> +<td><code>none</code></td> </tr> <tr> <td>/social/unblock</td> <td><code>POST</code></td> <td>unblock a user</td> -<td></td> -<td></td> +<td> + +```ts +{ id: userID } +``` + +</td> +<td><code>user</code></td> +<td><code>none</code></td> </tr> <tr> <td>/social/list/requests</td> <td><code>GET</code></td> <td>get a list of unaccepted friend requests</td> -<td></td> -<td></td> +<td><code>none</code></td> +<td><code>user</code></td> +<td> + +```ts +{ requests: Array<userInfo> } +``` + +</td> </tr> <tr> <td>/social/list/blocks</td> <td><code>GET</code></td> <td>get a list of blocked people</td> -<td></td> -<td></td> +<td><code>none</code></td> +<td><code>user</code></td> +<td> + +```ts +{ blocks: Array<userInfo> } +``` + +</td> </tr> <tr> <td>/social/list/friends</td> <td><code>GET</code></td> <td>get a list of your friends</td> -<td></td> -<td></td> +<td><code>none</code></td> +<td><code>user</code></td> +<td> + +```ts +{ friends: Array<userInfo> } +``` + +</td> </tr> <tr> <td>/game/new</td> <td><code>POST</code></td> <td>create a new private game</td> -<td></td> -<td></td> +<td><code>none</code></td> +<td><code>user</code></td> +<td> + +```ts +{ + id: gameID, + player_1: boolean, + game_started: boolean, +} +``` + +</td> </tr> <tr> <td>/game/random</td> <td><code>POST</code></td> <td>join or create a public game</td> -<td></td> -<td></td> +<td><code>none</code></td> +<td><code>user</code></td> +<td> + +```ts +{ + id: gameID, + player_1: boolean, + game_started: boolean, +} +``` + +</td> </tr> <tr> <td>/game/info</td> <td><code>POST</code></td> -<td></td> -<td></td> -<td></td> +<td>get game info by game id</td> +<td> + +```ts +{ id: gameID } +``` + +</td> +<td><code>user</code></td> +<td> + +```ts +{ gameInfo } +``` + +</td> </tr> <tr> <td>/game/accept</td> <td><code>POST</code></td> <td>accept game invite or rematch</td> -<td></td> -<td></td> +<td> + +```ts +{ id: gameID } +``` + +</td> +<td><code>user</code></td> +<td> + +```ts +{ + id: gameID, + player_1: boolean, + game_started: boolean, +} +``` + +</td> </tr> <tr> <td>/game/spectate</td> <td><code>POST</code></td> <td>spectate a game by id</td> -<td></td> -<td></td> +<td> + +```ts +{ id: gameID } +``` + +</td> +<td><code>none</code></td> +<td> + +```ts +{ + id: gameID, + player_1: boolean, + game_started: boolean, +} +``` + +</td> </tr> </tbody> @@ -495,24 +645,9 @@ curl http://localhost:5000/<endpoint> curl http://localhost:2080/api/<endpoint> ``` -## How to add new API endpoints - -Please follow these rules when creating new API endpoints: - -1. Endpoints should always return a valid JSON object and an appropriate - [http code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) -2. Endpoints that are in a namespace should get their own directory in this - folder, eg. http://localhost:5000/status is defined in api/status.py, - http://localhost:5000/auth/signup is defined in api/auth/signup.py etc. -3. Endpoints that take data should verify that the data is present and valid, - and return an empty JSON object with http code 400 (bad request) if the data - isn't valid. -4. Endpoints that require database access should get the cursor/connection - object from api/db.py - ## Example endpoint -Here's a simple endpoint that returns an empty JSON object: +Here's a simple endpoint that returns a "hello world" JSON object: ```py # api/tests/example.py @@ -537,3 +672,23 @@ dynamic_route = ["/tests", status] # | # namespace (defined in dynamic_route variable) ``` + +## Handy utility functions and where to find them + +All of the paths are defined relative to this (api/) directory. Most of these +functions/decorators should also have docstrings for editor autocompletion +help, but not all of them do. + +utility | description | file +-----------------------------------|--------------------------------------------------------------------------|------------- +`@util_two_id(type)` | exposes (token_id, explicit_id) to the endpoint | hierarchy.py +`@two_person` | exposes (user_1_id, user_2_id) to the endpoint | hierarchy.py +`@one_person` | exposes (user_id) to the endpoint | hierarchy.py +`@game_id_with_viewer` | exposes (game_id, viewer?) to the endpoint | hierarchy.py +`@auth_required(level)` | checks if user is authorized and expose (user_id) to the endpoint | hierarchy.py +`@io_auth_required(level)` | same as @auth_required but for socket.io event listeners | hierarchy.py +`all_def([ ... ])` | checks if all items of the list are truthy | util.py +`all_notdef([ ... ])` | checks if all items of the list are falsy | util.py +`format_user(user_id, viewer_id?)` | format a user to /api/user/info format with optional viewer for relation | user/info.py +`format_game(game_id, viewer_id?)` | format a game to /api/game/info format with optional viewer for opponent | game/info.py + |