jdabtieu / CTFOJ

Lightweight CTF judge platform for capture-the-flag (CTF) clubs
GNU Affero General Public License v3.0
10 stars 5 forks source link

[FEATURE] Export CTFtime scoreboard #219

Closed jdabtieu closed 1 year ago

jdabtieu commented 1 year ago

Is your feature request related to a problem? Please describe.

There should be an easy way for admins to export the scoreboard to CTFtime format to upload post contest. Or to put in the "live scoreboard feed" box in CTFtime

Describe the solution you'd like

API endpoint that exposes this.

This was used in BxMCTF:

diff --git a/src/api.py b/src/api.py
index 16feee5..121d003 100644
--- a/src/api.py
+++ b/src/api.py
@@ -220,6 +220,37 @@ def contest_problem():
     return json_success(returns)

+@api.route("/contest/scoreboard/<contest_id>")
+@api_login_required
+def contest_scoreboard(contest_id):
+    from application import db
+    # Ensure contest exists
+    contest_info = db.execute("SELECT * FROM contests WHERE id=:cid", cid=contest_id)
+    if len(contest_info) != 1:
+        return json_fail("The contest doesn't exist", 404)
+
+    # Ensure proper permissions
+    if not contest_info[0]["scoreboard_visible"] and not api_admin():
+        return json_fail('You are not allowed to view the scoreboard!', 401)
+
+    data = db.execute(
+        ("SELECT user_id, points, lastAC, username FROM contest_users "
+         "JOIN users on user_id=users.id WHERE contest_users.contest_id=:cid AND "
+         "hidden=0 ORDER BY points DESC, lastAC ASC"),
+        cid=contest_id)
+    teams = db.execute("SELECT id, username FROM users")
+    teams = {x["id"]: x["username"] for x in teams}
+    ret = {"standings": []}
+    for i in range(len(data)):
+        ret["standings"].append({
+            "pos": i + 1,
+            "team": teams[data[i]["user_id"]],
+            "score": data[i]["points"],
+        })
+
+    return json.dumps(ret)
+
+
jdabtieu commented 1 year ago

Implemented in a4d21a8157624d484091c15502b61ea922355243