ctfy.sdk.admin_resources.announcements

client.admin.announcements — platform announcement CRUD (admin).

 1"""``client.admin.announcements`` — platform announcement CRUD (admin)."""
 2
 3from __future__ import annotations
 4
 5import builtins
 6from datetime import datetime
 7from typing import Any
 8
 9from ctfy.sdk._helpers import _raise_for_status
10from ctfy.sdk.base import BaseHttpClient
11from ctfy.server.models import AnnouncementInfo
12
13
14class AdminAnnouncementsResource:
15    """Post / edit / delete platform-wide announcements."""
16
17    def __init__(self, http: BaseHttpClient) -> None:
18        self._http = http
19
20    def list(self, offset: int = 0, limit: int = 50) -> builtins.list[AnnouncementInfo]:
21        """Every announcement (active + scheduled + expired)."""
22        resp = self._http.request(
23            "GET", "/admin/announcements", params={"offset": offset, "limit": limit}
24        )
25        _raise_for_status(resp)
26        return [AnnouncementInfo.model_validate(a) for a in resp.json()["items"]]
27
28    def create(
29        self,
30        *,
31        title: str,
32        body: str = "",
33        severity: str = "info",
34        starts_at: datetime | None = None,
35        ends_at: datetime | None = None,
36    ) -> AnnouncementInfo:
37        """Post a platform-wide announcement. ``None`` time fields =
38        live immediately / never expires. Requires super-admin."""
39        resp = self._http.request(
40            "POST",
41            "/admin/announcements",
42            json={
43                "title": title,
44                "body": body,
45                "severity": severity,
46                "starts_at": starts_at.isoformat() if starts_at else None,
47                "ends_at": ends_at.isoformat() if ends_at else None,
48            },
49        )
50        _raise_for_status(resp)
51        return AnnouncementInfo.model_validate(resp.json())
52
53    def update(self, announcement_id: str, **fields: Any) -> AnnouncementInfo:
54        """PATCH any subset of ``title`` / ``body`` / ``severity`` /
55        ``starts_at`` / ``ends_at``. Omit a field to leave it."""
56        resp = self._http.request("PATCH", f"/admin/announcements/{announcement_id}", json=fields)
57        _raise_for_status(resp)
58        return AnnouncementInfo.model_validate(resp.json())
59
60    def delete(self, announcement_id: str) -> None:
61        """Hard-delete one announcement."""
62        resp = self._http.request("DELETE", f"/admin/announcements/{announcement_id}")
63        _raise_for_status(resp)
class AdminAnnouncementsResource:
15class AdminAnnouncementsResource:
16    """Post / edit / delete platform-wide announcements."""
17
18    def __init__(self, http: BaseHttpClient) -> None:
19        self._http = http
20
21    def list(self, offset: int = 0, limit: int = 50) -> builtins.list[AnnouncementInfo]:
22        """Every announcement (active + scheduled + expired)."""
23        resp = self._http.request(
24            "GET", "/admin/announcements", params={"offset": offset, "limit": limit}
25        )
26        _raise_for_status(resp)
27        return [AnnouncementInfo.model_validate(a) for a in resp.json()["items"]]
28
29    def create(
30        self,
31        *,
32        title: str,
33        body: str = "",
34        severity: str = "info",
35        starts_at: datetime | None = None,
36        ends_at: datetime | None = None,
37    ) -> AnnouncementInfo:
38        """Post a platform-wide announcement. ``None`` time fields =
39        live immediately / never expires. Requires super-admin."""
40        resp = self._http.request(
41            "POST",
42            "/admin/announcements",
43            json={
44                "title": title,
45                "body": body,
46                "severity": severity,
47                "starts_at": starts_at.isoformat() if starts_at else None,
48                "ends_at": ends_at.isoformat() if ends_at else None,
49            },
50        )
51        _raise_for_status(resp)
52        return AnnouncementInfo.model_validate(resp.json())
53
54    def update(self, announcement_id: str, **fields: Any) -> AnnouncementInfo:
55        """PATCH any subset of ``title`` / ``body`` / ``severity`` /
56        ``starts_at`` / ``ends_at``. Omit a field to leave it."""
57        resp = self._http.request("PATCH", f"/admin/announcements/{announcement_id}", json=fields)
58        _raise_for_status(resp)
59        return AnnouncementInfo.model_validate(resp.json())
60
61    def delete(self, announcement_id: str) -> None:
62        """Hard-delete one announcement."""
63        resp = self._http.request("DELETE", f"/admin/announcements/{announcement_id}")
64        _raise_for_status(resp)

Post / edit / delete platform-wide announcements.

AdminAnnouncementsResource(http: ctfy.sdk.base.BaseHttpClient)
18    def __init__(self, http: BaseHttpClient) -> None:
19        self._http = http
def list( self, offset: int = 0, limit: int = 50) -> list[ctfy.server.models.AnnouncementInfo]:
21    def list(self, offset: int = 0, limit: int = 50) -> builtins.list[AnnouncementInfo]:
22        """Every announcement (active + scheduled + expired)."""
23        resp = self._http.request(
24            "GET", "/admin/announcements", params={"offset": offset, "limit": limit}
25        )
26        _raise_for_status(resp)
27        return [AnnouncementInfo.model_validate(a) for a in resp.json()["items"]]

Every announcement (active + scheduled + expired).

def create( self, *, title: str, body: str = '', severity: str = 'info', starts_at: datetime.datetime | None = None, ends_at: datetime.datetime | None = None) -> ctfy.server.models.AnnouncementInfo:
29    def create(
30        self,
31        *,
32        title: str,
33        body: str = "",
34        severity: str = "info",
35        starts_at: datetime | None = None,
36        ends_at: datetime | None = None,
37    ) -> AnnouncementInfo:
38        """Post a platform-wide announcement. ``None`` time fields =
39        live immediately / never expires. Requires super-admin."""
40        resp = self._http.request(
41            "POST",
42            "/admin/announcements",
43            json={
44                "title": title,
45                "body": body,
46                "severity": severity,
47                "starts_at": starts_at.isoformat() if starts_at else None,
48                "ends_at": ends_at.isoformat() if ends_at else None,
49            },
50        )
51        _raise_for_status(resp)
52        return AnnouncementInfo.model_validate(resp.json())

Post a platform-wide announcement. None time fields = live immediately / never expires. Requires super-admin.

def update( self, announcement_id: str, **fields: Any) -> ctfy.server.models.AnnouncementInfo:
54    def update(self, announcement_id: str, **fields: Any) -> AnnouncementInfo:
55        """PATCH any subset of ``title`` / ``body`` / ``severity`` /
56        ``starts_at`` / ``ends_at``. Omit a field to leave it."""
57        resp = self._http.request("PATCH", f"/admin/announcements/{announcement_id}", json=fields)
58        _raise_for_status(resp)
59        return AnnouncementInfo.model_validate(resp.json())

PATCH any subset of title / body / severity / starts_at / ends_at. Omit a field to leave it.

def delete(self, announcement_id: str) -> None:
61    def delete(self, announcement_id: str) -> None:
62        """Hard-delete one announcement."""
63        resp = self._http.request("DELETE", f"/admin/announcements/{announcement_id}")
64        _raise_for_status(resp)

Hard-delete one announcement.