ctfy.sdk.resources.hints

client.hints — a challenge's hint tiers in a competition (#2101).

The same rules as the web page: a costed tier is opened explicitly by HintsResource.view(), and that charges the caller's whole team once.

 1"""``client.hints`` — a challenge's hint tiers in a competition (#2101).
 2
 3The same rules as the web page: a costed tier is opened explicitly by
 4:meth:`HintsResource.view`, and that charges the caller's whole team once.
 5"""
 6
 7from __future__ import annotations
 8
 9from ctfy.sdk._helpers import _raise_for_status
10from ctfy.sdk.base import BaseHttpClient
11from ctfy.server.models import HintViewResult, PlayerHintList
12
13
14class HintsResource:
15    """Read and open the hints of one challenge of one competition."""
16
17    def __init__(self, http: BaseHttpClient) -> None:
18        self._http = http
19
20    def list(self, competition_id: str, challenge_id: str) -> PlayerHintList:
21        """The tiers as your team sees them: released free or opened ones
22        with their content, costed ones with their cost, locked ones with
23        nothing but (for a tier that opens by time alone) when."""
24        resp = self._http.request(
25            "GET", f"/competitions/{competition_id}/challenges/{challenge_id}/hints"
26        )
27        _raise_for_status(resp)
28        return PlayerHintList.model_validate(resp.json())
29
30    def view(self, competition_id: str, challenge_id: str, hint_id: str) -> HintViewResult:
31        """Open one released tier for your team. A costed tier is charged
32        once, for the whole team, and cannot be undone."""
33        resp = self._http.request(
34            "POST",
35            f"/competitions/{competition_id}/challenges/{challenge_id}/hints/{hint_id}/view",
36        )
37        _raise_for_status(resp)
38        return HintViewResult.model_validate(resp.json())
39
40    def download_attachment(self, competition_id: str, challenge_id: str, hint_id: str) -> bytes:
41        """The file of a tier you may read."""
42        resp = self._http.request(
43            "GET",
44            f"/competitions/{competition_id}/challenges/{challenge_id}/hints/{hint_id}/attachment",
45        )
46        _raise_for_status(resp)
47        return resp.content
class HintsResource:
15class HintsResource:
16    """Read and open the hints of one challenge of one competition."""
17
18    def __init__(self, http: BaseHttpClient) -> None:
19        self._http = http
20
21    def list(self, competition_id: str, challenge_id: str) -> PlayerHintList:
22        """The tiers as your team sees them: released free or opened ones
23        with their content, costed ones with their cost, locked ones with
24        nothing but (for a tier that opens by time alone) when."""
25        resp = self._http.request(
26            "GET", f"/competitions/{competition_id}/challenges/{challenge_id}/hints"
27        )
28        _raise_for_status(resp)
29        return PlayerHintList.model_validate(resp.json())
30
31    def view(self, competition_id: str, challenge_id: str, hint_id: str) -> HintViewResult:
32        """Open one released tier for your team. A costed tier is charged
33        once, for the whole team, and cannot be undone."""
34        resp = self._http.request(
35            "POST",
36            f"/competitions/{competition_id}/challenges/{challenge_id}/hints/{hint_id}/view",
37        )
38        _raise_for_status(resp)
39        return HintViewResult.model_validate(resp.json())
40
41    def download_attachment(self, competition_id: str, challenge_id: str, hint_id: str) -> bytes:
42        """The file of a tier you may read."""
43        resp = self._http.request(
44            "GET",
45            f"/competitions/{competition_id}/challenges/{challenge_id}/hints/{hint_id}/attachment",
46        )
47        _raise_for_status(resp)
48        return resp.content

Read and open the hints of one challenge of one competition.

HintsResource(http: ctfy.sdk.base.BaseHttpClient)
18    def __init__(self, http: BaseHttpClient) -> None:
19        self._http = http
def list( self, competition_id: str, challenge_id: str) -> ctfy.server.models.PlayerHintList:
21    def list(self, competition_id: str, challenge_id: str) -> PlayerHintList:
22        """The tiers as your team sees them: released free or opened ones
23        with their content, costed ones with their cost, locked ones with
24        nothing but (for a tier that opens by time alone) when."""
25        resp = self._http.request(
26            "GET", f"/competitions/{competition_id}/challenges/{challenge_id}/hints"
27        )
28        _raise_for_status(resp)
29        return PlayerHintList.model_validate(resp.json())

The tiers as your team sees them: released free or opened ones with their content, costed ones with their cost, locked ones with nothing but (for a tier that opens by time alone) when.

def view( self, competition_id: str, challenge_id: str, hint_id: str) -> ctfy.server.models.HintViewResult:
31    def view(self, competition_id: str, challenge_id: str, hint_id: str) -> HintViewResult:
32        """Open one released tier for your team. A costed tier is charged
33        once, for the whole team, and cannot be undone."""
34        resp = self._http.request(
35            "POST",
36            f"/competitions/{competition_id}/challenges/{challenge_id}/hints/{hint_id}/view",
37        )
38        _raise_for_status(resp)
39        return HintViewResult.model_validate(resp.json())

Open one released tier for your team. A costed tier is charged once, for the whole team, and cannot be undone.

def download_attachment(self, competition_id: str, challenge_id: str, hint_id: str) -> bytes:
41    def download_attachment(self, competition_id: str, challenge_id: str, hint_id: str) -> bytes:
42        """The file of a tier you may read."""
43        resp = self._http.request(
44            "GET",
45            f"/competitions/{competition_id}/challenges/{challenge_id}/hints/{hint_id}/attachment",
46        )
47        _raise_for_status(resp)
48        return resp.content

The file of a tier you may read.