Skip to content

Misc Endpoints

tkaixiang edited this page Sep 1, 2021 · 9 revisions

GET /v1/scoreboard

Get all user score changes with timestamps
Authenticated

Input

No input required

Output

{
	"success": true,
	"scores": [
		{
			"author": "USERNAME_OF_USER",
			"timestamp": "TIMESTAMP",
			"points": "int (positive or negative)"
		},
		{
			"author": "USERNAME_OF_USER",
			"timestamp": "TIMESTAMP",
			"points": "int (positive or negative)"
		}
	]
}

Remarks

  • The events are not sorted by user and this must be done on the client side
  • This endpoint is probably very slow (needs to look through every document)
  • points is non-zero

GET /v1/scores

Get all user scores
Authenticated

Input

No input required

Output

{
	"success": true,
	"scores": [
		{
			"username": "USERNAME_OF_USER",
			"points": "int"
		},
		{
			"author": "USERNAME_OF_USER",
			"points": "int"
		}
	]
}

GET /v1/scoreboard/:username

Returns the score history of a requested user
Authenticated

Input

GET: /v1/scoreboard/USERNAME_OF_USER_TO_CHECK

Output

{
	"success": true,
	"scores": [
		{
			"challenge": "CHALLENGE_NAME",
			"type": "submission/hint",
			"timestamp": "TIMESTAMP",
			"points": "int"
		},
		{
			"challenge": "CHALLENGE_NAME",
			"type": "submission/hint",
			"timestamp": "TIMESTAMP",
			"points": "int"
		}
	]
}

Errors

No special errors

GET /v1/scores/:username

Gets the score of a requested user Authenticated

Input

GET: /v1/scores/USERNAME_OF_USER_TO_CHECK

Output

{
	"success": true,
	"score": 200
}

// If admin scores are disabled in the admin panel, the following is returned for admins:
{
    "success": true,
    "score": "hidden"
}

Errors

No special errors

GET /v1/submissions

Returns all recorded submissions(transactions)
Authenticated // Permissions: 2

Input

No input required

Output

{
	"success": true,
	"submissions": [
		{
			"_id": "SUBMISSION_ID (like 5ed326c62d0f6f32a834f049)",
			"author": "SUBMITTOR",
			"challenge": "CHALLENGE_NAME",
			"timestamp": "TIMESTAMP",
			"type": "submission/blocked_submission",
			"points": "int",
			"correct": "bool",
			"submission": "SUBMITTED_FLAG"
		}
	]
}

Errors

Error Definition
permissions The logged-in user does not have sufficient permissions to view submissions

Remarks

  • The submission ID is used to delete submissions

POST /adminSettings/

Change settings in the admin panel (more specifically settings stored in the cache collection)
Authenticated // Permissions: 2

Input

No input required

Output

{
	"success": true,
	"setting": "name_of_setting",
    "disable": "setting_value" // This can be a string/integer/boolean
}

Errors

Error Definition
permissions The logged-in user does not have sufficient permissions to change settings
invalid-setting The setting specified is not a valid setting to be changed

Remarks

  • Please get the initial state of settings from GET /account/disableStates and GET /challenges/disableStates
  • List of valid settings: ["registerDisable", "adminShowDisable", "submissionDisabled", "uploadSize", "uploadPath", "maxSockets"]

POST /profile/upload

Change the user's profile picture to the file specified Authenticated

Input

A multi-part form data with the file data named "profile_pic"

Output

{
	"success": true
}

Errors

Error Definition
no-file No file was uploaded/no file data was uploaded with the name "profile_pic"
only-1-file More than 1 file was uploaded
too-large The specified file was larger than the file size specified in cache.uploadSize (in bytes)
invalid-ext The file was not an image file of one of the allowed extensions (.png, .jpg, .jpeg, .webp)
file-upload There was an issue saving the file. Please check that the uploadPath cache.uploadPath has sufficient permissions for the script to save the file there

Remarks

  • By default, all images are converted to .webp and compressed to save space and load faster
  • The library used to convert the image to webp, sharp seems to have issues working on Windows, please use a Linux machine if possible.

POST /v1/submissions/new

Authenticated // Permissions: 2

Input

{
	"username": "USER_TO_CREDIT",
	"chall": "CHALL_NAME",
	"points": int,
	"flag": "(optional) FLAG_TO_BE_RECORDED",
	"force": (optional) bool
}

Output

{
	"success": true,
	"data": "STRING"
}

Data can be any of the following:

  • recorded: the submission was recorde
  • previous-higher: the previous score was higher, hence the score was not updated

Errors

Error Definition
permissions The logged-in user does not have sufficient permissions to create submissions

Remarks

  • When force is true, the API will ignore that the previous submissions had higher scores and will update the score anyways
  • This endpoint will be used for datascience challenges

WEBSOCKET /

The websocket is currently only used for live scoreboard updates. Please use wss if you have HTTPS enabled, and ws to connect if you don't.

All messages to/from the server are JSON-encoded in the following form:

{
	type: "string",
    data: "any JSON/String etc."
}

The communication protocol is likely to change if more websocket features are required

Live Scoreboard

  • First send an init packet

    {type: "init", data: {auth: "USER-TOKEN-FOR-AUTHENTICATION", lastChallengeID: 0 }}
    //lastChallengeID is the ID used for tracking whether the cached challenges are up-to-date
    • Responses (all with type init still)
      • bad-auth: User token is wrong
      • missing-auth: No auth property in data was found
      • max-connections: The account has more than the allowed connections set in maxSockets setting
      • If it is none of the above, then the endpoint sends scoreboard data to update the cached scoreboard
  • If the client fails to auth with the socket endpoint within 5 seconds, the client is disconnected forcefully

  • If the account hits the max-connections error, the server will disconnect clients from that account till the allowed limit.

  • Once the initialisation is completed, the client will receive any socket broadcasts from the server

  • A score packet is sent whenever a new hint is bought/challenge is solved to update the live scoreboard:

    { type: "score", data: solveDetails }