ctfy.sdk.admin_resources.challenge_schedule

client.admin.challenge_schedule — when each challenge of a competition appears and shuts, and the one-click release (#2093).

 1"""``client.admin.challenge_schedule`` — when each challenge of a competition
 2appears and shuts, and the one-click release (#2093)."""
 3
 4from __future__ import annotations
 5
 6from collections.abc import Sequence
 7from datetime import datetime
 8from typing import Any, Final
 9
10from ctfy.sdk._helpers import _raise_for_status
11from ctfy.sdk.base import BaseHttpClient
12from ctfy.server.models import CompetitionChallengeSchedule
13
14
15class _Unset:
16    """The argument was not passed — distinct from ``None``, which clears."""
17
18    def __repr__(self) -> str:
19        return "UNSET"
20
21
22UNSET: Final = _Unset()
23
24
25class AdminChallengeScheduleResource:
26    """Read and edit one competition's per-challenge release schedule. For
27    its organisers (global admins and the event's own competition admins)."""
28
29    def __init__(self, http: BaseHttpClient) -> None:
30        self._http = http
31
32    def get(self, competition_id: str) -> CompetitionChallengeSchedule:
33        """Every challenge of the competition with its batch, reveal and
34        close time; ``released`` / ``closed`` are read from the clock."""
35        resp = self._http.request("GET", f"/admin/competitions/{competition_id}/challenge-schedule")
36        _raise_for_status(resp)
37        return CompetitionChallengeSchedule.model_validate(resp.json())
38
39    def update(
40        self,
41        competition_id: str,
42        *,
43        challenge_ids: Sequence[str] = (),
44        in_batch: str = "",
45        batch: str | _Unset = UNSET,
46        reveal_at: datetime | _Unset | None = UNSET,
47        close_at: datetime | _Unset | None = UNSET,
48        release_now: bool = False,
49    ) -> CompetitionChallengeSchedule:
50        """Set the schedule of several challenges at once.
51
52        Select with ``challenge_ids`` and/or ``in_batch`` (every challenge
53        now in that batch). Partial: only what you pass is sent, and ``None``
54        clears a time (``""`` clears the batch). ``release_now`` reveals them
55        at the instant the request is served.
56        """
57        payload: dict[str, Any] = {
58            "challenge_ids": list(challenge_ids),
59            "in_batch": in_batch,
60            "release_now": release_now,
61        }
62        if not isinstance(batch, _Unset):
63            payload["batch"] = batch
64        if not isinstance(reveal_at, _Unset):
65            payload["reveal_at"] = reveal_at.isoformat() if reveal_at else None
66        if not isinstance(close_at, _Unset):
67            payload["close_at"] = close_at.isoformat() if close_at else None
68        resp = self._http.request(
69            "PATCH", f"/admin/competitions/{competition_id}/challenge-schedule", json=payload
70        )
71        _raise_for_status(resp)
72        return CompetitionChallengeSchedule.model_validate(resp.json())
UNSET: Final = UNSET
class AdminChallengeScheduleResource:
26class AdminChallengeScheduleResource:
27    """Read and edit one competition's per-challenge release schedule. For
28    its organisers (global admins and the event's own competition admins)."""
29
30    def __init__(self, http: BaseHttpClient) -> None:
31        self._http = http
32
33    def get(self, competition_id: str) -> CompetitionChallengeSchedule:
34        """Every challenge of the competition with its batch, reveal and
35        close time; ``released`` / ``closed`` are read from the clock."""
36        resp = self._http.request("GET", f"/admin/competitions/{competition_id}/challenge-schedule")
37        _raise_for_status(resp)
38        return CompetitionChallengeSchedule.model_validate(resp.json())
39
40    def update(
41        self,
42        competition_id: str,
43        *,
44        challenge_ids: Sequence[str] = (),
45        in_batch: str = "",
46        batch: str | _Unset = UNSET,
47        reveal_at: datetime | _Unset | None = UNSET,
48        close_at: datetime | _Unset | None = UNSET,
49        release_now: bool = False,
50    ) -> CompetitionChallengeSchedule:
51        """Set the schedule of several challenges at once.
52
53        Select with ``challenge_ids`` and/or ``in_batch`` (every challenge
54        now in that batch). Partial: only what you pass is sent, and ``None``
55        clears a time (``""`` clears the batch). ``release_now`` reveals them
56        at the instant the request is served.
57        """
58        payload: dict[str, Any] = {
59            "challenge_ids": list(challenge_ids),
60            "in_batch": in_batch,
61            "release_now": release_now,
62        }
63        if not isinstance(batch, _Unset):
64            payload["batch"] = batch
65        if not isinstance(reveal_at, _Unset):
66            payload["reveal_at"] = reveal_at.isoformat() if reveal_at else None
67        if not isinstance(close_at, _Unset):
68            payload["close_at"] = close_at.isoformat() if close_at else None
69        resp = self._http.request(
70            "PATCH", f"/admin/competitions/{competition_id}/challenge-schedule", json=payload
71        )
72        _raise_for_status(resp)
73        return CompetitionChallengeSchedule.model_validate(resp.json())

Read and edit one competition's per-challenge release schedule. For its organisers (global admins and the event's own competition admins).

AdminChallengeScheduleResource(http: ctfy.sdk.base.BaseHttpClient)
30    def __init__(self, http: BaseHttpClient) -> None:
31        self._http = http
def get( self, competition_id: str) -> ctfy.server.models.CompetitionChallengeSchedule:
33    def get(self, competition_id: str) -> CompetitionChallengeSchedule:
34        """Every challenge of the competition with its batch, reveal and
35        close time; ``released`` / ``closed`` are read from the clock."""
36        resp = self._http.request("GET", f"/admin/competitions/{competition_id}/challenge-schedule")
37        _raise_for_status(resp)
38        return CompetitionChallengeSchedule.model_validate(resp.json())

Every challenge of the competition with its batch, reveal and close time; released / closed are read from the clock.

def update( self, competition_id: str, *, challenge_ids: Sequence[str] = (), in_batch: str = '', batch: str | ctfy.sdk.admin_resources.challenge_schedule._Unset = UNSET, reveal_at: datetime.datetime | ctfy.sdk.admin_resources.challenge_schedule._Unset | None = UNSET, close_at: datetime.datetime | ctfy.sdk.admin_resources.challenge_schedule._Unset | None = UNSET, release_now: bool = False) -> ctfy.server.models.CompetitionChallengeSchedule:
40    def update(
41        self,
42        competition_id: str,
43        *,
44        challenge_ids: Sequence[str] = (),
45        in_batch: str = "",
46        batch: str | _Unset = UNSET,
47        reveal_at: datetime | _Unset | None = UNSET,
48        close_at: datetime | _Unset | None = UNSET,
49        release_now: bool = False,
50    ) -> CompetitionChallengeSchedule:
51        """Set the schedule of several challenges at once.
52
53        Select with ``challenge_ids`` and/or ``in_batch`` (every challenge
54        now in that batch). Partial: only what you pass is sent, and ``None``
55        clears a time (``""`` clears the batch). ``release_now`` reveals them
56        at the instant the request is served.
57        """
58        payload: dict[str, Any] = {
59            "challenge_ids": list(challenge_ids),
60            "in_batch": in_batch,
61            "release_now": release_now,
62        }
63        if not isinstance(batch, _Unset):
64            payload["batch"] = batch
65        if not isinstance(reveal_at, _Unset):
66            payload["reveal_at"] = reveal_at.isoformat() if reveal_at else None
67        if not isinstance(close_at, _Unset):
68            payload["close_at"] = close_at.isoformat() if close_at else None
69        resp = self._http.request(
70            "PATCH", f"/admin/competitions/{competition_id}/challenge-schedule", json=payload
71        )
72        _raise_for_status(resp)
73        return CompetitionChallengeSchedule.model_validate(resp.json())

Set the schedule of several challenges at once.

Select with challenge_ids and/or in_batch (every challenge now in that batch). Partial: only what you pass is sent, and None clears a time ("" clears the batch). release_now reveals them at the instant the request is served.