Updated Owncast clients to v0.2.5 and added spec-coverage and integration tests to enforce parity with the OpenAPI spec.
CI / Formatting (push) Successful in 6s
CI / Linting (push) Successful in 5s
CI / Tests (Python 3.12) (push) Successful in 2m55s
CI / Tests (Python 3.13) (push) Successful in 2m46s
CI / Tests (Python 3.14) (push) Successful in 2m42s
CI / Type Checking (push) Successful in 10s
CI / Spelling (push) Successful in 9s

This commit is contained in:
2026-04-24 16:57:11 -04:00
parent 44069793f8
commit f20faa317e
17 changed files with 7826 additions and 808 deletions
+333 -253
View File
@@ -67,18 +67,6 @@ class RecordingOwncastClient(_ClientBase):
"""The Owncast server base URL passed at construction."""
return self._base_url
async def get_status(self) -> dict[str, Any]:
"""Get the public server status."""
self.calls.append(RecordedCall("get_status", {}))
return {}
async def send_message(self, body: str, *, unsanitized: bool = False) -> str:
"""Send a chat message visible to all viewers."""
self.calls.append(
RecordedCall("send_message", {"body": body, "unsanitized": unsanitized})
)
return ""
async def send_system_message(self, body: str, *, unsanitized: bool = False) -> str:
"""Send a system message visible to all viewers."""
self.calls.append(
@@ -88,13 +76,6 @@ class RecordingOwncastClient(_ClientBase):
)
return ""
async def send_action(self, body: str, *, unsanitized: bool = False) -> str:
"""Send an action message (like IRC /me)."""
self.calls.append(
RecordedCall("send_action", {"body": body, "unsanitized": unsanitized})
)
return ""
async def send_system_message_to_client(
self, client_id: int, body: str, *, unsanitized: bool = False
) -> str:
@@ -107,6 +88,25 @@ class RecordingOwncastClient(_ClientBase):
)
return ""
async def send_user_message(self) -> str:
"""Send a chat message on behalf of a user (deprecated by Owncast)."""
self.calls.append(RecordedCall("send_user_message", {}))
return ""
async def send_message(self, body: str, *, unsanitized: bool = False) -> str:
"""Send a chat message visible to all viewers."""
self.calls.append(
RecordedCall("send_message", {"body": body, "unsanitized": unsanitized})
)
return ""
async def send_action(self, body: str, *, unsanitized: bool = False) -> str:
"""Send an action message (like IRC /me)."""
self.calls.append(
RecordedCall("send_action", {"body": body, "unsanitized": unsanitized})
)
return ""
async def set_message_visibility(
self, message_ids: list[str], *, visible: bool
) -> str:
@@ -119,6 +119,16 @@ class RecordingOwncastClient(_ClientBase):
)
return ""
async def get_status(self) -> dict[str, Any]:
"""Get the public server status."""
self.calls.append(RecordedCall("get_status", {}))
return {}
async def set_stream_title(self, title: str) -> str:
"""Update the stream title."""
self.calls.append(RecordedCall("set_stream_title", {"title": title}))
return ""
async def get_chat_history(self) -> list[dict[str, Any]]:
"""Fetch recent chat messages."""
self.calls.append(RecordedCall("get_chat_history", {}))
@@ -129,10 +139,10 @@ class RecordingOwncastClient(_ClientBase):
self.calls.append(RecordedCall("get_connected_clients", {}))
return []
async def set_stream_title(self, title: str) -> str:
"""Update the stream title."""
self.calls.append(RecordedCall("set_stream_title", {"title": title}))
return ""
async def get_user_details(self, user_id: str) -> dict[str, Any]:
"""Get moderation details for a chat user."""
self.calls.append(RecordedCall("get_user_details", {"user_id": user_id}))
return {}
class RecordingOwncastAdminClient(_AdminBase):
@@ -157,10 +167,15 @@ class RecordingOwncastAdminClient(_AdminBase):
self.calls.append(RecordedCall("get_status", {}))
return {}
async def get_active_viewers(self) -> list[dict[str, Any]]:
"""Get a list of currently active viewers."""
self.calls.append(RecordedCall("get_active_viewers", {}))
return []
async def disconnect_stream(self) -> dict[str, Any]:
"""Disconnect the current inbound stream."""
self.calls.append(RecordedCall("disconnect_stream", {}))
return {}
async def get_server_config(self) -> dict[str, Any]:
"""Get the full server configuration."""
self.calls.append(RecordedCall("get_server_config", {}))
return {}
async def get_viewers_over_time(self, window_start: int) -> list[dict[str, Any]]:
"""Get viewer count data over time for charting."""
@@ -169,34 +184,19 @@ class RecordingOwncastAdminClient(_AdminBase):
)
return []
async def get_active_viewers(self) -> list[dict[str, Any]]:
"""Get a list of currently active viewers."""
self.calls.append(RecordedCall("get_active_viewers", {}))
return []
async def get_hardware_stats(self) -> dict[str, Any]:
"""Get server hardware statistics (CPU, memory, disk)."""
self.calls.append(RecordedCall("get_hardware_stats", {}))
return {}
async def get_server_config(self) -> dict[str, Any]:
"""Get the full server configuration."""
self.calls.append(RecordedCall("get_server_config", {}))
return {}
async def disconnect_stream(self) -> dict[str, Any]:
"""Disconnect the current inbound stream."""
self.calls.append(RecordedCall("disconnect_stream", {}))
return {}
async def get_playback_metrics(self) -> dict[str, Any]:
"""Get playback quality metrics."""
self.calls.append(RecordedCall("get_playback_metrics", {}))
return {}
async def get_logs(self) -> list[dict[str, Any]]:
"""Get server logs."""
self.calls.append(RecordedCall("get_logs", {}))
return []
async def get_warnings(self) -> list[dict[str, Any]]:
"""Get server warning and error logs."""
self.calls.append(RecordedCall("get_warnings", {}))
async def get_connected_chat_clients(self) -> list[dict[str, Any]]:
"""Get currently connected chat clients."""
self.calls.append(RecordedCall("get_connected_chat_clients", {}))
return []
async def get_chat_messages(self) -> list[dict[str, Any]]:
@@ -204,11 +204,6 @@ class RecordingOwncastAdminClient(_AdminBase):
self.calls.append(RecordedCall("get_chat_messages", {}))
return []
async def get_connected_chat_clients(self) -> list[dict[str, Any]]:
"""Get currently connected chat clients."""
self.calls.append(RecordedCall("get_connected_chat_clients", {}))
return []
async def set_message_visibility(
self, message_ids: list[str], *, visible: bool
) -> str:
@@ -233,18 +228,6 @@ class RecordingOwncastAdminClient(_AdminBase):
self.calls.append(RecordedCall("get_disabled_users", {}))
return []
async def set_user_moderator(self, user_id: str, *, is_mod: bool) -> str:
"""Grant or revoke moderator status for a user."""
self.calls.append(
RecordedCall("set_user_moderator", {"user_id": user_id, "is_mod": is_mod})
)
return ""
async def get_moderators(self) -> list[dict[str, Any]]:
"""Get a list of moderator users."""
self.calls.append(RecordedCall("get_moderators", {}))
return []
async def ban_ip_address(self, ip: str) -> str:
"""Ban an IP address from chat."""
self.calls.append(RecordedCall("ban_ip_address", {"ip": ip}))
@@ -260,6 +243,84 @@ class RecordingOwncastAdminClient(_AdminBase):
self.calls.append(RecordedCall("get_ip_address_bans", {}))
return []
async def set_user_moderator(self, user_id: str, *, is_mod: bool) -> str:
"""Grant or revoke moderator status for a user."""
self.calls.append(
RecordedCall("set_user_moderator", {"user_id": user_id, "is_mod": is_mod})
)
return ""
async def get_moderators(self) -> list[dict[str, Any]]:
"""Get a list of moderator users."""
self.calls.append(RecordedCall("get_moderators", {}))
return []
async def get_logs(self) -> list[dict[str, Any]]:
"""Get server logs."""
self.calls.append(RecordedCall("get_logs", {}))
return []
async def get_warnings(self) -> list[dict[str, Any]]:
"""Get server warning and error logs."""
self.calls.append(RecordedCall("get_warnings", {}))
return []
async def get_followers(self, offset: int = 0, limit: int = 25) -> dict[str, Any]:
"""Get a paginated list of followers."""
self.calls.append(
RecordedCall("get_followers", {"offset": offset, "limit": limit})
)
return {}
async def get_pending_follow_requests(self) -> list[dict[str, Any]]:
"""Get pending follow requests."""
self.calls.append(RecordedCall("get_pending_follow_requests", {}))
return []
async def get_blocked_followers(self) -> list[dict[str, Any]]:
"""Get blocked and rejected followers."""
self.calls.append(RecordedCall("get_blocked_followers", {}))
return []
async def approve_follower(self, actor_iri: str, *, approved: bool) -> str:
"""Approve or reject a follow request."""
self.calls.append(
RecordedCall(
"approve_follower", {"actor_iri": actor_iri, "approved": approved}
)
)
return ""
async def upload_emoji(self, name: str, base64_data_url: str) -> str:
"""Upload a custom emoji."""
self.calls.append(
RecordedCall(
"upload_emoji",
{"name": name, "base64_data_url": base64_data_url},
)
)
return ""
async def delete_emoji(self, name: str) -> str:
"""Delete a custom emoji."""
self.calls.append(RecordedCall("delete_emoji", {"name": name}))
return ""
async def set_admin_password(self, password: str) -> str:
"""Change the admin password."""
self.calls.append(RecordedCall("set_admin_password", {"password": password}))
return ""
async def set_stream_keys(self, keys: list[StreamKey]) -> str:
"""Set the stream keys."""
self.calls.append(RecordedCall("set_stream_keys", {"keys": keys}))
return ""
async def set_page_content(self, content: str) -> str:
"""Set the custom page content (HTML/markdown below the player)."""
self.calls.append(RecordedCall("set_page_content", {"content": content}))
return ""
async def set_stream_title(self, title: str) -> str:
"""Set the stream title."""
self.calls.append(RecordedCall("set_stream_title", {"title": title}))
@@ -275,66 +336,14 @@ class RecordingOwncastAdminClient(_AdminBase):
self.calls.append(RecordedCall("set_server_summary", {"summary": summary}))
return ""
async def set_welcome_message(self, message: str) -> str:
"""Set the welcome message shown to new viewers."""
self.calls.append(RecordedCall("set_welcome_message", {"message": message}))
return ""
async def set_offline_message(self, message: str) -> str:
"""Set the message shown when the stream is offline."""
self.calls.append(RecordedCall("set_offline_message", {"message": message}))
return ""
async def set_page_content(self, content: str) -> str:
"""Set the custom page content (HTML/markdown below the player)."""
self.calls.append(RecordedCall("set_page_content", {"content": content}))
return ""
async def set_admin_password(self, password: str) -> str:
"""Change the admin password."""
self.calls.append(RecordedCall("set_admin_password", {"password": password}))
return ""
async def set_server_url(self, url: str) -> str:
"""Set the public server URL."""
self.calls.append(RecordedCall("set_server_url", {"url": url}))
return ""
async def set_logo(self, base64_data_url: str) -> str:
"""Set the server logo from a base64 data URL."""
self.calls.append(
RecordedCall("set_logo", {"base64_data_url": base64_data_url})
)
return ""
async def set_custom_styles(self, css: str) -> str:
"""Set custom CSS styles for the web interface."""
self.calls.append(RecordedCall("set_custom_styles", {"css": css}))
return ""
async def set_custom_javascript(self, js: str) -> str:
"""Set custom JavaScript for the web interface."""
self.calls.append(RecordedCall("set_custom_javascript", {"js": js}))
return ""
async def set_color_variables(self, variables: dict[str, Any]) -> str:
"""Set the custom color variables for the web interface."""
self.calls.append(RecordedCall("set_color_variables", {"variables": variables}))
return ""
async def set_tags(self, tags: list[str]) -> str:
"""Set the server tags."""
self.calls.append(RecordedCall("set_tags", {"tags": tags}))
return ""
async def set_social_handles(self, handles: list[SocialHandle]) -> str:
"""Set the social media handles displayed on the page."""
self.calls.append(RecordedCall("set_social_handles", {"handles": handles}))
return ""
async def set_external_actions(self, actions: list[ExternalAction]) -> str:
"""Set the external actions (buttons/links in the player)."""
self.calls.append(RecordedCall("set_external_actions", {"actions": actions}))
async def set_welcome_message(self, message: str) -> str:
"""Set the welcome message shown to new viewers."""
self.calls.append(RecordedCall("set_welcome_message", {"message": message}))
return ""
async def set_chat_disabled(self, *, disabled: bool) -> str:
@@ -356,6 +365,16 @@ class RecordingOwncastAdminClient(_AdminBase):
)
return ""
async def set_forbidden_usernames(self, names: list[str]) -> str:
"""Set the list of forbidden usernames."""
self.calls.append(RecordedCall("set_forbidden_usernames", {"names": names}))
return ""
async def set_suggested_usernames(self, names: list[str]) -> str:
"""Set the list of suggested usernames for new viewers."""
self.calls.append(RecordedCall("set_suggested_usernames", {"names": names}))
return ""
async def set_chat_spam_protection(self, *, enabled: bool) -> str:
"""Enable or disable chat spam protection."""
self.calls.append(
@@ -368,14 +387,87 @@ class RecordingOwncastAdminClient(_AdminBase):
self.calls.append(RecordedCall("set_chat_slur_filter", {"enabled": enabled}))
return ""
async def set_forbidden_usernames(self, names: list[str]) -> str:
"""Set the list of forbidden usernames."""
self.calls.append(RecordedCall("set_forbidden_usernames", {"names": names}))
async def set_chat_require_authentication(self, *, required: bool) -> str:
"""Require chat users to authenticate before sending messages."""
self.calls.append(
RecordedCall("set_chat_require_authentication", {"required": required})
)
return ""
async def set_suggested_usernames(self, names: list[str]) -> str:
"""Set the list of suggested usernames for new viewers."""
self.calls.append(RecordedCall("set_suggested_usernames", {"names": names}))
async def set_video_codec(self, codec: str) -> str:
"""Set the video codec."""
self.calls.append(RecordedCall("set_video_codec", {"codec": codec}))
return ""
async def set_stream_latency(self, level: int) -> str:
"""Set the stream latency level."""
self.calls.append(RecordedCall("set_stream_latency", {"level": level}))
return ""
async def set_video_variants(self, variants: list[VideoVariant]) -> str:
"""Set the video output variants (quality levels)."""
self.calls.append(RecordedCall("set_video_variants", {"variants": variants}))
return ""
async def set_color_variables(self, variables: dict[str, Any]) -> str:
"""Set the custom color variables for the web interface."""
self.calls.append(RecordedCall("set_color_variables", {"variables": variables}))
return ""
async def set_logo(self, base64_data_url: str) -> str:
"""Set the server logo from a base64 data URL."""
self.calls.append(
RecordedCall("set_logo", {"base64_data_url": base64_data_url})
)
return ""
async def set_favicon(self, base64_data_url: str) -> str:
"""Set a custom favicon from a base64 data URL."""
self.calls.append(
RecordedCall("set_favicon", {"base64_data_url": base64_data_url})
)
return ""
async def reset_favicon(self) -> str:
"""Reset the favicon to the Owncast default."""
self.calls.append(RecordedCall("reset_favicon", {}))
return ""
async def set_tags(self, tags: list[str]) -> str:
"""Set the server tags."""
self.calls.append(RecordedCall("set_tags", {"tags": tags}))
return ""
async def set_ffmpeg_path(self, path: str) -> str:
"""Set the path to the ffmpeg binary."""
self.calls.append(RecordedCall("set_ffmpeg_path", {"path": path}))
return ""
async def set_web_server_port(self, port: int) -> str:
"""Set the web server port."""
self.calls.append(RecordedCall("set_web_server_port", {"port": port}))
return ""
async def set_web_server_ip(self, ip: str) -> str:
"""Set the web server bind IP address."""
self.calls.append(RecordedCall("set_web_server_ip", {"ip": ip}))
return ""
async def set_rtmp_port(self, port: int) -> str:
"""Set the RTMP server port."""
self.calls.append(RecordedCall("set_rtmp_port", {"port": port}))
return ""
async def set_socket_host_override(self, host: str) -> str:
"""Set the WebSocket host override."""
self.calls.append(RecordedCall("set_socket_host_override", {"host": host}))
return ""
async def set_video_serving_endpoint(self, endpoint: str) -> str:
"""Set the video serving endpoint (e.g., for CDN)."""
self.calls.append(
RecordedCall("set_video_serving_endpoint", {"endpoint": endpoint})
)
return ""
async def set_nsfw(self, *, nsfw: bool) -> str:
@@ -388,68 +480,9 @@ class RecordingOwncastAdminClient(_AdminBase):
self.calls.append(RecordedCall("set_directory_enabled", {"enabled": enabled}))
return ""
async def set_hide_viewer_count(self, *, hide: bool) -> str:
"""Show or hide the viewer count."""
self.calls.append(RecordedCall("set_hide_viewer_count", {"hide": hide}))
return ""
async def set_disable_search_indexing(self, *, disabled: bool) -> str:
"""Enable or disable search engine indexing."""
self.calls.append(
RecordedCall("set_disable_search_indexing", {"disabled": disabled})
)
return ""
async def set_stream_keys(self, keys: list[StreamKey]) -> str:
"""Set the stream keys."""
self.calls.append(RecordedCall("set_stream_keys", {"keys": keys}))
return ""
async def set_video_variants(self, variants: list[VideoVariant]) -> str:
"""Set the video output variants (quality levels)."""
self.calls.append(RecordedCall("set_video_variants", {"variants": variants}))
return ""
async def set_video_codec(self, codec: str) -> str:
"""Set the video codec."""
self.calls.append(RecordedCall("set_video_codec", {"codec": codec}))
return ""
async def set_video_serving_endpoint(self, endpoint: str) -> str:
"""Set the video serving endpoint (e.g., for CDN)."""
self.calls.append(
RecordedCall("set_video_serving_endpoint", {"endpoint": endpoint})
)
return ""
async def set_stream_latency(self, level: int) -> str:
"""Set the stream latency level."""
self.calls.append(RecordedCall("set_stream_latency", {"level": level}))
return ""
async def set_ffmpeg_path(self, path: str) -> str:
"""Set the path to the ffmpeg binary."""
self.calls.append(RecordedCall("set_ffmpeg_path", {"path": path}))
return ""
async def set_socket_host_override(self, host: str) -> str:
"""Set the WebSocket host override."""
self.calls.append(RecordedCall("set_socket_host_override", {"host": host}))
return ""
async def set_rtmp_port(self, port: int) -> str:
"""Set the RTMP server port."""
self.calls.append(RecordedCall("set_rtmp_port", {"port": port}))
return ""
async def set_web_server_port(self, port: int) -> str:
"""Set the web server port."""
self.calls.append(RecordedCall("set_web_server_port", {"port": port}))
return ""
async def set_web_server_ip(self, ip: str) -> str:
"""Set the web server bind IP address."""
self.calls.append(RecordedCall("set_web_server_ip", {"ip": ip}))
async def set_social_handles(self, handles: list[SocialHandle]) -> str:
"""Set the social media handles displayed on the page."""
self.calls.append(RecordedCall("set_social_handles", {"handles": handles}))
return ""
async def set_s3_config(
@@ -478,6 +511,76 @@ class RecordingOwncastAdminClient(_AdminBase):
)
return ""
async def set_server_url(self, url: str) -> str:
"""Set the public server URL."""
self.calls.append(RecordedCall("set_server_url", {"url": url}))
return ""
async def set_external_actions(self, actions: list[ExternalAction]) -> str:
"""Set the external actions (buttons/links in the player)."""
self.calls.append(RecordedCall("set_external_actions", {"actions": actions}))
return ""
async def set_custom_styles(self, css: str) -> str:
"""Set custom CSS styles for the web interface."""
self.calls.append(RecordedCall("set_custom_styles", {"css": css}))
return ""
async def set_custom_javascript(self, js: str) -> str:
"""Set custom JavaScript for the web interface."""
self.calls.append(RecordedCall("set_custom_javascript", {"js": js}))
return ""
async def set_hide_viewer_count(self, *, hide: bool) -> str:
"""Show or hide the viewer count."""
self.calls.append(RecordedCall("set_hide_viewer_count", {"hide": hide}))
return ""
async def set_disable_search_indexing(self, *, disabled: bool) -> str:
"""Enable or disable search engine indexing."""
self.calls.append(
RecordedCall("set_disable_search_indexing", {"disabled": disabled})
)
return ""
async def set_federation_enabled(self, *, enabled: bool) -> str:
"""Enable or disable federation (ActivityPub)."""
self.calls.append(RecordedCall("set_federation_enabled", {"enabled": enabled}))
return ""
async def set_federation_activity_private(self, *, private: bool) -> str:
"""Mark federated activity as private (followers-only)."""
self.calls.append(
RecordedCall("set_federation_activity_private", {"private": private})
)
return ""
async def set_federation_show_engagement(self, *, enabled: bool) -> str:
"""Show or hide federated engagement (likes, boosts) in chat."""
self.calls.append(
RecordedCall("set_federation_show_engagement", {"enabled": enabled})
)
return ""
async def set_federation_username(self, name: str) -> str:
"""Set the federation (ActivityPub) username."""
self.calls.append(RecordedCall("set_federation_username", {"name": name}))
return ""
async def set_federation_go_live_message(self, message: str) -> str:
"""Set the message sent to followers when going live."""
self.calls.append(
RecordedCall("set_federation_go_live_message", {"message": message})
)
return ""
async def set_federation_blocked_domains(self, domains: list[str]) -> str:
"""Set the list of blocked federation domains."""
self.calls.append(
RecordedCall("set_federation_blocked_domains", {"domains": domains})
)
return ""
async def set_discord_notifications(
self, *, enabled: bool, webhook: str, go_live_message: str
) -> str:
@@ -506,23 +609,16 @@ class RecordingOwncastAdminClient(_AdminBase):
)
return ""
async def upload_emoji(self, name: str, data_base64: str) -> str:
"""Upload a custom emoji."""
self.calls.append(
RecordedCall("upload_emoji", {"name": name, "data_base64": data_base64})
)
return ""
async def delete_emoji(self, name: str) -> str:
"""Delete a custom emoji."""
self.calls.append(RecordedCall("delete_emoji", {"name": name}))
return ""
async def get_webhooks(self) -> list[dict[str, Any]]:
"""Get all registered webhooks."""
self.calls.append(RecordedCall("get_webhooks", {}))
return []
async def delete_webhook(self, webhook_id: int) -> str:
"""Delete a webhook."""
self.calls.append(RecordedCall("delete_webhook", {"webhook_id": webhook_id}))
return ""
async def create_webhook(self, url: str, events: list[str]) -> str:
"""Create a new webhook."""
self.calls.append(
@@ -530,16 +626,16 @@ class RecordingOwncastAdminClient(_AdminBase):
)
return ""
async def delete_webhook(self, webhook_id: int) -> str:
"""Delete a webhook."""
self.calls.append(RecordedCall("delete_webhook", {"webhook_id": webhook_id}))
return ""
async def get_access_tokens(self) -> list[dict[str, Any]]:
"""Get all access tokens."""
self.calls.append(RecordedCall("get_access_tokens", {}))
return []
async def delete_access_token(self, token: str) -> str:
"""Delete an access token."""
self.calls.append(RecordedCall("delete_access_token", {"token": token}))
return ""
async def create_access_token(self, name: str, scopes: list[str]) -> str:
"""Create a new access token."""
self.calls.append(
@@ -547,35 +643,34 @@ class RecordingOwncastAdminClient(_AdminBase):
)
return ""
async def delete_access_token(self, token: str) -> str:
"""Delete an access token."""
self.calls.append(RecordedCall("delete_access_token", {"token": token}))
return ""
async def get_followers(self, offset: int = 0, limit: int = 25) -> dict[str, Any]:
"""Get a paginated list of followers."""
self.calls.append(
RecordedCall("get_followers", {"offset": offset, "limit": limit})
)
async def reset_yp_registration(self) -> dict[str, Any]:
"""Clear the YP (Owncast directory) registration key."""
self.calls.append(RecordedCall("reset_yp_registration", {}))
return {}
async def get_pending_follow_requests(self) -> list[dict[str, Any]]:
"""Get pending follow requests."""
self.calls.append(RecordedCall("get_pending_follow_requests", {}))
return []
async def get_playback_metrics(self) -> dict[str, Any]:
"""Get playback quality metrics."""
self.calls.append(RecordedCall("get_playback_metrics", {}))
return {}
async def get_blocked_followers(self) -> list[dict[str, Any]]:
"""Get blocked and rejected followers."""
self.calls.append(RecordedCall("get_blocked_followers", {}))
return []
async def get_prometheus_metrics(self) -> str:
"""Fetch metrics from the Owncast-proxied Prometheus endpoint."""
self.calls.append(RecordedCall("get_prometheus_metrics", {}))
return ""
async def approve_follower(self, actor_iri: str, *, approved: bool) -> str:
"""Approve or reject a follow request."""
self.calls.append(
RecordedCall(
"approve_follower", {"actor_iri": actor_iri, "approved": approved}
)
)
async def post_prometheus(self, data: dict[str, Any] | None = None) -> str:
"""POST to the Owncast-proxied Prometheus endpoint."""
self.calls.append(RecordedCall("post_prometheus", {"data": data}))
return ""
async def put_prometheus(self, data: dict[str, Any] | None = None) -> str:
"""PUT to the Owncast-proxied Prometheus endpoint."""
self.calls.append(RecordedCall("put_prometheus", {"data": data}))
return ""
async def delete_prometheus(self) -> str:
"""DELETE on the Owncast-proxied Prometheus endpoint."""
self.calls.append(RecordedCall("delete_prometheus", {}))
return ""
async def send_federated_message(self, message: str) -> str:
@@ -583,26 +678,11 @@ class RecordingOwncastAdminClient(_AdminBase):
self.calls.append(RecordedCall("send_federated_message", {"message": message}))
return ""
async def set_federation_enabled(self, *, enabled: bool) -> str:
"""Enable or disable federation (ActivityPub)."""
self.calls.append(RecordedCall("set_federation_enabled", {"enabled": enabled}))
return ""
async def set_federation_username(self, name: str) -> str:
"""Set the federation (ActivityPub) username."""
self.calls.append(RecordedCall("set_federation_username", {"name": name}))
return ""
async def set_federation_go_live_message(self, message: str) -> str:
"""Set the message sent to followers when going live."""
async def get_federated_actions(
self, offset: int = 0, limit: int = 25
) -> dict[str, Any]:
"""Get a paginated list of accepted inbound federated activities."""
self.calls.append(
RecordedCall("set_federation_go_live_message", {"message": message})
RecordedCall("get_federated_actions", {"offset": offset, "limit": limit})
)
return ""
async def set_federation_blocked_domains(self, domains: list[str]) -> str:
"""Set the list of blocked federation domains."""
self.calls.append(
RecordedCall("set_federation_blocked_domains", {"domains": domains})
)
return ""
return {}