aboutsummaryrefslogtreecommitdiff

API

Endpoint reference

API return type classes are mostly defined in api/api.ts

endpoint method description parameters minimal authorization response
/status GET get online user count and active game count none none
{
  users: int,
  games: int,
  version: {
    commit: string,
    commit_short: string,
    number: string
  }
}
/auth/login POST log in with email or username
{
  email: string,
  password: string
}
none empty response with the set_cookie header
/auth/signup POST sign up
{
  username: string,
  email: string,
  password: string
}
none empty response with the set_cookie header
/user/info POST get user info by id
{
    id: userID;
}
none
{
    userInfo;
}
/user/info GET none user
{
    userInfo;
}
/user/games POST get games of user
{
    id: userID;
}
none
{
  games: Array<gameInfo>,
  totals: userGameTotals
}
/user/games GET none user
{
  games: Array<gameInfo>,
  totals: userGameTotals
}
/user/avatar?id= GET fetch avatar as .png using url parameter none none PNG image
/user/avatar GET fetch avatar as .png none user PNG image
/user/avatar POST update avatar

note: avatar is a client-resized 256x256 .png base64-encoded image, request returns error when image is not .png or larger than 256x256

{
  image: base64PNG;
}
user none
/user/prefrences GET fetch user preferences none user
{
  preferences: userPreferences;
}
/user/prefrences POST change user preferences
{
  newPreferences: userPreferences;
}
user none
/user/password POST update password
{
  password: string,
  newPassword: string,
}
user none
/user/email POST update email
{
  password: string,
  email: string,
}
user none
/user/username POST update username
{
  password: string,
  username: string,
}
user none
/user/status POST update status
{
  status: string;
}
user none
/social/request POST send a friend request to a user by user id
{
  id: userID;
}
user none
/social/accept POST accept a friend request
{
  id: userID;
}
user none
/social/remove POST remove a friend from your friend list or delete a friend request from a user
{
  id: userID;
}
user none
/social/search POST search for users by username or status
{
  query: string;
}
none
{
  results: Array<userInfo>
}
/social/block POST block a user
{
  id: userID;
}
user none
/social/unblock POST unblock a user
{
  id: userID;
}
user none
/social/list/requests GET get a list of unaccepted friend requests none user
{
  requests: Array<userInfo>
}
/social/list/blocks GET get a list of blocked people none user
{
  blocks: Array<userInfo>
}
/social/list/friends GET get a list of your friends none user
{
  friends: Array<userInfo>
}
/game/new POST create a new private game none user
{
  id: gameID,
  player_1: boolean,
  game_started: boolean,
}
/game/random POST join or create a public game none user
{
  id: gameID,
  player_1: boolean,
  game_started: boolean,
}
/game/info POST get game info by game id
{
  id: gameID;
}
user
{
  gameInfo;
}
/game/accept POST accept game invite or rematch
{
  id: gameID;
}
user
{
  id: gameID,
  player_1: boolean,
  game_started: boolean,
}
/game/spectate POST spectate a game by id
{
  id: gameID;
}
none
{
  id: gameID,
  player_1: boolean,
  game_started: boolean,
}
/verify/discord GET get a one-time code for verifying account ownership with the discord bot none user
{
  code: string;
}

Events

These are events that are fired by the socket.io connection

event description data direction context
fieldUpdate recieve new playfield from server { field: string } s -> c game
turnUpdate recieve if it's player 1's move { player1: boolean } s -> c game
gameStart sent when game starts none s -> c game
finish sent when game finishes none s -> c game
resign send to resign, is then forwarded to all subscribed clients none s <-> c game
newMove send a new move { move: int, game_id: string } s <- c game
registerGameListener listen to events for a game { id: string } s <- c game
incomingFriendRequest get notified of friend request none s -> c global
changedRelation get notified of a different relation to someone { id: string } s -> c global

How to test API endpoints

# If you're running the standalone flask server:
curl http://localhost:5000/<endpoint>

# If you're running flask and nginx at the same time:
curl http://localhost:2080/api/<endpoint>

Example endpoint

Here's a simple endpoint that returns a "hello world" JSON object:

# api/tests/example.py
from flask import Blueprint

example = Blueprint('example', __name__)

@example.route('/example')
def index():
    # python dictionaries are automatically converted to JSON by flask
    return {"hello": "world"}, 200 # flask returns http code 200 by default if no code is explicitly defined

# define a `dynamic_route` variable at the end of your endpoint definition file
# dynamic_route[0] is the namespace
# dynamic_route[1] is your flask.Blueprint
dynamic_route = ["/tests", status]

# this endpoint will be routed to /tests/example
#                                  \___/ \_____/
#                                    |      |
#                                    |      endpoint (defined by the @Blueprint.route() decorator)
#                                    |
#                                    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