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).
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.
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.
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.