ctfy.sdk.resources.users

client.users — public per-user profile reads.

 1"""``client.users`` — public per-user profile reads."""
 2
 3from __future__ import annotations
 4
 5from ctfy.sdk._helpers import _raise_for_status
 6from ctfy.sdk.base import BaseHttpClient
 7from ctfy.server.models import ProfileStats, UserInfo, UserSolveTrend
 8
 9
10class UsersResource:
11    """Public profile reads for one user (privacy-scrubbed per their settings)."""
12
13    def __init__(self, http: BaseHttpClient) -> None:
14        self._http = http
15
16    def get(self, user_id: str) -> UserInfo:
17        """Public profile for one user. Privacy-scrubbed per the user's
18        ``profile_visibility`` settings for non-owner non-admin viewers."""
19        resp = self._http.request("GET", f"/users/{user_id}")
20        _raise_for_status(resp)
21        return UserInfo.model_validate(resp.json())
22
23    def solve_trend(self, user_id: str, days: int = 30) -> UserSolveTrend:
24        """Daily solve count over ``days`` (UTC). Privacy-aware: returns
25        an empty series when the viewer can't see the user's solve trend."""
26        resp = self._http.request(
27            "GET",
28            f"/users/{user_id}/solve-trend",
29            params={"days": days},
30        )
31        _raise_for_status(resp)
32        return UserSolveTrend.model_validate(resp.json())
33
34    def profile_stats(self, user_id: str, days: int = 30) -> ProfileStats:
35        """Public profile visualizations for one user (activity
36        calendar, per-tag radar, difficulty bar, solve trend).
37        Privacy-scrubbed for non-owner non-admin viewers."""
38        resp = self._http.request("GET", f"/users/{user_id}/profile-stats", params={"days": days})
39        _raise_for_status(resp)
40        return ProfileStats.model_validate(resp.json())
class UsersResource:
11class UsersResource:
12    """Public profile reads for one user (privacy-scrubbed per their settings)."""
13
14    def __init__(self, http: BaseHttpClient) -> None:
15        self._http = http
16
17    def get(self, user_id: str) -> UserInfo:
18        """Public profile for one user. Privacy-scrubbed per the user's
19        ``profile_visibility`` settings for non-owner non-admin viewers."""
20        resp = self._http.request("GET", f"/users/{user_id}")
21        _raise_for_status(resp)
22        return UserInfo.model_validate(resp.json())
23
24    def solve_trend(self, user_id: str, days: int = 30) -> UserSolveTrend:
25        """Daily solve count over ``days`` (UTC). Privacy-aware: returns
26        an empty series when the viewer can't see the user's solve trend."""
27        resp = self._http.request(
28            "GET",
29            f"/users/{user_id}/solve-trend",
30            params={"days": days},
31        )
32        _raise_for_status(resp)
33        return UserSolveTrend.model_validate(resp.json())
34
35    def profile_stats(self, user_id: str, days: int = 30) -> ProfileStats:
36        """Public profile visualizations for one user (activity
37        calendar, per-tag radar, difficulty bar, solve trend).
38        Privacy-scrubbed for non-owner non-admin viewers."""
39        resp = self._http.request("GET", f"/users/{user_id}/profile-stats", params={"days": days})
40        _raise_for_status(resp)
41        return ProfileStats.model_validate(resp.json())

Public profile reads for one user (privacy-scrubbed per their settings).

UsersResource(http: ctfy.sdk.base.BaseHttpClient)
14    def __init__(self, http: BaseHttpClient) -> None:
15        self._http = http
def get(self, user_id: str) -> ctfy.server.models.UserInfo:
17    def get(self, user_id: str) -> UserInfo:
18        """Public profile for one user. Privacy-scrubbed per the user's
19        ``profile_visibility`` settings for non-owner non-admin viewers."""
20        resp = self._http.request("GET", f"/users/{user_id}")
21        _raise_for_status(resp)
22        return UserInfo.model_validate(resp.json())

Public profile for one user. Privacy-scrubbed per the user's profile_visibility settings for non-owner non-admin viewers.

def solve_trend( self, user_id: str, days: int = 30) -> ctfy.server.models.UserSolveTrend:
24    def solve_trend(self, user_id: str, days: int = 30) -> UserSolveTrend:
25        """Daily solve count over ``days`` (UTC). Privacy-aware: returns
26        an empty series when the viewer can't see the user's solve trend."""
27        resp = self._http.request(
28            "GET",
29            f"/users/{user_id}/solve-trend",
30            params={"days": days},
31        )
32        _raise_for_status(resp)
33        return UserSolveTrend.model_validate(resp.json())

Daily solve count over days (UTC). Privacy-aware: returns an empty series when the viewer can't see the user's solve trend.

def profile_stats( self, user_id: str, days: int = 30) -> ctfy.server.models.ProfileStats:
35    def profile_stats(self, user_id: str, days: int = 30) -> ProfileStats:
36        """Public profile visualizations for one user (activity
37        calendar, per-tag radar, difficulty bar, solve trend).
38        Privacy-scrubbed for non-owner non-admin viewers."""
39        resp = self._http.request("GET", f"/users/{user_id}/profile-stats", params={"days": days})
40        _raise_for_status(resp)
41        return ProfileStats.model_validate(resp.json())

Public profile visualizations for one user (activity calendar, per-tag radar, difficulty bar, solve trend). Privacy-scrubbed for non-owner non-admin viewers.