From 5acbcaf0b4b1e77f9d2fd70e89df81c24a2050d3 Mon Sep 17 00:00:00 2001 From: activitysmith-bot Date: Tue, 15 Sep 2026 12:49:05 +0000 Subject: [PATCH 01/12] chore: regenerate SDK --- activitysmith_openapi/__init__.py | 9 + activitysmith_openapi/api/__init__.py | 1 + .../api/app_icon_badges_api.py | 9 +- activitysmith_openapi/api/public_api.py | 563 ++++++++++++++++++ activitysmith_openapi/configuration.py | 7 + .../docs/AppIconBadgeCountUpdateError.md | 37 ++ .../docs/AppIconBadgeCountUpdateResponse.md | 6 +- .../docs/AppIconBadgesApi.md | 3 +- activitysmith_openapi/docs/ChangelogEntry.md | 37 ++ activitysmith_openapi/docs/ChangelogItem.md | 33 + .../docs/ChangelogListResponse.md | 29 + activitysmith_openapi/docs/HealthCheck.md | 31 + activitysmith_openapi/docs/HealthResponse.md | 32 + .../docs/LiveActivityEndRequest.md | 2 + .../docs/LiveActivityLimitError.md | 4 +- .../docs/LiveActivityStartRequest.md | 1 + .../docs/LiveActivityStreamDeleteRequest.md | 2 + .../docs/LiveActivityStreamRequest.md | 1 + .../docs/LiveActivityUpdateRequest.md | 2 + activitysmith_openapi/docs/MetadataValue.md | 28 + activitysmith_openapi/docs/PublicApi.md | 145 +++++ .../docs/PushNotificationAction.md | 2 +- .../docs/PushNotificationRequest.md | 3 +- .../docs/SendPushNotification429Response.md | 4 +- .../UpdateAppIconBadgeCount422Response.md | 37 ++ activitysmith_openapi/models/__init__.py | 8 + .../app_icon_badge_count_update_error.py | 111 ++++ .../app_icon_badge_count_update_response.py | 12 +- .../models/changelog_entry.py | 127 ++++ .../models/changelog_item.py | 110 ++++ .../models/changelog_list_response.py | 95 +++ activitysmith_openapi/models/health_check.py | 106 ++++ .../models/health_response.py | 102 ++++ .../models/live_activity_end_request.py | 20 +- .../models/live_activity_limit_error.py | 12 +- .../models/live_activity_start_request.py | 17 +- .../live_activity_stream_delete_request.py | 22 +- .../models/live_activity_stream_request.py | 17 +- .../models/live_activity_update_request.py | 20 +- .../models/metadata_value.py | 161 +++++ .../models/push_notification_action.py | 2 +- .../models/push_notification_request.py | 23 +- ...update_app_icon_badge_count422_response.py | 137 +++++ activitysmith_openapi/openapi-source.json | 6 + .../test_app_icon_badge_count_update_error.py | 66 ++ ...st_app_icon_badge_count_update_response.py | 6 +- .../test/test_changelog_entry.py | 82 +++ .../test/test_changelog_item.py | 57 ++ .../test/test_changelog_list_response.py | 88 +++ .../test/test_health_check.py | 56 ++ .../test/test_health_response.py | 68 +++ .../test/test_live_activity_end_request.py | 6 + .../test/test_live_activity_limit_error.py | 4 +- .../test/test_live_activity_start_request.py | 3 + ...est_live_activity_stream_delete_request.py | 6 + .../test/test_live_activity_stream_request.py | 3 + .../test/test_live_activity_update_request.py | 6 + .../test/test_metadata_value.py | 50 ++ activitysmith_openapi/test/test_public_api.py | 45 ++ .../test/test_push_notification_request.py | 5 +- ...test_send_push_notification429_response.py | 4 +- ...update_app_icon_badge_count422_response.py | 66 ++ 62 files changed, 2723 insertions(+), 34 deletions(-) create mode 100644 activitysmith_openapi/api/public_api.py create mode 100644 activitysmith_openapi/docs/AppIconBadgeCountUpdateError.md create mode 100644 activitysmith_openapi/docs/ChangelogEntry.md create mode 100644 activitysmith_openapi/docs/ChangelogItem.md create mode 100644 activitysmith_openapi/docs/ChangelogListResponse.md create mode 100644 activitysmith_openapi/docs/HealthCheck.md create mode 100644 activitysmith_openapi/docs/HealthResponse.md create mode 100644 activitysmith_openapi/docs/MetadataValue.md create mode 100644 activitysmith_openapi/docs/PublicApi.md create mode 100644 activitysmith_openapi/docs/UpdateAppIconBadgeCount422Response.md create mode 100644 activitysmith_openapi/models/app_icon_badge_count_update_error.py create mode 100644 activitysmith_openapi/models/changelog_entry.py create mode 100644 activitysmith_openapi/models/changelog_item.py create mode 100644 activitysmith_openapi/models/changelog_list_response.py create mode 100644 activitysmith_openapi/models/health_check.py create mode 100644 activitysmith_openapi/models/health_response.py create mode 100644 activitysmith_openapi/models/metadata_value.py create mode 100644 activitysmith_openapi/models/update_app_icon_badge_count422_response.py create mode 100644 activitysmith_openapi/openapi-source.json create mode 100644 activitysmith_openapi/test/test_app_icon_badge_count_update_error.py create mode 100644 activitysmith_openapi/test/test_changelog_entry.py create mode 100644 activitysmith_openapi/test/test_changelog_item.py create mode 100644 activitysmith_openapi/test/test_changelog_list_response.py create mode 100644 activitysmith_openapi/test/test_health_check.py create mode 100644 activitysmith_openapi/test/test_health_response.py create mode 100644 activitysmith_openapi/test/test_metadata_value.py create mode 100644 activitysmith_openapi/test/test_public_api.py create mode 100644 activitysmith_openapi/test/test_update_app_icon_badge_count422_response.py diff --git a/activitysmith_openapi/__init__.py b/activitysmith_openapi/__init__.py index 6c01606..e456db2 100644 --- a/activitysmith_openapi/__init__.py +++ b/activitysmith_openapi/__init__.py @@ -20,6 +20,7 @@ from activitysmith_openapi.api.app_icon_badges_api import AppIconBadgesApi from activitysmith_openapi.api.live_activities_api import LiveActivitiesApi from activitysmith_openapi.api.metrics_api import MetricsApi +from activitysmith_openapi.api.public_api import PublicApi from activitysmith_openapi.api.push_notifications_api import PushNotificationsApi # import ApiClient @@ -37,14 +38,20 @@ from activitysmith_openapi.models.activity_metric import ActivityMetric from activitysmith_openapi.models.activity_metric_value import ActivityMetricValue from activitysmith_openapi.models.alert_payload import AlertPayload +from activitysmith_openapi.models.app_icon_badge_count_update_error import AppIconBadgeCountUpdateError from activitysmith_openapi.models.app_icon_badge_count_update_request import AppIconBadgeCountUpdateRequest from activitysmith_openapi.models.app_icon_badge_count_update_response import AppIconBadgeCountUpdateResponse from activitysmith_openapi.models.bad_request_error import BadRequestError +from activitysmith_openapi.models.changelog_entry import ChangelogEntry +from activitysmith_openapi.models.changelog_item import ChangelogItem +from activitysmith_openapi.models.changelog_list_response import ChangelogListResponse from activitysmith_openapi.models.channel_target import ChannelTarget from activitysmith_openapi.models.content_state_end import ContentStateEnd from activitysmith_openapi.models.content_state_start import ContentStateStart from activitysmith_openapi.models.content_state_update import ContentStateUpdate from activitysmith_openapi.models.forbidden_error import ForbiddenError +from activitysmith_openapi.models.health_check import HealthCheck +from activitysmith_openapi.models.health_response import HealthResponse from activitysmith_openapi.models.live_activity_action import LiveActivityAction from activitysmith_openapi.models.live_activity_action_type import LiveActivityActionType from activitysmith_openapi.models.live_activity_alert_badge import LiveActivityAlertBadge @@ -62,6 +69,7 @@ from activitysmith_openapi.models.live_activity_update_request import LiveActivityUpdateRequest from activitysmith_openapi.models.live_activity_update_response import LiveActivityUpdateResponse from activitysmith_openapi.models.live_activity_webhook_method import LiveActivityWebhookMethod +from activitysmith_openapi.models.metadata_value import MetadataValue from activitysmith_openapi.models.metric_error import MetricError from activitysmith_openapi.models.metric_value_update_request import MetricValueUpdateRequest from activitysmith_openapi.models.metric_value_update_request_value import MetricValueUpdateRequestValue @@ -76,3 +84,4 @@ from activitysmith_openapi.models.rate_limit_error import RateLimitError from activitysmith_openapi.models.send_push_notification429_response import SendPushNotification429Response from activitysmith_openapi.models.stream_content_state import StreamContentState +from activitysmith_openapi.models.update_app_icon_badge_count422_response import UpdateAppIconBadgeCount422Response diff --git a/activitysmith_openapi/api/__init__.py b/activitysmith_openapi/api/__init__.py index f70481e..3f9116e 100644 --- a/activitysmith_openapi/api/__init__.py +++ b/activitysmith_openapi/api/__init__.py @@ -4,5 +4,6 @@ from activitysmith_openapi.api.app_icon_badges_api import AppIconBadgesApi from activitysmith_openapi.api.live_activities_api import LiveActivitiesApi from activitysmith_openapi.api.metrics_api import MetricsApi +from activitysmith_openapi.api.public_api import PublicApi from activitysmith_openapi.api.push_notifications_api import PushNotificationsApi diff --git a/activitysmith_openapi/api/app_icon_badges_api.py b/activitysmith_openapi/api/app_icon_badges_api.py index 29d22f6..e832526 100644 --- a/activitysmith_openapi/api/app_icon_badges_api.py +++ b/activitysmith_openapi/api/app_icon_badges_api.py @@ -94,7 +94,8 @@ def update_app_icon_badge_count( '200': "AppIconBadgeCountUpdateResponse", '400': "BadRequestError", '403': "ForbiddenError", - '404': "NoRecipientsError", + '422': "UpdateAppIconBadgeCount422Response", + '502': "AppIconBadgeCountUpdateError", '429': "RateLimitError", } response_data = self.api_client.call_api( @@ -165,7 +166,8 @@ def update_app_icon_badge_count_with_http_info( '200': "AppIconBadgeCountUpdateResponse", '400': "BadRequestError", '403': "ForbiddenError", - '404': "NoRecipientsError", + '422': "UpdateAppIconBadgeCount422Response", + '502': "AppIconBadgeCountUpdateError", '429': "RateLimitError", } response_data = self.api_client.call_api( @@ -236,7 +238,8 @@ def update_app_icon_badge_count_without_preload_content( '200': "AppIconBadgeCountUpdateResponse", '400': "BadRequestError", '403': "ForbiddenError", - '404': "NoRecipientsError", + '422': "UpdateAppIconBadgeCount422Response", + '502': "AppIconBadgeCountUpdateError", '429': "RateLimitError", } response_data = self.api_client.call_api( diff --git a/activitysmith_openapi/api/public_api.py b/activitysmith_openapi/api/public_api.py new file mode 100644 index 0000000..8749681 --- /dev/null +++ b/activitysmith_openapi/api/public_api.py @@ -0,0 +1,563 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import Field, StrictStr +from typing import Optional +from typing_extensions import Annotated +from activitysmith_openapi.models.changelog_list_response import ChangelogListResponse +from activitysmith_openapi.models.health_response import HealthResponse + +from activitysmith_openapi.api_client import ApiClient, RequestSerialized +from activitysmith_openapi.api_response import ApiResponse +from activitysmith_openapi.rest import RESTResponseType + + +class PublicApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def get_api_health( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> HealthResponse: + """Get API Health + + Returns the current availability of the ActivitySmith API and its required services. No authentication is required. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_api_health_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "HealthResponse", + '503': "HealthResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def get_api_health_with_http_info( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[HealthResponse]: + """Get API Health + + Returns the current availability of the ActivitySmith API and its required services. No authentication is required. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_api_health_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "HealthResponse", + '503': "HealthResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def get_api_health_without_preload_content( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Get API Health + + Returns the current availability of the ActivitySmith API and its required services. No authentication is required. + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_api_health_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "HealthResponse", + '503': "HealthResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_api_health_serialize( + self, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[str, Union[str, bytes]] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/health', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def list_public_changelog_entries( + self, + platform: Annotated[Optional[StrictStr], Field(description="Platform whose published changelog entries should be returned.")] = None, + limit: Annotated[Optional[Annotated[int, Field(le=20, strict=True, ge=1)]], Field(description="Maximum number of entries to return.")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ChangelogListResponse: + """List Public Changelog Entries + + Returns published ActivitySmith app changelog entries. No authentication is required. + + :param platform: Platform whose published changelog entries should be returned. + :type platform: str + :param limit: Maximum number of entries to return. + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_public_changelog_entries_serialize( + platform=platform, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ChangelogListResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def list_public_changelog_entries_with_http_info( + self, + platform: Annotated[Optional[StrictStr], Field(description="Platform whose published changelog entries should be returned.")] = None, + limit: Annotated[Optional[Annotated[int, Field(le=20, strict=True, ge=1)]], Field(description="Maximum number of entries to return.")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[ChangelogListResponse]: + """List Public Changelog Entries + + Returns published ActivitySmith app changelog entries. No authentication is required. + + :param platform: Platform whose published changelog entries should be returned. + :type platform: str + :param limit: Maximum number of entries to return. + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_public_changelog_entries_serialize( + platform=platform, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ChangelogListResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def list_public_changelog_entries_without_preload_content( + self, + platform: Annotated[Optional[StrictStr], Field(description="Platform whose published changelog entries should be returned.")] = None, + limit: Annotated[Optional[Annotated[int, Field(le=20, strict=True, ge=1)]], Field(description="Maximum number of entries to return.")] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """List Public Changelog Entries + + Returns published ActivitySmith app changelog entries. No authentication is required. + + :param platform: Platform whose published changelog entries should be returned. + :type platform: str + :param limit: Maximum number of entries to return. + :type limit: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_public_changelog_entries_serialize( + platform=platform, + limit=limit, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "ChangelogListResponse", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_public_changelog_entries_serialize( + self, + platform, + limit, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[str, Union[str, bytes]] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if platform is not None: + + _query_params.append(('platform', platform)) + + if limit is not None: + + _query_params.append(('limit', limit)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/changelog', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/activitysmith_openapi/configuration.py b/activitysmith_openapi/configuration.py index 4d3acda..28e3460 100644 --- a/activitysmith_openapi/configuration.py +++ b/activitysmith_openapi/configuration.py @@ -382,6 +382,13 @@ def auth_settings(self): 'key': 'Authorization', 'value': 'Bearer ' + self.access_token } + if self.access_token is not None: + auth['mcpOAuth'] = { + 'type': 'oauth2', + 'in': 'header', + 'key': 'Authorization', + 'value': 'Bearer ' + self.access_token + } return auth def to_debug_report(self): diff --git a/activitysmith_openapi/docs/AppIconBadgeCountUpdateError.md b/activitysmith_openapi/docs/AppIconBadgeCountUpdateError.md new file mode 100644 index 0000000..8aec0cf --- /dev/null +++ b/activitysmith_openapi/docs/AppIconBadgeCountUpdateError.md @@ -0,0 +1,37 @@ +# AppIconBadgeCountUpdateError + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**error** | **str** | | +**code** | **str** | | +**message** | **str** | | +**badge** | **int** | | +**devices_targeted** | **int** | | [optional] +**devices_updated** | **int** | | +**users_updated** | **int** | | [optional] +**devices_notified** | **int** | Deprecated compatibility alias for devices_updated. | [optional] +**effective_channel_slugs** | **List[str]** | | [optional] + +## Example + +```python +from activitysmith_openapi.models.app_icon_badge_count_update_error import AppIconBadgeCountUpdateError + +# TODO update the JSON string below +json = "{}" +# create an instance of AppIconBadgeCountUpdateError from a JSON string +app_icon_badge_count_update_error_instance = AppIconBadgeCountUpdateError.from_json(json) +# print the JSON string representation of the object +print(AppIconBadgeCountUpdateError.to_json()) + +# convert the object into a dict +app_icon_badge_count_update_error_dict = app_icon_badge_count_update_error_instance.to_dict() +# create an instance of AppIconBadgeCountUpdateError from a dict +app_icon_badge_count_update_error_from_dict = AppIconBadgeCountUpdateError.from_dict(app_icon_badge_count_update_error_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/activitysmith_openapi/docs/AppIconBadgeCountUpdateResponse.md b/activitysmith_openapi/docs/AppIconBadgeCountUpdateResponse.md index 74dd986..072e90e 100644 --- a/activitysmith_openapi/docs/AppIconBadgeCountUpdateResponse.md +++ b/activitysmith_openapi/docs/AppIconBadgeCountUpdateResponse.md @@ -7,8 +7,10 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **success** | **bool** | | **badge** | **int** | | -**devices_notified** | **int** | | -**users_notified** | **int** | | +**devices_updated** | **int** | Number of devices whose App Icon Badge Count was updated. | +**users_updated** | **int** | Number of account users with at least one updated device. | +**devices_notified** | **int** | Deprecated compatibility alias for devices_updated. | [optional] +**users_notified** | **int** | Deprecated compatibility alias for users_updated. | [optional] **effective_channel_slugs** | **List[str]** | | **timestamp** | **datetime** | | diff --git a/activitysmith_openapi/docs/AppIconBadgesApi.md b/activitysmith_openapi/docs/AppIconBadgesApi.md index 6ae3264..76505cf 100644 --- a/activitysmith_openapi/docs/AppIconBadgesApi.md +++ b/activitysmith_openapi/docs/AppIconBadgesApi.md @@ -85,7 +85,8 @@ Name | Type | Description | Notes **200** | App Icon Badge Count updated | - | **400** | Bad request | - | **403** | Forbidden | - | -**404** | No recipients found for effective channel target | - | +**422** | No matching devices found, or a targeted device needs to reconnect | - | +**502** | App Icon Badge Count could not be updated | - | **429** | Rate limit exceeded | - | [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) diff --git a/activitysmith_openapi/docs/ChangelogEntry.md b/activitysmith_openapi/docs/ChangelogEntry.md new file mode 100644 index 0000000..57c121d --- /dev/null +++ b/activitysmith_openapi/docs/ChangelogEntry.md @@ -0,0 +1,37 @@ +# ChangelogEntry + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **str** | | +**platform** | **str** | | +**version** | **str** | | +**title** | **str** | | +**subtitle** | **str** | | +**hero_image_url** | **str** | | +**cta_title** | **str** | | +**published_at** | **datetime** | | +**items** | [**List[ChangelogItem]**](ChangelogItem.md) | | + +## Example + +```python +from activitysmith_openapi.models.changelog_entry import ChangelogEntry + +# TODO update the JSON string below +json = "{}" +# create an instance of ChangelogEntry from a JSON string +changelog_entry_instance = ChangelogEntry.from_json(json) +# print the JSON string representation of the object +print(ChangelogEntry.to_json()) + +# convert the object into a dict +changelog_entry_dict = changelog_entry_instance.to_dict() +# create an instance of ChangelogEntry from a dict +changelog_entry_from_dict = ChangelogEntry.from_dict(changelog_entry_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/activitysmith_openapi/docs/ChangelogItem.md b/activitysmith_openapi/docs/ChangelogItem.md new file mode 100644 index 0000000..7610a15 --- /dev/null +++ b/activitysmith_openapi/docs/ChangelogItem.md @@ -0,0 +1,33 @@ +# ChangelogItem + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**icon** | **str** | | [optional] +**title** | **str** | | +**body** | **str** | | +**image_url** | **str** | | [optional] +**accent_color** | **str** | | [optional] + +## Example + +```python +from activitysmith_openapi.models.changelog_item import ChangelogItem + +# TODO update the JSON string below +json = "{}" +# create an instance of ChangelogItem from a JSON string +changelog_item_instance = ChangelogItem.from_json(json) +# print the JSON string representation of the object +print(ChangelogItem.to_json()) + +# convert the object into a dict +changelog_item_dict = changelog_item_instance.to_dict() +# create an instance of ChangelogItem from a dict +changelog_item_from_dict = ChangelogItem.from_dict(changelog_item_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/activitysmith_openapi/docs/ChangelogListResponse.md b/activitysmith_openapi/docs/ChangelogListResponse.md new file mode 100644 index 0000000..a7f3bab --- /dev/null +++ b/activitysmith_openapi/docs/ChangelogListResponse.md @@ -0,0 +1,29 @@ +# ChangelogListResponse + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**changelogs** | [**List[ChangelogEntry]**](ChangelogEntry.md) | | + +## Example + +```python +from activitysmith_openapi.models.changelog_list_response import ChangelogListResponse + +# TODO update the JSON string below +json = "{}" +# create an instance of ChangelogListResponse from a JSON string +changelog_list_response_instance = ChangelogListResponse.from_json(json) +# print the JSON string representation of the object +print(ChangelogListResponse.to_json()) + +# convert the object into a dict +changelog_list_response_dict = changelog_list_response_instance.to_dict() +# create an instance of ChangelogListResponse from a dict +changelog_list_response_from_dict = ChangelogListResponse.from_dict(changelog_list_response_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/activitysmith_openapi/docs/HealthCheck.md b/activitysmith_openapi/docs/HealthCheck.md new file mode 100644 index 0000000..d96fb1c --- /dev/null +++ b/activitysmith_openapi/docs/HealthCheck.md @@ -0,0 +1,31 @@ +# HealthCheck + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**name** | **str** | | +**status** | **str** | | +**duration_ms** | **int** | | + +## Example + +```python +from activitysmith_openapi.models.health_check import HealthCheck + +# TODO update the JSON string below +json = "{}" +# create an instance of HealthCheck from a JSON string +health_check_instance = HealthCheck.from_json(json) +# print the JSON string representation of the object +print(HealthCheck.to_json()) + +# convert the object into a dict +health_check_dict = health_check_instance.to_dict() +# create an instance of HealthCheck from a dict +health_check_from_dict = HealthCheck.from_dict(health_check_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/activitysmith_openapi/docs/HealthResponse.md b/activitysmith_openapi/docs/HealthResponse.md new file mode 100644 index 0000000..7704fca --- /dev/null +++ b/activitysmith_openapi/docs/HealthResponse.md @@ -0,0 +1,32 @@ +# HealthResponse + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**ok** | **bool** | | +**service** | **str** | | +**timestamp** | **datetime** | | +**checks** | [**List[HealthCheck]**](HealthCheck.md) | | + +## Example + +```python +from activitysmith_openapi.models.health_response import HealthResponse + +# TODO update the JSON string below +json = "{}" +# create an instance of HealthResponse from a JSON string +health_response_instance = HealthResponse.from_json(json) +# print the JSON string representation of the object +print(HealthResponse.to_json()) + +# convert the object into a dict +health_response_dict = health_response_instance.to_dict() +# create an instance of HealthResponse from a dict +health_response_from_dict = HealthResponse.from_dict(health_response_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/activitysmith_openapi/docs/LiveActivityEndRequest.md b/activitysmith_openapi/docs/LiveActivityEndRequest.md index 94f4fa6..c723061 100644 --- a/activitysmith_openapi/docs/LiveActivityEndRequest.md +++ b/activitysmith_openapi/docs/LiveActivityEndRequest.md @@ -6,7 +6,9 @@ End an existing Live Activity by activity_id. Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**metadata** | [**Dict[str, MetadataValue]**](MetadataValue.md) | Additional information shown in notification and Live Activity details in ActivitySmith. Not displayed in the Push Notification or Live Activity on the device. Values must be strings, finite numbers, or booleans. At most 50 entries and 16 KB of serialized UTF-8 JSON. Omit on updates to preserve existing Metadata; send {} to clear it. | [optional] **activity_id** | **str** | | +**tags** | **List[str]** | Tags for notification history. Omit to keep existing Tags, supply an array to replace them, or send an empty array to clear them. | [optional] **content_state** | [**ContentStateEnd**](ContentStateEnd.md) | | **action** | [**LiveActivityAction**](LiveActivityAction.md) | | [optional] **secondary_action** | [**LiveActivityAction**](LiveActivityAction.md) | Optional secondary action button. Supported for alert, progress, and segmented_progress Live Activities. Uses the same open_url, shortcuts://, and webhook shapes as action. | [optional] diff --git a/activitysmith_openapi/docs/LiveActivityLimitError.md b/activitysmith_openapi/docs/LiveActivityLimitError.md index d661fc6..25cb51a 100644 --- a/activitysmith_openapi/docs/LiveActivityLimitError.md +++ b/activitysmith_openapi/docs/LiveActivityLimitError.md @@ -8,7 +8,9 @@ Name | Type | Description | Notes **error** | **str** | | **message** | **str** | | **limit** | **int** | | -**active** | **int** | Current number of active Live Activities. | +**active** | **int** | Highest number of active Live Activities among the targeted devices. | +**blocked_devices** | **int** | Number of targeted devices that have reached the enforced iOS Live Activity concurrency threshold. Included only when targeted devices have mixed capacity. | [optional] +**targeted_devices** | **int** | Total number of targeted devices. Included only when targeted devices have mixed capacity. | [optional] ## Example diff --git a/activitysmith_openapi/docs/LiveActivityStartRequest.md b/activitysmith_openapi/docs/LiveActivityStartRequest.md index 914e655..f8b8e7d 100644 --- a/activitysmith_openapi/docs/LiveActivityStartRequest.md +++ b/activitysmith_openapi/docs/LiveActivityStartRequest.md @@ -6,6 +6,7 @@ Start a new Live Activity. The response includes activity_id for later update an Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**metadata** | [**Dict[str, MetadataValue]**](MetadataValue.md) | Additional information shown in notification and Live Activity details in ActivitySmith. Not displayed in the Push Notification or Live Activity on the device. Values must be strings, finite numbers, or booleans. At most 50 entries and 16 KB of serialized UTF-8 JSON. Omit on updates to preserve existing Metadata; send {} to clear it. | [optional] **content_state** | [**ContentStateStart**](ContentStateStart.md) | | **action** | [**LiveActivityAction**](LiveActivityAction.md) | | [optional] **secondary_action** | [**LiveActivityAction**](LiveActivityAction.md) | Optional secondary action button. Supported for alert, progress, and segmented_progress Live Activities. Uses the same open_url, shortcuts://, and webhook shapes as action. | [optional] diff --git a/activitysmith_openapi/docs/LiveActivityStreamDeleteRequest.md b/activitysmith_openapi/docs/LiveActivityStreamDeleteRequest.md index bde073d..d1d068a 100644 --- a/activitysmith_openapi/docs/LiveActivityStreamDeleteRequest.md +++ b/activitysmith_openapi/docs/LiveActivityStreamDeleteRequest.md @@ -6,6 +6,8 @@ Optional payload for ending a managed stream. When omitted, ActivitySmith ends t Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**metadata** | [**Dict[str, MetadataValue]**](MetadataValue.md) | Additional information shown in notification and Live Activity details in ActivitySmith. Not displayed in the Push Notification or Live Activity on the device. Values must be strings, finite numbers, or booleans. At most 50 entries and 16 KB of serialized UTF-8 JSON. Omit on updates to preserve existing Metadata; send {} to clear it. | [optional] +**tags** | **List[str]** | Optional tags to organize and filter notification history. | [optional] **content_state** | [**StreamContentState**](StreamContentState.md) | | [optional] **action** | [**LiveActivityAction**](LiveActivityAction.md) | | [optional] **secondary_action** | [**LiveActivityAction**](LiveActivityAction.md) | Optional secondary action button. Supported for alert, progress, and segmented_progress Live Activities. Uses the same open_url, shortcuts://, and webhook shapes as action. | [optional] diff --git a/activitysmith_openapi/docs/LiveActivityStreamRequest.md b/activitysmith_openapi/docs/LiveActivityStreamRequest.md index 2aba012..2df7c2a 100644 --- a/activitysmith_openapi/docs/LiveActivityStreamRequest.md +++ b/activitysmith_openapi/docs/LiveActivityStreamRequest.md @@ -6,6 +6,7 @@ Send the latest state for a managed Live Activity stream. channels is the stream Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**metadata** | [**Dict[str, MetadataValue]**](MetadataValue.md) | Additional information shown in notification and Live Activity details in ActivitySmith. Not displayed in the Push Notification or Live Activity on the device. Values must be strings, finite numbers, or booleans. At most 50 entries and 16 KB of serialized UTF-8 JSON. Omit on updates to preserve existing Metadata; send {} to clear it. | [optional] **content_state** | [**StreamContentState**](StreamContentState.md) | | **action** | [**LiveActivityAction**](LiveActivityAction.md) | | [optional] **secondary_action** | [**LiveActivityAction**](LiveActivityAction.md) | Optional secondary action button. Supported for alert, progress, and segmented_progress Live Activities. Uses the same open_url, shortcuts://, and webhook shapes as action. | [optional] diff --git a/activitysmith_openapi/docs/LiveActivityUpdateRequest.md b/activitysmith_openapi/docs/LiveActivityUpdateRequest.md index 1144734..e579170 100644 --- a/activitysmith_openapi/docs/LiveActivityUpdateRequest.md +++ b/activitysmith_openapi/docs/LiveActivityUpdateRequest.md @@ -6,7 +6,9 @@ Update an existing Live Activity by activity_id. Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**metadata** | [**Dict[str, MetadataValue]**](MetadataValue.md) | Additional information shown in notification and Live Activity details in ActivitySmith. Not displayed in the Push Notification or Live Activity on the device. Values must be strings, finite numbers, or booleans. At most 50 entries and 16 KB of serialized UTF-8 JSON. Omit on updates to preserve existing Metadata; send {} to clear it. | [optional] **activity_id** | **str** | | +**tags** | **List[str]** | Tags for notification history. Omit to keep existing Tags, supply an array to replace them, or send an empty array to clear them. | [optional] **content_state** | [**ContentStateUpdate**](ContentStateUpdate.md) | | **action** | [**LiveActivityAction**](LiveActivityAction.md) | | [optional] **secondary_action** | [**LiveActivityAction**](LiveActivityAction.md) | Optional secondary action button. Supported for alert, progress, and segmented_progress Live Activities. Uses the same open_url, shortcuts://, and webhook shapes as action. | [optional] diff --git a/activitysmith_openapi/docs/MetadataValue.md b/activitysmith_openapi/docs/MetadataValue.md new file mode 100644 index 0000000..d7e08ed --- /dev/null +++ b/activitysmith_openapi/docs/MetadataValue.md @@ -0,0 +1,28 @@ +# MetadataValue + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +## Example + +```python +from activitysmith_openapi.models.metadata_value import MetadataValue + +# TODO update the JSON string below +json = "{}" +# create an instance of MetadataValue from a JSON string +metadata_value_instance = MetadataValue.from_json(json) +# print the JSON string representation of the object +print(MetadataValue.to_json()) + +# convert the object into a dict +metadata_value_dict = metadata_value_instance.to_dict() +# create an instance of MetadataValue from a dict +metadata_value_from_dict = MetadataValue.from_dict(metadata_value_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/activitysmith_openapi/docs/PublicApi.md b/activitysmith_openapi/docs/PublicApi.md new file mode 100644 index 0000000..932bed6 --- /dev/null +++ b/activitysmith_openapi/docs/PublicApi.md @@ -0,0 +1,145 @@ +# activitysmith_openapi.PublicApi + +All URIs are relative to *https://activitysmith.com/api* + +Method | HTTP request | Description +------------- | ------------- | ------------- +[**get_api_health**](PublicApi.md#get_api_health) | **GET** /health | Get API Health +[**list_public_changelog_entries**](PublicApi.md#list_public_changelog_entries) | **GET** /changelog | List Public Changelog Entries + + +# **get_api_health** +> HealthResponse get_api_health() + +Get API Health + +Returns the current availability of the ActivitySmith API and its required services. No authentication is required. + +### Example + + +```python +import activitysmith_openapi +from activitysmith_openapi.models.health_response import HealthResponse +from activitysmith_openapi.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to https://activitysmith.com/api +# See configuration.py for a list of all supported configuration parameters. +configuration = activitysmith_openapi.Configuration( + host = "https://activitysmith.com/api" +) + + +# Enter a context with an instance of the API client +with activitysmith_openapi.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = activitysmith_openapi.PublicApi(api_client) + + try: + # Get API Health + api_response = api_instance.get_api_health() + print("The response of PublicApi->get_api_health:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling PublicApi->get_api_health: %s\n" % e) +``` + + + +### Parameters + +This endpoint does not need any parameter. + +### Return type + +[**HealthResponse**](HealthResponse.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | The API and its required services are available. | - | +**503** | One or more required services are unavailable. | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +# **list_public_changelog_entries** +> ChangelogListResponse list_public_changelog_entries(platform=platform, limit=limit) + +List Public Changelog Entries + +Returns published ActivitySmith app changelog entries. No authentication is required. + +### Example + + +```python +import activitysmith_openapi +from activitysmith_openapi.models.changelog_list_response import ChangelogListResponse +from activitysmith_openapi.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to https://activitysmith.com/api +# See configuration.py for a list of all supported configuration parameters. +configuration = activitysmith_openapi.Configuration( + host = "https://activitysmith.com/api" +) + + +# Enter a context with an instance of the API client +with activitysmith_openapi.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = activitysmith_openapi.PublicApi(api_client) + platform = 'ios' # str | Platform whose published changelog entries should be returned. (optional) (default to 'ios') + limit = 10 # int | Maximum number of entries to return. (optional) (default to 10) + + try: + # List Public Changelog Entries + api_response = api_instance.list_public_changelog_entries(platform=platform, limit=limit) + print("The response of PublicApi->list_public_changelog_entries:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling PublicApi->list_public_changelog_entries: %s\n" % e) +``` + + + +### Parameters + + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **platform** | **str**| Platform whose published changelog entries should be returned. | [optional] [default to 'ios'] + **limit** | **int**| Maximum number of entries to return. | [optional] [default to 10] + +### Return type + +[**ChangelogListResponse**](ChangelogListResponse.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | Published changelog entries ordered from newest to oldest. | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/activitysmith_openapi/docs/PushNotificationAction.md b/activitysmith_openapi/docs/PushNotificationAction.md index a47961f..b1569fd 100644 --- a/activitysmith_openapi/docs/PushNotificationAction.md +++ b/activitysmith_openapi/docs/PushNotificationAction.md @@ -7,7 +7,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **title** | **str** | Button title displayed in iOS expanded notification UI. | **type** | [**PushNotificationActionType**](PushNotificationActionType.md) | | -**url** | **str** | Action URL. For open_url, use an HTTP or HTTPS URL or a shortcuts://run-shortcut?name=... URL that runs a specific iPhone Shortcut. For webhook, use an HTTPS URL called by the ActivitySmith backend. | +**url** | **str** | Action URL. For open_url, use HTTP, HTTPS, Shortcuts, or an installed app’s custom URL scheme, such as spotify:// or spotify:track:123. Custom app schemes require iOS 1.13.4 build 2 or later; no web fallback is provided. Internal and executable schemes are blocked. For webhook, use an HTTPS URL called by the ActivitySmith backend. | **method** | [**PushNotificationWebhookMethod**](PushNotificationWebhookMethod.md) | Webhook HTTP method. Used only when type=webhook. | [optional] [default to PushNotificationWebhookMethod.POST] **body** | **object** | Optional webhook payload body. Used only when type=webhook. | [optional] diff --git a/activitysmith_openapi/docs/PushNotificationRequest.md b/activitysmith_openapi/docs/PushNotificationRequest.md index aa6611c..1c45c9e 100644 --- a/activitysmith_openapi/docs/PushNotificationRequest.md +++ b/activitysmith_openapi/docs/PushNotificationRequest.md @@ -5,11 +5,12 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**metadata** | [**Dict[str, MetadataValue]**](MetadataValue.md) | Additional information shown in notification and Live Activity details in ActivitySmith. Not displayed in the Push Notification or Live Activity on the device. Values must be strings, finite numbers, or booleans. At most 50 entries and 16 KB of serialized UTF-8 JSON. Omit on updates to preserve existing Metadata; send {} to clear it. | [optional] **title** | **str** | | **message** | **str** | | [optional] **subtitle** | **str** | | [optional] **media** | **str** | Optional HTTPS URL for an image, audio file, or video that users can preview or play when they expand the notification. If `redirection` is omitted, tapping the notification opens this URL. Cannot be combined with `actions`. | [optional] -**redirection** | **str** | Optional HTTP URL, HTTPS URL, or shortcuts://run-shortcut?name=... URL opened when the user taps the notification body. Use shortcuts://run-shortcut?name=... to run a specific iPhone Shortcut that already exists on the user's device. Overrides the default tap target from `media` when both are provided. | [optional] +**redirection** | **str** | Optional HTTP, HTTPS, Shortcuts, or installed app URL opened when the user taps the notification body. Custom schemes such as spotify:// and spotify:track:123 require iOS 1.13.4 build 2 or later and an installed handler; no web fallback is provided. Internal and executable schemes are blocked. Overrides the default tap target from media. | [optional] **actions** | [**List[PushNotificationAction]**](PushNotificationAction.md) | Optional interactive actions shown when users expand the notification. Cannot be combined with `media`. | [optional] **payload** | **object** | | [optional] **badge** | **int** | | [optional] diff --git a/activitysmith_openapi/docs/SendPushNotification429Response.md b/activitysmith_openapi/docs/SendPushNotification429Response.md index e1738e1..b4847aa 100644 --- a/activitysmith_openapi/docs/SendPushNotification429Response.md +++ b/activitysmith_openapi/docs/SendPushNotification429Response.md @@ -8,7 +8,9 @@ Name | Type | Description | Notes **error** | **str** | | **message** | **str** | | **limit** | **int** | | -**active** | **int** | Current number of active Live Activities. | +**active** | **int** | Highest number of active Live Activities among the targeted devices. | +**blocked_devices** | **int** | Number of targeted devices that have reached the enforced iOS Live Activity concurrency threshold. Included only when targeted devices have mixed capacity. | [optional] +**targeted_devices** | **int** | Total number of targeted devices. Included only when targeted devices have mixed capacity. | [optional] ## Example diff --git a/activitysmith_openapi/docs/UpdateAppIconBadgeCount422Response.md b/activitysmith_openapi/docs/UpdateAppIconBadgeCount422Response.md new file mode 100644 index 0000000..f7cbbfe --- /dev/null +++ b/activitysmith_openapi/docs/UpdateAppIconBadgeCount422Response.md @@ -0,0 +1,37 @@ +# UpdateAppIconBadgeCount422Response + + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**error** | **str** | | +**message** | **str** | | +**effective_channel_slugs** | **List[str]** | | [optional] +**code** | **str** | | +**badge** | **int** | | +**devices_targeted** | **int** | | [optional] +**devices_updated** | **int** | | +**users_updated** | **int** | | [optional] +**devices_notified** | **int** | Deprecated compatibility alias for devices_updated. | [optional] + +## Example + +```python +from activitysmith_openapi.models.update_app_icon_badge_count422_response import UpdateAppIconBadgeCount422Response + +# TODO update the JSON string below +json = "{}" +# create an instance of UpdateAppIconBadgeCount422Response from a JSON string +update_app_icon_badge_count422_response_instance = UpdateAppIconBadgeCount422Response.from_json(json) +# print the JSON string representation of the object +print(UpdateAppIconBadgeCount422Response.to_json()) + +# convert the object into a dict +update_app_icon_badge_count422_response_dict = update_app_icon_badge_count422_response_instance.to_dict() +# create an instance of UpdateAppIconBadgeCount422Response from a dict +update_app_icon_badge_count422_response_from_dict = UpdateAppIconBadgeCount422Response.from_dict(update_app_icon_badge_count422_response_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/activitysmith_openapi/models/__init__.py b/activitysmith_openapi/models/__init__.py index b9576c7..8faa131 100644 --- a/activitysmith_openapi/models/__init__.py +++ b/activitysmith_openapi/models/__init__.py @@ -17,14 +17,20 @@ from activitysmith_openapi.models.activity_metric import ActivityMetric from activitysmith_openapi.models.activity_metric_value import ActivityMetricValue from activitysmith_openapi.models.alert_payload import AlertPayload +from activitysmith_openapi.models.app_icon_badge_count_update_error import AppIconBadgeCountUpdateError from activitysmith_openapi.models.app_icon_badge_count_update_request import AppIconBadgeCountUpdateRequest from activitysmith_openapi.models.app_icon_badge_count_update_response import AppIconBadgeCountUpdateResponse from activitysmith_openapi.models.bad_request_error import BadRequestError +from activitysmith_openapi.models.changelog_entry import ChangelogEntry +from activitysmith_openapi.models.changelog_item import ChangelogItem +from activitysmith_openapi.models.changelog_list_response import ChangelogListResponse from activitysmith_openapi.models.channel_target import ChannelTarget from activitysmith_openapi.models.content_state_end import ContentStateEnd from activitysmith_openapi.models.content_state_start import ContentStateStart from activitysmith_openapi.models.content_state_update import ContentStateUpdate from activitysmith_openapi.models.forbidden_error import ForbiddenError +from activitysmith_openapi.models.health_check import HealthCheck +from activitysmith_openapi.models.health_response import HealthResponse from activitysmith_openapi.models.live_activity_action import LiveActivityAction from activitysmith_openapi.models.live_activity_action_type import LiveActivityActionType from activitysmith_openapi.models.live_activity_alert_badge import LiveActivityAlertBadge @@ -42,6 +48,7 @@ from activitysmith_openapi.models.live_activity_update_request import LiveActivityUpdateRequest from activitysmith_openapi.models.live_activity_update_response import LiveActivityUpdateResponse from activitysmith_openapi.models.live_activity_webhook_method import LiveActivityWebhookMethod +from activitysmith_openapi.models.metadata_value import MetadataValue from activitysmith_openapi.models.metric_error import MetricError from activitysmith_openapi.models.metric_value_update_request import MetricValueUpdateRequest from activitysmith_openapi.models.metric_value_update_request_value import MetricValueUpdateRequestValue @@ -56,3 +63,4 @@ from activitysmith_openapi.models.rate_limit_error import RateLimitError from activitysmith_openapi.models.send_push_notification429_response import SendPushNotification429Response from activitysmith_openapi.models.stream_content_state import StreamContentState +from activitysmith_openapi.models.update_app_icon_badge_count422_response import UpdateAppIconBadgeCount422Response diff --git a/activitysmith_openapi/models/app_icon_badge_count_update_error.py b/activitysmith_openapi/models/app_icon_badge_count_update_error.py new file mode 100644 index 0000000..0b9c9c7 --- /dev/null +++ b/activitysmith_openapi/models/app_icon_badge_count_update_error.py @@ -0,0 +1,111 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self + +class AppIconBadgeCountUpdateError(BaseModel): + """ + AppIconBadgeCountUpdateError + """ # noqa: E501 + error: StrictStr + code: StrictStr + message: StrictStr + badge: Annotated[int, Field(le=2147483647, strict=True, ge=0)] + devices_targeted: Optional[StrictInt] = None + devices_updated: StrictInt + users_updated: Optional[StrictInt] = None + devices_notified: Optional[StrictInt] = Field(default=None, description="Deprecated compatibility alias for devices_updated.") + effective_channel_slugs: Optional[List[StrictStr]] = None + __properties: ClassVar[List[str]] = ["error", "code", "message", "badge", "devices_targeted", "devices_updated", "users_updated", "devices_notified", "effective_channel_slugs"] + + @field_validator('code') + def code_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['badge_device_disconnected', 'badge_update_failed']): + raise ValueError("must be one of enum values ('badge_device_disconnected', 'badge_update_failed')") + return value + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of AppIconBadgeCountUpdateError from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AppIconBadgeCountUpdateError from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "error": obj.get("error"), + "code": obj.get("code"), + "message": obj.get("message"), + "badge": obj.get("badge"), + "devices_targeted": obj.get("devices_targeted"), + "devices_updated": obj.get("devices_updated"), + "users_updated": obj.get("users_updated"), + "devices_notified": obj.get("devices_notified"), + "effective_channel_slugs": obj.get("effective_channel_slugs") + }) + return _obj + + diff --git a/activitysmith_openapi/models/app_icon_badge_count_update_response.py b/activitysmith_openapi/models/app_icon_badge_count_update_response.py index 4818c20..e0582ba 100644 --- a/activitysmith_openapi/models/app_icon_badge_count_update_response.py +++ b/activitysmith_openapi/models/app_icon_badge_count_update_response.py @@ -19,7 +19,7 @@ from datetime import datetime from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr -from typing import Any, ClassVar, Dict, List +from typing import Any, ClassVar, Dict, List, Optional from typing_extensions import Annotated from typing import Optional, Set from typing_extensions import Self @@ -30,11 +30,13 @@ class AppIconBadgeCountUpdateResponse(BaseModel): """ # noqa: E501 success: StrictBool badge: Annotated[int, Field(le=2147483647, strict=True, ge=0)] - devices_notified: StrictInt - users_notified: StrictInt + devices_updated: StrictInt = Field(description="Number of devices whose App Icon Badge Count was updated.") + users_updated: StrictInt = Field(description="Number of account users with at least one updated device.") + devices_notified: Optional[StrictInt] = Field(default=None, description="Deprecated compatibility alias for devices_updated.") + users_notified: Optional[StrictInt] = Field(default=None, description="Deprecated compatibility alias for users_updated.") effective_channel_slugs: List[StrictStr] timestamp: datetime - __properties: ClassVar[List[str]] = ["success", "badge", "devices_notified", "users_notified", "effective_channel_slugs", "timestamp"] + __properties: ClassVar[List[str]] = ["success", "badge", "devices_updated", "users_updated", "devices_notified", "users_notified", "effective_channel_slugs", "timestamp"] model_config = ConfigDict( populate_by_name=True, @@ -89,6 +91,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "success": obj.get("success"), "badge": obj.get("badge"), + "devices_updated": obj.get("devices_updated"), + "users_updated": obj.get("users_updated"), "devices_notified": obj.get("devices_notified"), "users_notified": obj.get("users_notified"), "effective_channel_slugs": obj.get("effective_channel_slugs"), diff --git a/activitysmith_openapi/models/changelog_entry.py b/activitysmith_openapi/models/changelog_entry.py new file mode 100644 index 0000000..e42b808 --- /dev/null +++ b/activitysmith_openapi/models/changelog_entry.py @@ -0,0 +1,127 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from activitysmith_openapi.models.changelog_item import ChangelogItem +from typing import Optional, Set +from typing_extensions import Self + +class ChangelogEntry(BaseModel): + """ + ChangelogEntry + """ # noqa: E501 + id: StrictStr + platform: StrictStr + version: StrictStr + title: StrictStr + subtitle: Optional[StrictStr] + hero_image_url: Optional[StrictStr] + cta_title: StrictStr + published_at: Optional[datetime] + items: List[ChangelogItem] + __properties: ClassVar[List[str]] = ["id", "platform", "version", "title", "subtitle", "hero_image_url", "cta_title", "published_at", "items"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ChangelogEntry from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in items (list) + _items = [] + if self.items: + for _item in self.items: + if _item: + _items.append(_item.to_dict()) + _dict['items'] = _items + # set to None if subtitle (nullable) is None + # and model_fields_set contains the field + if self.subtitle is None and "subtitle" in self.model_fields_set: + _dict['subtitle'] = None + + # set to None if hero_image_url (nullable) is None + # and model_fields_set contains the field + if self.hero_image_url is None and "hero_image_url" in self.model_fields_set: + _dict['hero_image_url'] = None + + # set to None if published_at (nullable) is None + # and model_fields_set contains the field + if self.published_at is None and "published_at" in self.model_fields_set: + _dict['published_at'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ChangelogEntry from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "id": obj.get("id"), + "platform": obj.get("platform"), + "version": obj.get("version"), + "title": obj.get("title"), + "subtitle": obj.get("subtitle"), + "hero_image_url": obj.get("hero_image_url"), + "cta_title": obj.get("cta_title"), + "published_at": obj.get("published_at"), + "items": [ChangelogItem.from_dict(_item) for _item in obj["items"]] if obj.get("items") is not None else None + }) + return _obj + + diff --git a/activitysmith_openapi/models/changelog_item.py b/activitysmith_openapi/models/changelog_item.py new file mode 100644 index 0000000..03e4e14 --- /dev/null +++ b/activitysmith_openapi/models/changelog_item.py @@ -0,0 +1,110 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self + +class ChangelogItem(BaseModel): + """ + ChangelogItem + """ # noqa: E501 + icon: Optional[StrictStr] = None + title: StrictStr + body: StrictStr + image_url: Optional[StrictStr] = None + accent_color: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = ["icon", "title", "body", "image_url", "accent_color"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ChangelogItem from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if icon (nullable) is None + # and model_fields_set contains the field + if self.icon is None and "icon" in self.model_fields_set: + _dict['icon'] = None + + # set to None if image_url (nullable) is None + # and model_fields_set contains the field + if self.image_url is None and "image_url" in self.model_fields_set: + _dict['image_url'] = None + + # set to None if accent_color (nullable) is None + # and model_fields_set contains the field + if self.accent_color is None and "accent_color" in self.model_fields_set: + _dict['accent_color'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ChangelogItem from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "icon": obj.get("icon"), + "title": obj.get("title"), + "body": obj.get("body"), + "image_url": obj.get("image_url"), + "accent_color": obj.get("accent_color") + }) + return _obj + + diff --git a/activitysmith_openapi/models/changelog_list_response.py b/activitysmith_openapi/models/changelog_list_response.py new file mode 100644 index 0000000..c09c01d --- /dev/null +++ b/activitysmith_openapi/models/changelog_list_response.py @@ -0,0 +1,95 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List +from activitysmith_openapi.models.changelog_entry import ChangelogEntry +from typing import Optional, Set +from typing_extensions import Self + +class ChangelogListResponse(BaseModel): + """ + ChangelogListResponse + """ # noqa: E501 + changelogs: List[ChangelogEntry] + __properties: ClassVar[List[str]] = ["changelogs"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ChangelogListResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in changelogs (list) + _items = [] + if self.changelogs: + for _item in self.changelogs: + if _item: + _items.append(_item.to_dict()) + _dict['changelogs'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ChangelogListResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "changelogs": [ChangelogEntry.from_dict(_item) for _item in obj["changelogs"]] if obj.get("changelogs") is not None else None + }) + return _obj + + diff --git a/activitysmith_openapi/models/health_check.py b/activitysmith_openapi/models/health_check.py new file mode 100644 index 0000000..aca8ca0 --- /dev/null +++ b/activitysmith_openapi/models/health_check.py @@ -0,0 +1,106 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self + +class HealthCheck(BaseModel): + """ + HealthCheck + """ # noqa: E501 + name: StrictStr + status: StrictStr + duration_ms: Annotated[int, Field(strict=True, ge=0)] + __properties: ClassVar[List[str]] = ["name", "status", "duration_ms"] + + @field_validator('name') + def name_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['database', 'redis']): + raise ValueError("must be one of enum values ('database', 'redis')") + return value + + @field_validator('status') + def status_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['ok', 'failed']): + raise ValueError("must be one of enum values ('ok', 'failed')") + return value + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of HealthCheck from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of HealthCheck from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "name": obj.get("name"), + "status": obj.get("status"), + "duration_ms": obj.get("duration_ms") + }) + return _obj + + diff --git a/activitysmith_openapi/models/health_response.py b/activitysmith_openapi/models/health_response.py new file mode 100644 index 0000000..2016e77 --- /dev/null +++ b/activitysmith_openapi/models/health_response.py @@ -0,0 +1,102 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from pydantic import BaseModel, ConfigDict, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List +from activitysmith_openapi.models.health_check import HealthCheck +from typing import Optional, Set +from typing_extensions import Self + +class HealthResponse(BaseModel): + """ + HealthResponse + """ # noqa: E501 + ok: StrictBool + service: StrictStr + timestamp: datetime + checks: List[HealthCheck] + __properties: ClassVar[List[str]] = ["ok", "service", "timestamp", "checks"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of HealthResponse from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in checks (list) + _items = [] + if self.checks: + for _item in self.checks: + if _item: + _items.append(_item.to_dict()) + _dict['checks'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of HealthResponse from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "ok": obj.get("ok"), + "service": obj.get("service"), + "timestamp": obj.get("timestamp"), + "checks": [HealthCheck.from_dict(_item) for _item in obj["checks"]] if obj.get("checks") is not None else None + }) + return _obj + + diff --git a/activitysmith_openapi/models/live_activity_end_request.py b/activitysmith_openapi/models/live_activity_end_request.py index d9da0dd..4b9d75c 100644 --- a/activitysmith_openapi/models/live_activity_end_request.py +++ b/activitysmith_openapi/models/live_activity_end_request.py @@ -19,8 +19,10 @@ from pydantic import BaseModel, ConfigDict, Field, StrictStr from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated from activitysmith_openapi.models.content_state_end import ContentStateEnd from activitysmith_openapi.models.live_activity_action import LiveActivityAction +from activitysmith_openapi.models.metadata_value import MetadataValue from typing import Optional, Set from typing_extensions import Self @@ -28,11 +30,13 @@ class LiveActivityEndRequest(BaseModel): """ End an existing Live Activity by activity_id. """ # noqa: E501 + metadata: Optional[Dict[str, MetadataValue]] = Field(default=None, description="Additional information shown in notification and Live Activity details in ActivitySmith. Not displayed in the Push Notification or Live Activity on the device. Values must be strings, finite numbers, or booleans. At most 50 entries and 16 KB of serialized UTF-8 JSON. Omit on updates to preserve existing Metadata; send {} to clear it.") activity_id: StrictStr + tags: Optional[Annotated[List[Annotated[str, Field(min_length=1, strict=True, max_length=64)]], Field(max_length=20)]] = Field(default=None, description="Tags for notification history. Omit to keep existing Tags, supply an array to replace them, or send an empty array to clear them.") content_state: ContentStateEnd action: Optional[LiveActivityAction] = None secondary_action: Optional[LiveActivityAction] = Field(default=None, description="Optional secondary action button. Supported for alert, progress, and segmented_progress Live Activities. Uses the same open_url, shortcuts://, and webhook shapes as action.") - __properties: ClassVar[List[str]] = ["activity_id", "content_state", "action", "secondary_action"] + __properties: ClassVar[List[str]] = ["metadata", "activity_id", "tags", "content_state", "action", "secondary_action"] model_config = ConfigDict( populate_by_name=True, @@ -73,6 +77,13 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of each value in metadata (dict) + _field_dict = {} + if self.metadata: + for _key in self.metadata: + if self.metadata[_key]: + _field_dict[_key] = self.metadata[_key].to_dict() + _dict['metadata'] = _field_dict # override the default output from pydantic by calling `to_dict()` of content_state if self.content_state: _dict['content_state'] = self.content_state.to_dict() @@ -94,7 +105,14 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ + "metadata": dict( + (_k, MetadataValue.from_dict(_v)) + for _k, _v in obj["metadata"].items() + ) + if obj.get("metadata") is not None + else None, "activity_id": obj.get("activity_id"), + "tags": obj.get("tags"), "content_state": ContentStateEnd.from_dict(obj["content_state"]) if obj.get("content_state") is not None else None, "action": LiveActivityAction.from_dict(obj["action"]) if obj.get("action") is not None else None, "secondary_action": LiveActivityAction.from_dict(obj["secondary_action"]) if obj.get("secondary_action") is not None else None diff --git a/activitysmith_openapi/models/live_activity_limit_error.py b/activitysmith_openapi/models/live_activity_limit_error.py index f33b7e4..e3862e1 100644 --- a/activitysmith_openapi/models/live_activity_limit_error.py +++ b/activitysmith_openapi/models/live_activity_limit_error.py @@ -18,7 +18,7 @@ import json from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr -from typing import Any, ClassVar, Dict, List +from typing import Any, ClassVar, Dict, List, Optional from typing import Optional, Set from typing_extensions import Self @@ -29,8 +29,10 @@ class LiveActivityLimitError(BaseModel): error: StrictStr message: StrictStr limit: StrictInt - active: StrictInt = Field(description="Current number of active Live Activities.") - __properties: ClassVar[List[str]] = ["error", "message", "limit", "active"] + active: StrictInt = Field(description="Highest number of active Live Activities among the targeted devices.") + blocked_devices: Optional[StrictInt] = Field(default=None, description="Number of targeted devices that have reached the enforced iOS Live Activity concurrency threshold. Included only when targeted devices have mixed capacity.") + targeted_devices: Optional[StrictInt] = Field(default=None, description="Total number of targeted devices. Included only when targeted devices have mixed capacity.") + __properties: ClassVar[List[str]] = ["error", "message", "limit", "active", "blocked_devices", "targeted_devices"] model_config = ConfigDict( populate_by_name=True, @@ -86,7 +88,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "error": obj.get("error"), "message": obj.get("message"), "limit": obj.get("limit"), - "active": obj.get("active") + "active": obj.get("active"), + "blocked_devices": obj.get("blocked_devices"), + "targeted_devices": obj.get("targeted_devices") }) return _obj diff --git a/activitysmith_openapi/models/live_activity_start_request.py b/activitysmith_openapi/models/live_activity_start_request.py index 64ad780..1197184 100644 --- a/activitysmith_openapi/models/live_activity_start_request.py +++ b/activitysmith_openapi/models/live_activity_start_request.py @@ -24,6 +24,7 @@ from activitysmith_openapi.models.channel_target import ChannelTarget from activitysmith_openapi.models.content_state_start import ContentStateStart from activitysmith_openapi.models.live_activity_action import LiveActivityAction +from activitysmith_openapi.models.metadata_value import MetadataValue from typing import Optional, Set from typing_extensions import Self @@ -31,13 +32,14 @@ class LiveActivityStartRequest(BaseModel): """ Start a new Live Activity. The response includes activity_id for later update and end calls. """ # noqa: E501 + metadata: Optional[Dict[str, MetadataValue]] = Field(default=None, description="Additional information shown in notification and Live Activity details in ActivitySmith. Not displayed in the Push Notification or Live Activity on the device. Values must be strings, finite numbers, or booleans. At most 50 entries and 16 KB of serialized UTF-8 JSON. Omit on updates to preserve existing Metadata; send {} to clear it.") content_state: ContentStateStart action: Optional[LiveActivityAction] = None secondary_action: Optional[LiveActivityAction] = Field(default=None, description="Optional secondary action button. Supported for alert, progress, and segmented_progress Live Activities. Uses the same open_url, shortcuts://, and webhook shapes as action.") alert: Optional[AlertPayload] = None target: Optional[ChannelTarget] = None tags: Optional[List[Annotated[str, Field(min_length=1, strict=True, max_length=64)]]] = Field(default=None, description="Optional tags to organize and filter notification history.") - __properties: ClassVar[List[str]] = ["content_state", "action", "secondary_action", "alert", "target", "tags"] + __properties: ClassVar[List[str]] = ["metadata", "content_state", "action", "secondary_action", "alert", "target", "tags"] model_config = ConfigDict( populate_by_name=True, @@ -78,6 +80,13 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of each value in metadata (dict) + _field_dict = {} + if self.metadata: + for _key in self.metadata: + if self.metadata[_key]: + _field_dict[_key] = self.metadata[_key].to_dict() + _dict['metadata'] = _field_dict # override the default output from pydantic by calling `to_dict()` of content_state if self.content_state: _dict['content_state'] = self.content_state.to_dict() @@ -105,6 +114,12 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ + "metadata": dict( + (_k, MetadataValue.from_dict(_v)) + for _k, _v in obj["metadata"].items() + ) + if obj.get("metadata") is not None + else None, "content_state": ContentStateStart.from_dict(obj["content_state"]) if obj.get("content_state") is not None else None, "action": LiveActivityAction.from_dict(obj["action"]) if obj.get("action") is not None else None, "secondary_action": LiveActivityAction.from_dict(obj["secondary_action"]) if obj.get("secondary_action") is not None else None, diff --git a/activitysmith_openapi/models/live_activity_stream_delete_request.py b/activitysmith_openapi/models/live_activity_stream_delete_request.py index 8edb49c..b47c57b 100644 --- a/activitysmith_openapi/models/live_activity_stream_delete_request.py +++ b/activitysmith_openapi/models/live_activity_stream_delete_request.py @@ -17,10 +17,12 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field +from pydantic import BaseModel, ConfigDict, Field, field_validator from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated from activitysmith_openapi.models.alert_payload import AlertPayload from activitysmith_openapi.models.live_activity_action import LiveActivityAction +from activitysmith_openapi.models.metadata_value import MetadataValue from activitysmith_openapi.models.stream_content_state import StreamContentState from typing import Optional, Set from typing_extensions import Self @@ -29,11 +31,13 @@ class LiveActivityStreamDeleteRequest(BaseModel): """ Optional payload for ending a managed stream. When omitted, ActivitySmith ends the stream using the latest known state when possible. """ # noqa: E501 + metadata: Optional[Dict[str, MetadataValue]] = Field(default=None, description="Additional information shown in notification and Live Activity details in ActivitySmith. Not displayed in the Push Notification or Live Activity on the device. Values must be strings, finite numbers, or booleans. At most 50 entries and 16 KB of serialized UTF-8 JSON. Omit on updates to preserve existing Metadata; send {} to clear it.") + tags: Optional[List[Annotated[str, Field(min_length=1, strict=True, max_length=64)]]] = Field(default=None, description="Optional tags to organize and filter notification history.") content_state: Optional[StreamContentState] = None action: Optional[LiveActivityAction] = None secondary_action: Optional[LiveActivityAction] = Field(default=None, description="Optional secondary action button. Supported for alert, progress, and segmented_progress Live Activities. Uses the same open_url, shortcuts://, and webhook shapes as action.") alert: Optional[AlertPayload] = None - __properties: ClassVar[List[str]] = ["content_state", "action", "secondary_action", "alert"] + __properties: ClassVar[List[str]] = ["metadata", "tags", "content_state", "action", "secondary_action", "alert"] model_config = ConfigDict( populate_by_name=True, @@ -74,6 +78,13 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of each value in metadata (dict) + _field_dict = {} + if self.metadata: + for _key in self.metadata: + if self.metadata[_key]: + _field_dict[_key] = self.metadata[_key].to_dict() + _dict['metadata'] = _field_dict # override the default output from pydantic by calling `to_dict()` of content_state if self.content_state: _dict['content_state'] = self.content_state.to_dict() @@ -98,6 +109,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ + "metadata": dict( + (_k, MetadataValue.from_dict(_v)) + for _k, _v in obj["metadata"].items() + ) + if obj.get("metadata") is not None + else None, + "tags": obj.get("tags"), "content_state": StreamContentState.from_dict(obj["content_state"]) if obj.get("content_state") is not None else None, "action": LiveActivityAction.from_dict(obj["action"]) if obj.get("action") is not None else None, "secondary_action": LiveActivityAction.from_dict(obj["secondary_action"]) if obj.get("secondary_action") is not None else None, diff --git a/activitysmith_openapi/models/live_activity_stream_request.py b/activitysmith_openapi/models/live_activity_stream_request.py index 7a2e7c4..3b39cad 100644 --- a/activitysmith_openapi/models/live_activity_stream_request.py +++ b/activitysmith_openapi/models/live_activity_stream_request.py @@ -23,6 +23,7 @@ from activitysmith_openapi.models.alert_payload import AlertPayload from activitysmith_openapi.models.channel_target import ChannelTarget from activitysmith_openapi.models.live_activity_action import LiveActivityAction +from activitysmith_openapi.models.metadata_value import MetadataValue from activitysmith_openapi.models.stream_content_state import StreamContentState from typing import Optional, Set from typing_extensions import Self @@ -31,6 +32,7 @@ class LiveActivityStreamRequest(BaseModel): """ Send the latest state for a managed Live Activity stream. channels is the streamlined form for stream targeting. target.channels is also accepted for compatibility. If both are provided, they must match. """ # noqa: E501 + metadata: Optional[Dict[str, MetadataValue]] = Field(default=None, description="Additional information shown in notification and Live Activity details in ActivitySmith. Not displayed in the Push Notification or Live Activity on the device. Values must be strings, finite numbers, or booleans. At most 50 entries and 16 KB of serialized UTF-8 JSON. Omit on updates to preserve existing Metadata; send {} to clear it.") content_state: StreamContentState action: Optional[LiveActivityAction] = None secondary_action: Optional[LiveActivityAction] = Field(default=None, description="Optional secondary action button. Supported for alert, progress, and segmented_progress Live Activities. Uses the same open_url, shortcuts://, and webhook shapes as action.") @@ -38,7 +40,7 @@ class LiveActivityStreamRequest(BaseModel): channels: Optional[Annotated[List[StrictStr], Field(min_length=1)]] = Field(default=None, description="Channel slugs. When omitted, API key scope determines recipients.") target: Optional[ChannelTarget] = None tags: Optional[List[Annotated[str, Field(min_length=1, strict=True, max_length=64)]]] = Field(default=None, description="Optional tags to organize and filter notification history.") - __properties: ClassVar[List[str]] = ["content_state", "action", "secondary_action", "alert", "channels", "target", "tags"] + __properties: ClassVar[List[str]] = ["metadata", "content_state", "action", "secondary_action", "alert", "channels", "target", "tags"] model_config = ConfigDict( populate_by_name=True, @@ -79,6 +81,13 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of each value in metadata (dict) + _field_dict = {} + if self.metadata: + for _key in self.metadata: + if self.metadata[_key]: + _field_dict[_key] = self.metadata[_key].to_dict() + _dict['metadata'] = _field_dict # override the default output from pydantic by calling `to_dict()` of content_state if self.content_state: _dict['content_state'] = self.content_state.to_dict() @@ -106,6 +115,12 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ + "metadata": dict( + (_k, MetadataValue.from_dict(_v)) + for _k, _v in obj["metadata"].items() + ) + if obj.get("metadata") is not None + else None, "content_state": StreamContentState.from_dict(obj["content_state"]) if obj.get("content_state") is not None else None, "action": LiveActivityAction.from_dict(obj["action"]) if obj.get("action") is not None else None, "secondary_action": LiveActivityAction.from_dict(obj["secondary_action"]) if obj.get("secondary_action") is not None else None, diff --git a/activitysmith_openapi/models/live_activity_update_request.py b/activitysmith_openapi/models/live_activity_update_request.py index 3ed4911..4c342b9 100644 --- a/activitysmith_openapi/models/live_activity_update_request.py +++ b/activitysmith_openapi/models/live_activity_update_request.py @@ -19,8 +19,10 @@ from pydantic import BaseModel, ConfigDict, Field, StrictStr from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated from activitysmith_openapi.models.content_state_update import ContentStateUpdate from activitysmith_openapi.models.live_activity_action import LiveActivityAction +from activitysmith_openapi.models.metadata_value import MetadataValue from typing import Optional, Set from typing_extensions import Self @@ -28,11 +30,13 @@ class LiveActivityUpdateRequest(BaseModel): """ Update an existing Live Activity by activity_id. """ # noqa: E501 + metadata: Optional[Dict[str, MetadataValue]] = Field(default=None, description="Additional information shown in notification and Live Activity details in ActivitySmith. Not displayed in the Push Notification or Live Activity on the device. Values must be strings, finite numbers, or booleans. At most 50 entries and 16 KB of serialized UTF-8 JSON. Omit on updates to preserve existing Metadata; send {} to clear it.") activity_id: StrictStr + tags: Optional[Annotated[List[Annotated[str, Field(min_length=1, strict=True, max_length=64)]], Field(max_length=20)]] = Field(default=None, description="Tags for notification history. Omit to keep existing Tags, supply an array to replace them, or send an empty array to clear them.") content_state: ContentStateUpdate action: Optional[LiveActivityAction] = None secondary_action: Optional[LiveActivityAction] = Field(default=None, description="Optional secondary action button. Supported for alert, progress, and segmented_progress Live Activities. Uses the same open_url, shortcuts://, and webhook shapes as action.") - __properties: ClassVar[List[str]] = ["activity_id", "content_state", "action", "secondary_action"] + __properties: ClassVar[List[str]] = ["metadata", "activity_id", "tags", "content_state", "action", "secondary_action"] model_config = ConfigDict( populate_by_name=True, @@ -73,6 +77,13 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of each value in metadata (dict) + _field_dict = {} + if self.metadata: + for _key in self.metadata: + if self.metadata[_key]: + _field_dict[_key] = self.metadata[_key].to_dict() + _dict['metadata'] = _field_dict # override the default output from pydantic by calling `to_dict()` of content_state if self.content_state: _dict['content_state'] = self.content_state.to_dict() @@ -94,7 +105,14 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ + "metadata": dict( + (_k, MetadataValue.from_dict(_v)) + for _k, _v in obj["metadata"].items() + ) + if obj.get("metadata") is not None + else None, "activity_id": obj.get("activity_id"), + "tags": obj.get("tags"), "content_state": ContentStateUpdate.from_dict(obj["content_state"]) if obj.get("content_state") is not None else None, "action": LiveActivityAction.from_dict(obj["action"]) if obj.get("action") is not None else None, "secondary_action": LiveActivityAction.from_dict(obj["secondary_action"]) if obj.get("secondary_action") is not None else None diff --git a/activitysmith_openapi/models/metadata_value.py b/activitysmith_openapi/models/metadata_value.py new file mode 100644 index 0000000..a2053b1 --- /dev/null +++ b/activitysmith_openapi/models/metadata_value.py @@ -0,0 +1,161 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import json +import pprint +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictFloat, StrictInt, StrictStr, ValidationError, field_validator +from typing import Any, List, Optional, Union +from typing_extensions import Annotated +from pydantic import StrictStr, Field +from typing import Union, List, Set, Optional, Dict +from typing_extensions import Literal, Self + +METADATAVALUE_ONE_OF_SCHEMAS = ["bool", "float", "str"] + +class MetadataValue(BaseModel): + """ + MetadataValue + """ + # data type: str + oneof_schema_1_validator: Optional[Annotated[str, Field(strict=True, max_length=4000)]] = None + # data type: float + oneof_schema_2_validator: Optional[Union[StrictFloat, StrictInt]] = None + # data type: bool + oneof_schema_3_validator: Optional[StrictBool] = None + actual_instance: Optional[Union[bool, float, str]] = None + one_of_schemas: Set[str] = { "bool", "float", "str" } + + model_config = ConfigDict( + validate_assignment=True, + protected_namespaces=(), + ) + + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_oneof(cls, v): + instance = MetadataValue.model_construct() + error_messages = [] + match = 0 + # validate data type: str + try: + instance.oneof_schema_1_validator = v + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: float + try: + instance.oneof_schema_2_validator = v + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # validate data type: bool + try: + instance.oneof_schema_3_validator = v + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + if match > 1: + # more than 1 match + raise ValueError("Multiple matches found when setting `actual_instance` in MetadataValue with oneOf schemas: bool, float, str. Details: " + ", ".join(error_messages)) + elif match == 0: + # no match + raise ValueError("No match found when setting `actual_instance` in MetadataValue with oneOf schemas: bool, float, str. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Union[str, Dict[str, Any]]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + match = 0 + + # deserialize data into str + try: + # validation + instance.oneof_schema_1_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.oneof_schema_1_validator + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into float + try: + # validation + instance.oneof_schema_2_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.oneof_schema_2_validator + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into bool + try: + # validation + instance.oneof_schema_3_validator = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.oneof_schema_3_validator + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if match > 1: + # more than 1 match + raise ValueError("Multiple matches found when deserializing the JSON string into MetadataValue with oneOf schemas: bool, float, str. Details: " + ", ".join(error_messages)) + elif match == 0: + # no match + raise ValueError("No match found when deserializing the JSON string into MetadataValue with oneOf schemas: bool, float, str. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], bool, float, str]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + # primitive type + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/activitysmith_openapi/models/push_notification_action.py b/activitysmith_openapi/models/push_notification_action.py index efd94cd..5af3e5b 100644 --- a/activitysmith_openapi/models/push_notification_action.py +++ b/activitysmith_openapi/models/push_notification_action.py @@ -30,7 +30,7 @@ class PushNotificationAction(BaseModel): """ # noqa: E501 title: StrictStr = Field(description="Button title displayed in iOS expanded notification UI.") type: PushNotificationActionType - url: StrictStr = Field(description="Action URL. For open_url, use an HTTP or HTTPS URL or a shortcuts://run-shortcut?name=... URL that runs a specific iPhone Shortcut. For webhook, use an HTTPS URL called by the ActivitySmith backend.") + url: StrictStr = Field(description="Action URL. For open_url, use HTTP, HTTPS, Shortcuts, or an installed app’s custom URL scheme, such as spotify:// or spotify:track:123. Custom app schemes require iOS 1.13.4 build 2 or later; no web fallback is provided. Internal and executable schemes are blocked. For webhook, use an HTTPS URL called by the ActivitySmith backend.") method: Optional[PushNotificationWebhookMethod] = Field(default=PushNotificationWebhookMethod.POST, description="Webhook HTTP method. Used only when type=webhook.") body: Optional[Dict[str, Any]] = Field(default=None, description="Optional webhook payload body. Used only when type=webhook.") additional_properties: Dict[str, Any] = {} diff --git a/activitysmith_openapi/models/push_notification_request.py b/activitysmith_openapi/models/push_notification_request.py index 4e83ea0..c62d06c 100644 --- a/activitysmith_openapi/models/push_notification_request.py +++ b/activitysmith_openapi/models/push_notification_request.py @@ -21,6 +21,7 @@ from typing import Any, ClassVar, Dict, List, Optional from typing_extensions import Annotated from activitysmith_openapi.models.channel_target import ChannelTarget +from activitysmith_openapi.models.metadata_value import MetadataValue from activitysmith_openapi.models.push_notification_action import PushNotificationAction from typing import Optional, Set from typing_extensions import Self @@ -29,11 +30,12 @@ class PushNotificationRequest(BaseModel): """ PushNotificationRequest """ # noqa: E501 + metadata: Optional[Dict[str, MetadataValue]] = Field(default=None, description="Additional information shown in notification and Live Activity details in ActivitySmith. Not displayed in the Push Notification or Live Activity on the device. Values must be strings, finite numbers, or booleans. At most 50 entries and 16 KB of serialized UTF-8 JSON. Omit on updates to preserve existing Metadata; send {} to clear it.") title: StrictStr message: Optional[StrictStr] = None subtitle: Optional[StrictStr] = None media: Optional[Annotated[str, Field(strict=True)]] = Field(default=None, description="Optional HTTPS URL for an image, audio file, or video that users can preview or play when they expand the notification. If `redirection` is omitted, tapping the notification opens this URL. Cannot be combined with `actions`.") - redirection: Optional[Annotated[str, Field(strict=True)]] = Field(default=None, description="Optional HTTP URL, HTTPS URL, or shortcuts://run-shortcut?name=... URL opened when the user taps the notification body. Use shortcuts://run-shortcut?name=... to run a specific iPhone Shortcut that already exists on the user's device. Overrides the default tap target from `media` when both are provided.") + redirection: Optional[Annotated[str, Field(strict=True, max_length=2048)]] = Field(default=None, description="Optional HTTP, HTTPS, Shortcuts, or installed app URL opened when the user taps the notification body. Custom schemes such as spotify:// and spotify:track:123 require iOS 1.13.4 build 2 or later and an installed handler; no web fallback is provided. Internal and executable schemes are blocked. Overrides the default tap target from media.") actions: Optional[Annotated[List[PushNotificationAction], Field(max_length=4)]] = Field(default=None, description="Optional interactive actions shown when users expand the notification. Cannot be combined with `media`.") payload: Optional[Dict[str, Any]] = None badge: Optional[StrictInt] = None @@ -41,7 +43,7 @@ class PushNotificationRequest(BaseModel): target: Optional[ChannelTarget] = None tags: Optional[List[Annotated[str, Field(min_length=1, strict=True, max_length=64)]]] = Field(default=None, description="Optional tags to organize and filter notification history.") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["title", "message", "subtitle", "media", "redirection", "actions", "payload", "badge", "sound", "target", "tags"] + __properties: ClassVar[List[str]] = ["metadata", "title", "message", "subtitle", "media", "redirection", "actions", "payload", "badge", "sound", "target", "tags"] @field_validator('media') def media_validate_regular_expression(cls, value): @@ -59,8 +61,8 @@ def redirection_validate_regular_expression(cls, value): if value is None: return value - if not re.match(r"^(http|https|shortcuts):\/\/", value): - raise ValueError(r"must validate the regular expression /^(http|https|shortcuts):\/\//") + if not re.match(r"^[A-Za-z][A-Za-z0-9+.-]*:", value): + raise ValueError(r"must validate the regular expression /^[A-Za-z][A-Za-z0-9+.-]*:/") return value model_config = ConfigDict( @@ -104,6 +106,13 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of each value in metadata (dict) + _field_dict = {} + if self.metadata: + for _key in self.metadata: + if self.metadata[_key]: + _field_dict[_key] = self.metadata[_key].to_dict() + _dict['metadata'] = _field_dict # override the default output from pydantic by calling `to_dict()` of each item in actions (list) _items = [] if self.actions: @@ -131,6 +140,12 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ + "metadata": dict( + (_k, MetadataValue.from_dict(_v)) + for _k, _v in obj["metadata"].items() + ) + if obj.get("metadata") is not None + else None, "title": obj.get("title"), "message": obj.get("message"), "subtitle": obj.get("subtitle"), diff --git a/activitysmith_openapi/models/update_app_icon_badge_count422_response.py b/activitysmith_openapi/models/update_app_icon_badge_count422_response.py new file mode 100644 index 0000000..ebf28ab --- /dev/null +++ b/activitysmith_openapi/models/update_app_icon_badge_count422_response.py @@ -0,0 +1,137 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import json +import pprint +from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator +from typing import Any, List, Optional +from activitysmith_openapi.models.app_icon_badge_count_update_error import AppIconBadgeCountUpdateError +from activitysmith_openapi.models.no_recipients_error import NoRecipientsError +from pydantic import StrictStr, Field +from typing import Union, List, Set, Optional, Dict +from typing_extensions import Literal, Self + +UPDATEAPPICONBADGECOUNT422RESPONSE_ONE_OF_SCHEMAS = ["AppIconBadgeCountUpdateError", "NoRecipientsError"] + +class UpdateAppIconBadgeCount422Response(BaseModel): + """ + UpdateAppIconBadgeCount422Response + """ + # data type: NoRecipientsError + oneof_schema_1_validator: Optional[NoRecipientsError] = None + # data type: AppIconBadgeCountUpdateError + oneof_schema_2_validator: Optional[AppIconBadgeCountUpdateError] = None + actual_instance: Optional[Union[AppIconBadgeCountUpdateError, NoRecipientsError]] = None + one_of_schemas: Set[str] = { "AppIconBadgeCountUpdateError", "NoRecipientsError" } + + model_config = ConfigDict( + validate_assignment=True, + protected_namespaces=(), + ) + + + def __init__(self, *args, **kwargs) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_oneof(cls, v): + instance = UpdateAppIconBadgeCount422Response.model_construct() + error_messages = [] + match = 0 + # validate data type: NoRecipientsError + if not isinstance(v, NoRecipientsError): + error_messages.append(f"Error! Input type `{type(v)}` is not `NoRecipientsError`") + else: + match += 1 + # validate data type: AppIconBadgeCountUpdateError + if not isinstance(v, AppIconBadgeCountUpdateError): + error_messages.append(f"Error! Input type `{type(v)}` is not `AppIconBadgeCountUpdateError`") + else: + match += 1 + if match > 1: + # more than 1 match + raise ValueError("Multiple matches found when setting `actual_instance` in UpdateAppIconBadgeCount422Response with oneOf schemas: AppIconBadgeCountUpdateError, NoRecipientsError. Details: " + ", ".join(error_messages)) + elif match == 0: + # no match + raise ValueError("No match found when setting `actual_instance` in UpdateAppIconBadgeCount422Response with oneOf schemas: AppIconBadgeCountUpdateError, NoRecipientsError. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Union[str, Dict[str, Any]]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Returns the object represented by the json string""" + instance = cls.model_construct() + error_messages = [] + match = 0 + + # deserialize data into NoRecipientsError + try: + instance.actual_instance = NoRecipientsError.from_json(json_str) + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + # deserialize data into AppIconBadgeCountUpdateError + try: + instance.actual_instance = AppIconBadgeCountUpdateError.from_json(json_str) + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + + if match > 1: + # more than 1 match + raise ValueError("Multiple matches found when deserializing the JSON string into UpdateAppIconBadgeCount422Response with oneOf schemas: AppIconBadgeCountUpdateError, NoRecipientsError. Details: " + ", ".join(error_messages)) + elif match == 0: + # no match + raise ValueError("No match found when deserializing the JSON string into UpdateAppIconBadgeCount422Response with oneOf schemas: AppIconBadgeCountUpdateError, NoRecipientsError. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[Dict[str, Any], AppIconBadgeCountUpdateError, NoRecipientsError]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + # primitive type + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + + diff --git a/activitysmith_openapi/openapi-source.json b/activitysmith_openapi/openapi-source.json new file mode 100644 index 0000000..5a616d3 --- /dev/null +++ b/activitysmith_openapi/openapi-source.json @@ -0,0 +1,6 @@ +{ + "repository": "ActivitySmithHQ/activitysmith-backend", + "commit": "3cd1df5f1296777bacfad731eac9f91d27d01c6e", + "path": "openapi.json", + "sha256": "e112ddb9a069dc0ad87a123d0be1286ff0a671da505fabfdf4bb94ff6bcb444f" +} diff --git a/activitysmith_openapi/test/test_app_icon_badge_count_update_error.py b/activitysmith_openapi/test/test_app_icon_badge_count_update_error.py new file mode 100644 index 0000000..b6b6f1e --- /dev/null +++ b/activitysmith_openapi/test/test_app_icon_badge_count_update_error.py @@ -0,0 +1,66 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from activitysmith_openapi.models.app_icon_badge_count_update_error import AppIconBadgeCountUpdateError + +class TestAppIconBadgeCountUpdateError(unittest.TestCase): + """AppIconBadgeCountUpdateError unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> AppIconBadgeCountUpdateError: + """Test AppIconBadgeCountUpdateError + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `AppIconBadgeCountUpdateError` + """ + model = AppIconBadgeCountUpdateError() + if include_optional: + return AppIconBadgeCountUpdateError( + error = '', + code = 'badge_device_disconnected', + message = '', + badge = 0, + devices_targeted = 56, + devices_updated = 56, + users_updated = 56, + devices_notified = 56, + effective_channel_slugs = [ + '' + ] + ) + else: + return AppIconBadgeCountUpdateError( + error = '', + code = 'badge_device_disconnected', + message = '', + badge = 0, + devices_updated = 56, + ) + """ + + def testAppIconBadgeCountUpdateError(self): + """Test AppIconBadgeCountUpdateError""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/activitysmith_openapi/test/test_app_icon_badge_count_update_response.py b/activitysmith_openapi/test/test_app_icon_badge_count_update_response.py index 82f2555..ada9340 100644 --- a/activitysmith_openapi/test/test_app_icon_badge_count_update_response.py +++ b/activitysmith_openapi/test/test_app_icon_badge_count_update_response.py @@ -37,6 +37,8 @@ def make_instance(self, include_optional) -> AppIconBadgeCountUpdateResponse: return AppIconBadgeCountUpdateResponse( success = True, badge = 0, + devices_updated = 56, + users_updated = 56, devices_notified = 56, users_notified = 56, effective_channel_slugs = [ @@ -48,8 +50,8 @@ def make_instance(self, include_optional) -> AppIconBadgeCountUpdateResponse: return AppIconBadgeCountUpdateResponse( success = True, badge = 0, - devices_notified = 56, - users_notified = 56, + devices_updated = 56, + users_updated = 56, effective_channel_slugs = [ '' ], diff --git a/activitysmith_openapi/test/test_changelog_entry.py b/activitysmith_openapi/test/test_changelog_entry.py new file mode 100644 index 0000000..27d0ba7 --- /dev/null +++ b/activitysmith_openapi/test/test_changelog_entry.py @@ -0,0 +1,82 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from activitysmith_openapi.models.changelog_entry import ChangelogEntry + +class TestChangelogEntry(unittest.TestCase): + """ChangelogEntry unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> ChangelogEntry: + """Test ChangelogEntry + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `ChangelogEntry` + """ + model = ChangelogEntry() + if include_optional: + return ChangelogEntry( + id = '', + platform = '', + version = '', + title = '', + subtitle = '', + hero_image_url = '', + cta_title = '', + published_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + items = [ + activitysmith_openapi.models.changelog_item.ChangelogItem( + icon = '', + title = '', + body = '', + image_url = '', + accent_color = '', ) + ] + ) + else: + return ChangelogEntry( + id = '', + platform = '', + version = '', + title = '', + subtitle = '', + hero_image_url = '', + cta_title = '', + published_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + items = [ + activitysmith_openapi.models.changelog_item.ChangelogItem( + icon = '', + title = '', + body = '', + image_url = '', + accent_color = '', ) + ], + ) + """ + + def testChangelogEntry(self): + """Test ChangelogEntry""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/activitysmith_openapi/test/test_changelog_item.py b/activitysmith_openapi/test/test_changelog_item.py new file mode 100644 index 0000000..c20a159 --- /dev/null +++ b/activitysmith_openapi/test/test_changelog_item.py @@ -0,0 +1,57 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from activitysmith_openapi.models.changelog_item import ChangelogItem + +class TestChangelogItem(unittest.TestCase): + """ChangelogItem unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> ChangelogItem: + """Test ChangelogItem + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `ChangelogItem` + """ + model = ChangelogItem() + if include_optional: + return ChangelogItem( + icon = '', + title = '', + body = '', + image_url = '', + accent_color = '' + ) + else: + return ChangelogItem( + title = '', + body = '', + ) + """ + + def testChangelogItem(self): + """Test ChangelogItem""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/activitysmith_openapi/test/test_changelog_list_response.py b/activitysmith_openapi/test/test_changelog_list_response.py new file mode 100644 index 0000000..eae19b8 --- /dev/null +++ b/activitysmith_openapi/test/test_changelog_list_response.py @@ -0,0 +1,88 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from activitysmith_openapi.models.changelog_list_response import ChangelogListResponse + +class TestChangelogListResponse(unittest.TestCase): + """ChangelogListResponse unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> ChangelogListResponse: + """Test ChangelogListResponse + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `ChangelogListResponse` + """ + model = ChangelogListResponse() + if include_optional: + return ChangelogListResponse( + changelogs = [ + activitysmith_openapi.models.changelog_entry.ChangelogEntry( + id = '', + platform = '', + version = '', + title = '', + subtitle = '', + hero_image_url = '', + cta_title = '', + published_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + items = [ + activitysmith_openapi.models.changelog_item.ChangelogItem( + icon = '', + title = '', + body = '', + image_url = '', + accent_color = '', ) + ], ) + ] + ) + else: + return ChangelogListResponse( + changelogs = [ + activitysmith_openapi.models.changelog_entry.ChangelogEntry( + id = '', + platform = '', + version = '', + title = '', + subtitle = '', + hero_image_url = '', + cta_title = '', + published_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + items = [ + activitysmith_openapi.models.changelog_item.ChangelogItem( + icon = '', + title = '', + body = '', + image_url = '', + accent_color = '', ) + ], ) + ], + ) + """ + + def testChangelogListResponse(self): + """Test ChangelogListResponse""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/activitysmith_openapi/test/test_health_check.py b/activitysmith_openapi/test/test_health_check.py new file mode 100644 index 0000000..fe37e13 --- /dev/null +++ b/activitysmith_openapi/test/test_health_check.py @@ -0,0 +1,56 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from activitysmith_openapi.models.health_check import HealthCheck + +class TestHealthCheck(unittest.TestCase): + """HealthCheck unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> HealthCheck: + """Test HealthCheck + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `HealthCheck` + """ + model = HealthCheck() + if include_optional: + return HealthCheck( + name = 'database', + status = 'ok', + duration_ms = 0 + ) + else: + return HealthCheck( + name = 'database', + status = 'ok', + duration_ms = 0, + ) + """ + + def testHealthCheck(self): + """Test HealthCheck""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/activitysmith_openapi/test/test_health_response.py b/activitysmith_openapi/test/test_health_response.py new file mode 100644 index 0000000..cf55ec3 --- /dev/null +++ b/activitysmith_openapi/test/test_health_response.py @@ -0,0 +1,68 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from activitysmith_openapi.models.health_response import HealthResponse + +class TestHealthResponse(unittest.TestCase): + """HealthResponse unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> HealthResponse: + """Test HealthResponse + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `HealthResponse` + """ + model = HealthResponse() + if include_optional: + return HealthResponse( + ok = True, + service = '', + timestamp = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + checks = [ + activitysmith_openapi.models.health_check.HealthCheck( + name = 'database', + status = 'ok', + duration_ms = 0, ) + ] + ) + else: + return HealthResponse( + ok = True, + service = '', + timestamp = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + checks = [ + activitysmith_openapi.models.health_check.HealthCheck( + name = 'database', + status = 'ok', + duration_ms = 0, ) + ], + ) + """ + + def testHealthResponse(self): + """Test HealthResponse""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/activitysmith_openapi/test/test_live_activity_end_request.py b/activitysmith_openapi/test/test_live_activity_end_request.py index 5e51e63..a03564c 100644 --- a/activitysmith_openapi/test/test_live_activity_end_request.py +++ b/activitysmith_openapi/test/test_live_activity_end_request.py @@ -35,7 +35,13 @@ def make_instance(self, include_optional) -> LiveActivityEndRequest: model = LiveActivityEndRequest() if include_optional: return LiveActivityEndRequest( + metadata = { + 'key' : null + }, activity_id = '', + tags = [ + '0' + ], content_state = activitysmith_openapi.models.content_state_end.ContentStateEnd( title = '', subtitle = '', diff --git a/activitysmith_openapi/test/test_live_activity_limit_error.py b/activitysmith_openapi/test/test_live_activity_limit_error.py index c618fef..99a9502 100644 --- a/activitysmith_openapi/test/test_live_activity_limit_error.py +++ b/activitysmith_openapi/test/test_live_activity_limit_error.py @@ -38,7 +38,9 @@ def make_instance(self, include_optional) -> LiveActivityLimitError: error = '', message = '', limit = 56, - active = 56 + active = 56, + blocked_devices = 56, + targeted_devices = 56 ) else: return LiveActivityLimitError( diff --git a/activitysmith_openapi/test/test_live_activity_start_request.py b/activitysmith_openapi/test/test_live_activity_start_request.py index beb6dcb..cb9b91a 100644 --- a/activitysmith_openapi/test/test_live_activity_start_request.py +++ b/activitysmith_openapi/test/test_live_activity_start_request.py @@ -35,6 +35,9 @@ def make_instance(self, include_optional) -> LiveActivityStartRequest: model = LiveActivityStartRequest() if include_optional: return LiveActivityStartRequest( + metadata = { + 'key' : null + }, content_state = activitysmith_openapi.models.content_state_start.ContentStateStart( title = '', subtitle = '', diff --git a/activitysmith_openapi/test/test_live_activity_stream_delete_request.py b/activitysmith_openapi/test/test_live_activity_stream_delete_request.py index dc33c0a..3238961 100644 --- a/activitysmith_openapi/test/test_live_activity_stream_delete_request.py +++ b/activitysmith_openapi/test/test_live_activity_stream_delete_request.py @@ -35,6 +35,12 @@ def make_instance(self, include_optional) -> LiveActivityStreamDeleteRequest: model = LiveActivityStreamDeleteRequest() if include_optional: return LiveActivityStreamDeleteRequest( + metadata = { + 'key' : null + }, + tags = [ + 'gB:9JLe6iL71-aa-.Ctq:dcsc.3-8:1gAa8Xa6u61ArrlGpCQjkQVRmfnjddwcDM0' + ], content_state = activitysmith_openapi.models.stream_content_state.StreamContentState( title = '', subtitle = '', diff --git a/activitysmith_openapi/test/test_live_activity_stream_request.py b/activitysmith_openapi/test/test_live_activity_stream_request.py index d63a709..bc88f8f 100644 --- a/activitysmith_openapi/test/test_live_activity_stream_request.py +++ b/activitysmith_openapi/test/test_live_activity_stream_request.py @@ -35,6 +35,9 @@ def make_instance(self, include_optional) -> LiveActivityStreamRequest: model = LiveActivityStreamRequest() if include_optional: return LiveActivityStreamRequest( + metadata = { + 'key' : null + }, content_state = activitysmith_openapi.models.stream_content_state.StreamContentState( title = '', subtitle = '', diff --git a/activitysmith_openapi/test/test_live_activity_update_request.py b/activitysmith_openapi/test/test_live_activity_update_request.py index aa6241a..9200dc8 100644 --- a/activitysmith_openapi/test/test_live_activity_update_request.py +++ b/activitysmith_openapi/test/test_live_activity_update_request.py @@ -35,7 +35,13 @@ def make_instance(self, include_optional) -> LiveActivityUpdateRequest: model = LiveActivityUpdateRequest() if include_optional: return LiveActivityUpdateRequest( + metadata = { + 'key' : null + }, activity_id = '', + tags = [ + '0' + ], content_state = activitysmith_openapi.models.content_state_update.ContentStateUpdate( title = '', subtitle = '', diff --git a/activitysmith_openapi/test/test_metadata_value.py b/activitysmith_openapi/test/test_metadata_value.py new file mode 100644 index 0000000..e7115d2 --- /dev/null +++ b/activitysmith_openapi/test/test_metadata_value.py @@ -0,0 +1,50 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from activitysmith_openapi.models.metadata_value import MetadataValue + +class TestMetadataValue(unittest.TestCase): + """MetadataValue unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> MetadataValue: + """Test MetadataValue + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `MetadataValue` + """ + model = MetadataValue() + if include_optional: + return MetadataValue( + ) + else: + return MetadataValue( + ) + """ + + def testMetadataValue(self): + """Test MetadataValue""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/activitysmith_openapi/test/test_public_api.py b/activitysmith_openapi/test/test_public_api.py new file mode 100644 index 0000000..c529a30 --- /dev/null +++ b/activitysmith_openapi/test/test_public_api.py @@ -0,0 +1,45 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from activitysmith_openapi.api.public_api import PublicApi + + +class TestPublicApi(unittest.TestCase): + """PublicApi unit test stubs""" + + def setUp(self) -> None: + self.api = PublicApi() + + def tearDown(self) -> None: + pass + + def test_get_api_health(self) -> None: + """Test case for get_api_health + + Get API Health + """ + pass + + def test_list_public_changelog_entries(self) -> None: + """Test case for list_public_changelog_entries + + List Public Changelog Entries + """ + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/activitysmith_openapi/test/test_push_notification_request.py b/activitysmith_openapi/test/test_push_notification_request.py index 7139f55..803435e 100644 --- a/activitysmith_openapi/test/test_push_notification_request.py +++ b/activitysmith_openapi/test/test_push_notification_request.py @@ -35,11 +35,14 @@ def make_instance(self, include_optional) -> PushNotificationRequest: model = PushNotificationRequest() if include_optional: return PushNotificationRequest( + metadata = { + 'key' : null + }, title = '', message = '', subtitle = '', media = 'https:/', - redirection = 'shortcuts:/', + redirection = 'A5bTTFjjMRwg.Zbs8YayHLrJdgMvb:', actions = [ { 'key' : null diff --git a/activitysmith_openapi/test/test_send_push_notification429_response.py b/activitysmith_openapi/test/test_send_push_notification429_response.py index 5466f95..d47464f 100644 --- a/activitysmith_openapi/test/test_send_push_notification429_response.py +++ b/activitysmith_openapi/test/test_send_push_notification429_response.py @@ -38,7 +38,9 @@ def make_instance(self, include_optional) -> SendPushNotification429Response: error = '', message = '', limit = 56, - active = 56 + active = 56, + blocked_devices = 56, + targeted_devices = 56 ) else: return SendPushNotification429Response( diff --git a/activitysmith_openapi/test/test_update_app_icon_badge_count422_response.py b/activitysmith_openapi/test/test_update_app_icon_badge_count422_response.py new file mode 100644 index 0000000..23bea2e --- /dev/null +++ b/activitysmith_openapi/test/test_update_app_icon_badge_count422_response.py @@ -0,0 +1,66 @@ +# coding: utf-8 + +""" + ActivitySmith API + + Send push notifications and Live Activities to your own devices via a single API key. + + The version of the OpenAPI document: 1.0.0 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from activitysmith_openapi.models.update_app_icon_badge_count422_response import UpdateAppIconBadgeCount422Response + +class TestUpdateAppIconBadgeCount422Response(unittest.TestCase): + """UpdateAppIconBadgeCount422Response unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> UpdateAppIconBadgeCount422Response: + """Test UpdateAppIconBadgeCount422Response + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `UpdateAppIconBadgeCount422Response` + """ + model = UpdateAppIconBadgeCount422Response() + if include_optional: + return UpdateAppIconBadgeCount422Response( + error = '', + message = '', + effective_channel_slugs = [ + '' + ], + code = 'badge_device_disconnected', + badge = 0, + devices_targeted = 56, + devices_updated = 56, + users_updated = 56, + devices_notified = 56 + ) + else: + return UpdateAppIconBadgeCount422Response( + error = '', + message = '', + code = 'badge_device_disconnected', + badge = 0, + devices_updated = 56, + ) + """ + + def testUpdateAppIconBadgeCount422Response(self): + """Test UpdateAppIconBadgeCount422Response""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() From 4200becff29932cd17663af345b58c89bde2162e Mon Sep 17 00:00:00 2001 From: bardonadam Date: Tue, 15 Sep 2026 19:55:03 +0700 Subject: [PATCH 02/12] feat: prepare python SDK metadata and documentation updates Preserve native metadata values and clearing semantics, extend legacy and stream-end history fields, and align the README with the pending SDK documentation. Package versions remain unchanged; release requires separate approval. Verification: local SDK tests passed against the regenerated contract; README code-fence preservation check passed. Initiated-by: user Implemented-by: codex --- CHANGELOG.md | 10 + README.md | 424 +++++++++++++----------------- activitysmith/client.py | 44 +++- activitysmith/normalization.py | 51 ++++ tests/test_resources.py | 7 + tests/test_value_serialization.py | 144 ++++++++++ 6 files changed, 439 insertions(+), 241 deletions(-) create mode 100644 activitysmith/normalization.py create mode 100644 tests/test_value_serialization.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 0118f44..b45b7f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## Unreleased + +- Support Push Notification app deep links and final Tags/Metadata when ending a managed Live Activity stream. + +- Add Metadata to Push Notifications and Live Activity start, update, end, and stream requests, including empty-object clearing. + +- Add Tags replacement and empty-array clearing to legacy Live Activity update and end. + +- Accept native numbers and strings for Live Activity metrics and Lock Screen Widget values without generated value wrappers. + ## 1.10.0 ### New Features diff --git a/README.md b/README.md index b09e63d..538e03b 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,19 @@ -# ActivitySmith Python Library +# ActivitySmith Python SDK -The ActivitySmith Python library provides convenient access to the ActivitySmith API from Python applications. - -## Documentation - -See the [API reference](https://activitysmith.com/docs/api-reference/introduction). - -## Table of Contents - -- [Installation](#installation) -- [Setup](#setup) -- [Push Notifications](#push-notifications) - - [Send a Push Notification](#send-a-push-notification) - - [Rich Push Notifications with Media](#rich-push-notifications-with-media) - - [Actionable Push Notifications](#actionable-push-notifications) -- [Live Activities](#live-activities) - - [Start & Update Live Activity](#start--update-live-activity) - - [End Live Activity](#end-live-activity) - - [Live Activity Action](#live-activity-action) - - [Icons and Badges](#icons-and-badges) - - [Live Activity Colors](#live-activity-colors) -- [Widgets](#widgets) -- [App Icon Badge Count](#app-icon-badge-count) -- [Channels](#channels) -- [Tags](#tags) +[Documentation](https://activitysmith.com/docs/sdks/python) ## Installation -This package is available on PyPI: +Install the ActivitySmith Python SDK with pip: -```sh +```bash pip install activitysmith ``` -Alternatively, install from source with: - -```sh -python -m pip install . -``` +## Quickstart -## Setup +1. [Create an API key](https://activitysmith.com/app/keys) +2. Set `ACTIVITYSMITH_API_KEY` or pass it directly to `ActivitySmith`. ```python import os @@ -52,18 +26,16 @@ from activitysmith import ( metric, ) -activitysmith = ActivitySmith( - api_key=os.environ["ACTIVITYSMITH_API_KEY"], -) +activitysmith = ActivitySmith(api_key=os.environ["ACTIVITYSMITH_API_KEY"]) ``` ## Push Notifications ### Send a Push Notification -

- Push notification example -

+Send an immediate notification for a completed task or event. + +![Push Notification example for a new subscription event](https://cdn.activitysmith.com/features/new-subscription-push-notification.png) ```python activitysmith.notifications.send( @@ -74,24 +46,19 @@ activitysmith.notifications.send( ### Rich Push Notifications with Media -

- Rich push notification with image -

+![Rich Push Notification with image](https://cdn.activitysmith.com/features/rich-push-notification-with-image.png) ```python activitysmith.notifications.send( title="Homepage ready", message="Your agent finished the redesign.", media="https://cdn.example.com/output/homepage-v2.png", - redirection="https://github.com/acme/web/pull/482", ) ``` -Send images, videos, or audio with your push notifications, press and hold to preview media directly from the notification, then tap through to open the linked content. +Attach images, videos, or audio to your Push Notifications. Press and hold the notification to preview the media. -

- Rich push notification with audio -

+![Rich Push Notification with audio](https://cdn.activitysmith.com/features/rich-push-notification-with-audio.png) What will work: @@ -100,23 +67,33 @@ What will work: - direct video file URL: `.mp4`, `.mov`, etc. - URL that responds with a proper media `Content-Type`, even if the path has no extension +`media` cannot be combined with `actions`. + +### Push Notifications with Redirection + +Open a web page, an iPhone Shortcut, or an installed app when someone taps the notification. Set `redirection` to an HTTP, HTTPS, or Shortcuts URL, or an app deep link such as `spotify:track:123`. + +```python +activitysmith.notifications.send( + title="Homepage ready", + message="Your agent finished the redesign.", + redirection="https://github.com/acme/web/pull/482", +) +``` + ### Actionable Push Notifications -

- Actionable push notification example -

+![Actionable Push Notification with redirection and actions](https://cdn.activitysmith.com/features/actionable-push-notifications-2.png) -Push notification `redirection` and `actions` are optional. Use them to open HTTPS URLs, run a specific iPhone Shortcut with `shortcuts://run-shortcut?name=...`, or trigger backend webhook workflows. -Webhooks are executed by the ActivitySmith backend. +For expanded notification actions, `open_url` supports HTTP, HTTPS, Shortcuts, and installed app deep links. Webhooks are executed by the ActivitySmith backend and must use HTTPS. Custom app links require iOS 1.13.4 build 2 or later and an installed app that handles the URL. ```python activitysmith.notifications.send( title="New subscription 💸", message="Customer upgraded to Pro plan", - redirection="https://crm.example.com/customers/cus_9f3a1d", # Optional - actions=[ # Optional (max 4) + actions=[ action( - title="Open CRM Profile", + title="Open CRM", type="open_url", url="https://crm.example.com/customers/cus_9f3a1d", ), @@ -141,14 +118,19 @@ activitysmith.notifications.send( ## Live Activities -There are six types of Live Activities: +Choose the Live Activity type that matches what you want to show: + +- ![Stats Live Activity with six labeled sales metrics](https://cdn.activitysmith.com/features/stats-live-activity.png) **Stats**: Show up to 8 labeled values on your Lock Screen, from revenue and orders to uptime and conversion. + +- ![Metrics Live Activity with CPU and memory values](https://cdn.activitysmith.com/features/metrics-live-activity-start.png) **Metrics**: Track two related values with segmented bars, such as CPU and memory. + +- ![Segmented Progress Live Activity showing a workflow step](https://cdn.activitysmith.com/features/update-live-activity.png) **Segmented Progress**: Show progress through a known set of steps, like build, test, deploy, and verify. + +- ![Progress Live Activity showing percentage completion](https://cdn.activitysmith.com/features/progress-live-activity.png) **Progress**: Show percentage progress for jobs that move continuously toward completion. -- `stats`: best for showing business numbers side by side, such as revenue, sales, new users, conversion, refunds, or any other value you want visible at a glance -- `metrics`: best for live percentage values that change often, like server CPU, memory usage, disk usage, or error rate -- `segmented_progress`: best for anything that moves through clear stages, like deployments, onboarding flows, backups, ETL pipelines, migrations, and AI agent runs -- `progress`: best for tracking real-time progress with percentage, like tasks, backups, migrations, syncs, or uploads -- `alert`: best for status updates, such as feature adoption, reactivation, onboarding blockers, incidents, escalations, and other operational states -- `timer`: best for countdowns and elapsed runtime, like benchmark runs, uploads, backups, transcodes, and long-running jobs +- ![Alert Live Activity showing a customer reactivation update](https://cdn.activitysmith.com/features/alert-live-activity.png) **Alert**: Show status updates with a clear message, badge, and icon. When you add an action button, `color` controls the button tint. + +- ![Timer Live Activity showing a benchmark run countdown](https://cdn.activitysmith.com/features/timer-live-activity.png) **Timer**: Count down from a duration, or count up from 00:00 while a job runs. ### Start & Update Live Activity @@ -156,13 +138,9 @@ Use a stable `stream_key` to identify the metric, job, deployment, or system you #### Stats -

- Stats Live Activity stream example -

+The current Python client requires `...` for values inside Live Activity metrics. It serializes to a plain number or string in the API request. + +![Stats Live Activity stream example](https://cdn.activitysmith.com/features/stats-live-activity.png) ```python activitysmith.live_activities.stream( @@ -185,13 +163,7 @@ activitysmith.live_activities.stream( #### Metrics -

- Metrics Live Activity stream example -

+![Metrics Live Activity stream example](https://cdn.activitysmith.com/features/metrics-live-activity-start.png) ```python activitysmith.live_activities.stream( @@ -210,13 +182,7 @@ activitysmith.live_activities.stream( #### Segmented Progress -

- Segmented Progress Live Activity stream example -

+![Segmented Progress Live Activity stream example](https://cdn.activitysmith.com/features/update-live-activity.png) ```python activitysmith.live_activities.stream( @@ -233,13 +199,7 @@ activitysmith.live_activities.stream( #### Progress -

- Progress Live Activity stream example -

+![Progress Live Activity stream example](https://cdn.activitysmith.com/features/progress-live-activity.png) ```python activitysmith.live_activities.stream( @@ -255,13 +215,7 @@ activitysmith.live_activities.stream( #### Alert -

- Alert Live Activity stream example -

+![Alert Live Activity stream example](https://cdn.activitysmith.com/features/alert-live-activity.png) ```python activitysmith.live_activities.stream( @@ -278,13 +232,7 @@ activitysmith.live_activities.stream( #### Timer -

- Timer Live Activity showing a benchmark run countdown -

+![Timer Live Activity stream example](https://cdn.activitysmith.com/features/timer-live-activity.png) ```python activitysmith.live_activities.stream( @@ -301,11 +249,11 @@ activitysmith.live_activities.stream( For a countdown, send `duration_seconds`. You can update `title`, `subtitle`, `color`, or any other visible field as the work changes. Leave `duration_seconds` out unless you want to change the timer. -To start at 00:00 and count up, set `counts_down: false` and leave out `duration_seconds`. +To start at 00:00 and count up, set `counts_down=False` and leave out `duration_seconds`. ### End Live Activity -Call `end_stream(...)` with the same `stream_key` to dismiss the Live Activity. You can include final values before it is removed. By default, iOS removes the Live Activity after two minutes. Set `auto_dismiss_minutes` to choose a different dismissal time, including `0` for immediate dismissal. +Call `end_stream(...)` with the same `stream_key` to dismiss the Live Activity. You can include final values before it is removed. Set `auto_dismiss_seconds` to dismiss it after a delay in seconds, or `auto_dismiss_minutes` for minutes. Use `0` for immediate dismissal. Seconds take precedence if both are set. ```python activitysmith.live_activities.end_stream( @@ -318,27 +266,78 @@ activitysmith.live_activities.end_stream( metric(label="CPU", value=7, unit="%"), metric(label="MEM", value=38, unit="%"), ], - auto_dismiss_minutes=2, + auto_dismiss_seconds=30, ), ) ``` +### Icons and Badges + +Add more context to Live Activities with icons and badges. + +#### Icon + +Supported Live Activity types: `stats`, `metrics`, `progress`, `segmented_progress`, `alert`, and `timer`. + +![Metrics Live Activity with an SF Symbol icon on the iPhone Lock Screen](https://cdn.activitysmith.com/features/metrics-live-activity-with-icon.png) + +```python +activitysmith.live_activities.stream( + "prod-web-1", + content_state=content_state( + title="Server Health", + subtitle="prod-web-1", + type=activitysmith.live_activities.TYPE_METRICS, + icon=alert_icon("server.rack", color="blue"), + metrics=[ + metric(label="CPU", value=18, unit="%"), + metric(label="MEM", value=42, unit="%"), + ], + ), +) +``` + +The `icon.symbol` value is an Apple SF Symbol name. Browse the catalog with one of these tools: + +- [ActivitySmith app](https://apps.apple.com/us/app/activitysmith/id6752254835) - Open Settings -> SF Symbols to browse 45 hand-picked icons ready to use +- [SF Symbols](https://developer.apple.com/sf-symbols/) - Apple's official macOS app +- [Interactful](https://apps.apple.com/app/interactful/id1528095640) - free third-party iOS app listing all SF Symbols under Foundations -> Iconography + +#### Badge + +Badges are supported by `alert`, `progress`, and `segmented_progress` Live Activities. + +![Progress Live Activity with a badge on the iPhone Lock Screen](https://cdn.activitysmith.com/features/progress-live-activity-with-badge.png) + +```python +activitysmith.live_activities.stream( + "nightly-database-backup", + content_state=content_state( + title="Nightly Database Backup", + subtitle="verify restore", + type=activitysmith.live_activities.TYPE_PROGRESS, + badge=alert_badge("S3", color="cyan"), + percentage=62, + ), +) +``` + +### Live Activity Colors + +Choose from these colors for the Live Activity accent, including progress bars and action buttons, or apply them to an individual icon or badge: + +`lime`, `green`, `cyan`, `blue`, `purple`, `magenta`, `red`, `orange`, `yellow`, `gray` + ### Live Activity Action +![Metrics Live Activity with action](https://cdn.activitysmith.com/features/metrics-live-activity-action.png) + Live Activities can include an action button. -- `open_url`: open an HTTPS URL. -- `open_url` with a `shortcuts://` URL: run an Apple Shortcut, for example to open an app. +- `open_url`: open an HTTP or HTTPS URL. +- `open_url` with a `shortcuts://run-shortcut?name=...` URL: run a specific iPhone Shortcut, for example to open an app. - `webhook`: trigger a backend GET/POST workflow. -

- Live Activity with action button -

- #### Open URL action ```python @@ -356,7 +355,7 @@ activitysmith.live_activities.stream( action=action( title="Dashboard", type="open_url", - url="https://ops.example.com/servers/prod-web-1", + url="https://status.example.com/servers/prod-web-1", ), ) ``` @@ -365,13 +364,15 @@ activitysmith.live_activities.stream( ```python activitysmith.live_activities.stream( - "deploy-payments-api", + "prod-web-1", content_state=content_state( - title="Deploying payments-api", - subtitle="Running database migrations", - type="segmented_progress", - number_of_steps=5, - current_step=3, + title="Server Health", + subtitle="prod-web-1", + type="metrics", + metrics=[ + metric(label="CPU", value=76, unit="%"), + metric(label="MEM", value=52, unit="%"), + ], ), action=action( title="Chat with Jarvis", @@ -408,13 +409,7 @@ activitysmith.live_activities.stream( #### Secondary action -

- Alert Live Activity with primary and secondary action buttons -

+![Alert Live Activity with primary and secondary action buttons](https://cdn.activitysmith.com/features/live-activity-secondary-action.png) Use `secondary_action` when you want a second button beside the primary `action`. @@ -454,78 +449,15 @@ activitysmith.live_activities.stream( ) ``` -### Icons and Badges - -Add more context to Live Activities with icons and badges. - -#### Icon - -Supported Live Activity types: `stats`, `metrics`, `progress`, `segmented_progress`, `alert`, and `timer`. - -

- Metrics Live Activity with an SF Symbol icon on the iPhone Lock Screen -

- -```python -activitysmith.live_activities.stream( - "prod-web-1", - content_state=content_state( - title="Server Health", - subtitle="prod-web-1", - type=activitysmith.live_activities.TYPE_METRICS, - icon=alert_icon("server.rack", color="blue"), - metrics=[ - metric(label="CPU", value=18, unit="%"), - metric(label="MEM", value=42, unit="%"), - ], - ), -) -``` - -The `icon.symbol` value is an Apple SF Symbol name. Browse the catalog with one of these tools: +## Lock Screen Widgets -- [ActivitySmith app](https://apps.apple.com/us/app/activitysmith/id6752254835) - Open Settings -> SF Symbols to browse 45 hand-picked icons ready to use -- [SF Symbols](https://developer.apple.com/sf-symbols/) - Apple's official macOS app -- [Interactful](https://apps.apple.com/app/interactful/id1528095640) - free third-party iOS app listing all SF Symbols under Foundations -> Iconography +![Lock screen widgets](https://cdn.activitysmith.com/features/lock-screen-widgets.png) -#### Badge +ActivitySmith lets you display any value on your Lock Screen with widgets - SaaS metrics, revenue, signups, uptime, habits, or anything else you want to track. Create a metric in the [web app](https://activitysmith.com/app/widgets), then update the metric value using our API, add a widget to your lock screen and it will fetch the latest update automatically. -Badges are supported by `alert`, `progress`, and `segmented_progress` Live Activities. +![Create widget metric](https://cdn.activitysmith.com/features/create-widget-metric.png) -

- Progress Live Activity with a badge on the iPhone Lock Screen -

- -```python -activitysmith.live_activities.stream( - "nightly-database-backup", - content_state=content_state( - title="Nightly Database Backup", - subtitle="verify restore", - type=activitysmith.live_activities.TYPE_PROGRESS, - badge=alert_badge("S3", color="cyan"), - percentage=62, - ), -) -``` - -### Live Activity Colors - -Choose from these colors for the Live Activity accent, including progress bars and action buttons, or apply them to an individual icon or badge: - -`lime`, `green`, `cyan`, `blue`, `purple`, `magenta`, `red`, `orange`, `yellow`, `gray` - -## Widgets - -

- Lock screen widgets -

- -ActivitySmith lets you display any value on your Lock Screen with widgets - SaaS metrics, revenue, signups, uptime, habits, or anything else you want to track. Create a metric in the web app, then update the metric value using our API, add a widget to your lock screen and it will fetch the latest update automatically. - -

- Create widget metric -

+Use the metric key to update its value. The current Python client requires `...` here; it serializes to the number or string expected by the API. ```python activitysmith.metrics.update("deploy.success_rate", 99.9) @@ -539,87 +471,107 @@ activitysmith.metrics.update("prod.status", "healthy") ## App Icon Badge Count -

- ActivitySmith app icon with an App Icon Badge Count -

+![ActivitySmith app icon with an App Icon Badge Count](https://cdn.activitysmith.com/features/badge-count.png) Show the number you care about on your ActivitySmith app icon. Track MRR, a customer count, a stock price, or any other value you want to keep in view. -Set or update the badge value. +### Set or update the badge value ```python activitysmith.badge_count(8333) ``` -To clear the badge, set its value to 0. +### Clear the badge + +Pass `0` to clear the badge. ```python activitysmith.badge_count(0) ``` -## Channels - -Use `channels` to target specific team members or devices +## Tags -### Push Notifications +Use Tags to organize and filter Push Notification and Live Activity history. Tags are created automatically when you first use them. Sending Tags requires SDK version 1.10.0 or later. ```python activitysmith.notifications.send( title="New subscription 💸", message="Customer upgraded to Pro plan", - channels=["sales", "customer-success"], + tags=["user:382", "billing"], ) ``` -### Live Activities +On Live Activity stream updates and legacy `update` or `end` calls, omit `tags` to keep existing Tags, supply a list to replace them, or pass `tags=[]` to clear them. ```python -activitysmith.live_activities.start( - content_state=content_state( - title="Nightly Database Backup", - subtitle="verify restore", - type="progress", - percentage=62, - ), - channels=["sales", "customer-success"], +activitysmith.live_activities.update( + activity_id="YOUR_ACTIVITY_ID", + title="Customer Import", + percentage=60, + tags=[], ) ``` -### App Icon Badge Count +`end_stream` also accepts final Tags and Metadata. Omit them to preserve existing values, or supply empty collections to clear them. + +## Metadata + +Metadata adds information to Push Notification and Live Activity details in ActivitySmith. It does not appear in the notification or Live Activity on your device. ```python -activitysmith.badge_count(3, channels=["sales", "customer-success"]) +activitysmith.notifications.send( + title="New subscription 💸", + metadata={"customer_id": "382", "plan": "Pro", "amount": 29, "trial": False}, +) + +activitysmith.live_activities.stream( + "customer-import", + title="Customer Import", + type="progress", + percentage=60, + metadata={"job_id": "import-382", "records": 1200}, +) ``` -## Tags +Supported on Push Notifications, Live Activity streams (including stream ending), and legacy `start`, `update`, and `end` calls. On updates or end calls, omit `metadata` to keep it, supply an object to replace it, or send `{}` to clear it. -Use `tags` to organize and filter your Push Notification and Live Activity history. Tags are created automatically when you first use them. +Values can be strings, numbers, or booleans. Metadata supports up to 50 entries and 16 KB of JSON, with keys up to 100 characters and strings up to 4,000 characters. Nested objects, arrays, and null values are not supported. + +## Channels + +Use `channels` to target specific team members or devices when sending Push Notifications, Live Activities, or App Icon Badge Count updates. Omit it for account-wide delivery. ```python activitysmith.notifications.send( title="New subscription 💸", message="Customer upgraded to Pro plan", - tags=["user:382", "billing"], + channels=["sales", "customer-success"], ) + +activitysmith.live_activities.stream( + "nightly-backup", + content_state=content_state( + title="Nightly database backup", + type="segmented_progress", + number_of_steps=3, + current_step=1, + ), + channels=["ios-builds"], +) + +activitysmith.badge_count(3, channels=["sales", "customer-success"]) ``` ## Error Handling -```python -try: - activitysmith.notifications.send( - title="New subscription 💸", - ) -except Exception as err: - print("Request failed:", err) -``` +Wrap API calls with `try/except`. The SDK raises exceptions for non-2xx responses. Rate limit errors use the `error` and `message` fields, and Live Activity limit errors include `limit` and `active`. See [Rate Limits](https://activitysmith.com/docs/rate-limits) for details. -Request/response models are included and can be imported from `activitysmith_openapi.models`. +## Additional Resources -## Requirements +### [PyPI Package](https://pypi.org/project/activitysmith/) -- Python 3.9 or newer +Install the ActivitySmith Python SDK from PyPI -## License +### [Source Code](https://github.com/ActivitySmithHQ/activitysmith-python) -MIT +View the Python SDK source on GitHub diff --git a/activitysmith/client.py b/activitysmith/client.py index 2cf4d0a..7468aee 100644 --- a/activitysmith/client.py +++ b/activitysmith/client.py @@ -1,4 +1,5 @@ from __future__ import annotations +from .normalization import normalize_metadata_request from dataclasses import dataclass from typing import Any @@ -11,6 +12,10 @@ from activitysmith_openapi.api.push_notifications_api import PushNotificationsApi from activitysmith_openapi.api.app_icon_badges_api import AppIconBadgesApi +from activitysmith_openapi.models.metric_value_update_request import MetricValueUpdateRequest + +from .normalization import normalize_live_activity_request, normalize_metric_request + SDK_VERSION = "1.10.0" SDK_HEADER_NAME = "X-ActivitySmith-SDK" SDK_HEADER_VALUE = f"python-v{SDK_VERSION}" @@ -46,6 +51,11 @@ def _validate_push_request(request: Any) -> Any: def _metric_value_request(value_or_request: Any, timestamp: Any | None = None) -> Any: + if isinstance(value_or_request, MetricValueUpdateRequest): + if timestamp is None: + return value_or_request + return value_or_request.model_copy(update={"timestamp": timestamp}) + if isinstance(value_or_request, dict) and "value" in value_or_request: if timestamp is None: return value_or_request @@ -211,6 +221,7 @@ def _build_push_request( target: Any | None = None, channels: Any | None = None, tags: Any | None = None, + metadata: Any | None = None, ) -> Any: request_fields = _compact_dict( { @@ -223,6 +234,7 @@ def _build_push_request( "target": target, "channels": channels, "tags": tags, + "metadata": metadata, } ) @@ -284,6 +296,7 @@ def _build_live_activity_request( target: Any | None = None, channels: Any | None = None, tags: Any | None = None, + metadata: Any | None = None, ) -> Any: content_state_fields = _compact_dict( { @@ -317,11 +330,12 @@ def _build_live_activity_request( "target": target, "channels": channels, "tags": tags, + "metadata": metadata, } ) if content_state is None and not content_state_fields and not request_fields: - return request + return normalize_live_activity_request(request) if request is None: normalized: dict[str, Any] = {} @@ -355,7 +369,7 @@ def _build_live_activity_request( ) normalized.update(request_fields) - return normalized + return normalize_live_activity_request(normalized) class NotificationsResource: @@ -375,6 +389,7 @@ def send( target: Any | None = None, channels: Any | None = None, tags: Any | None = None, + metadata: Any | None = None, ): request = _build_push_request( request, @@ -387,8 +402,9 @@ def send( target=target, channels=channels, tags=tags, + metadata=metadata, ) - normalized = _validate_push_request(_normalize_channels_target(request)) + normalized = normalize_metadata_request(_validate_push_request(_normalize_channels_target(request))) return self._api.send_push_notification( push_notification_request=normalized ) @@ -462,6 +478,7 @@ def start( target: Any | None = None, channels: Any | None = None, tags: Any | None = None, + metadata: Any | None = None, ): request = _build_live_activity_request( request, @@ -488,6 +505,7 @@ def start( target=target, channels=channels, tags=tags, + metadata=metadata, ) return self._api.start_live_activity( live_activity_start_request=_normalize_channels_target(request) @@ -517,6 +535,8 @@ def update( step_color: Any | None = None, action: Any | None = None, secondary_action: Any | None = None, + tags: Any | None = None, + metadata: Any | None = None, ): request = _build_live_activity_request( request, @@ -540,6 +560,8 @@ def update( step_color=step_color, action=action, secondary_action=secondary_action, + tags=tags, + metadata=metadata, ) return self._api.update_live_activity(live_activity_update_request=request) @@ -568,6 +590,8 @@ def end( auto_dismiss_minutes: Any | None = None, action: Any | None = None, secondary_action: Any | None = None, + tags: Any | None = None, + metadata: Any | None = None, ): request = _build_live_activity_request( request, @@ -592,6 +616,8 @@ def end( auto_dismiss_minutes=auto_dismiss_minutes, action=action, secondary_action=secondary_action, + tags=tags, + metadata=metadata, ) return self._api.end_live_activity(live_activity_end_request=request) @@ -623,6 +649,7 @@ def stream( target: Any | None = None, channels: Any | None = None, tags: Any | None = None, + metadata: Any | None = None, ): request = _build_live_activity_request( request, @@ -649,6 +676,7 @@ def stream( target=target, channels=channels, tags=tags, + metadata=metadata, ) return self._api.reconcile_live_activity_stream( stream_key=stream_key, @@ -681,6 +709,8 @@ def end_stream( action: Any | None = None, secondary_action: Any | None = None, alert: Any | None = None, + tags: list[str] | None = None, + metadata: dict[str, Any] | None = None, ): request = _build_live_activity_request( request, @@ -705,6 +735,8 @@ def end_stream( action=action, secondary_action=secondary_action, alert=alert, + tags=tags, + metadata=metadata, ) return self._api.end_live_activity_stream( stream_key=stream_key, @@ -745,14 +777,16 @@ def __init__(self, api: MetricsApi) -> None: def update(self, key: str, value_or_request: Any, timestamp: Any | None = None): return self._api.update_metric_value( key=key, - metric_value_update_request=_metric_value_request(value_or_request, timestamp), + metric_value_update_request=normalize_metric_request( + _metric_value_request(value_or_request, timestamp) + ), ) # Backward-compatible generated-style alias. def update_metric_value(self, key: str, metric_value_update_request: Any): return self._api.update_metric_value( key=key, - metric_value_update_request=metric_value_update_request, + metric_value_update_request=normalize_metric_request(metric_value_update_request), ) diff --git a/activitysmith/normalization.py b/activitysmith/normalization.py new file mode 100644 index 0000000..2e4ead7 --- /dev/null +++ b/activitysmith/normalization.py @@ -0,0 +1,51 @@ +"""Adapt plain values to the generated client's union models.""" +from typing import Any + +from activitysmith_openapi.models.activity_metric_value import ActivityMetricValue +from activitysmith_openapi.models.metric_value_update_request_value import MetricValueUpdateRequestValue + + +def _wrap_value(value: Any, model: Any) -> Any: + if isinstance(value, model): + return value + if isinstance(value, bool) or not isinstance(value, (int, float, str, dict)): + raise ValueError("ActivitySmith: metric value must be a number or string") + if isinstance(value, dict): + if "actual_instance" not in value: + raise ValueError("ActivitySmith: metric value must be a number or string") + return model.model_validate(value) + return model(value) + + +def normalize_live_activity_request(request: Any) -> Any: + request = normalize_metadata_request(request) + if not isinstance(request, dict): + return request + state = request.get("content_state") + if not isinstance(state, dict) or not isinstance(state.get("metrics"), (list, tuple)): + return request + metrics = [] + for metric in state["metrics"]: + if isinstance(metric, dict) and "value" in metric: + metric = {**metric, "value": _wrap_value(metric["value"], ActivityMetricValue)} + metrics.append(metric) + return {**request, "content_state": {**state, "metrics": metrics}} + + +def normalize_metric_request(request: Any) -> Any: + if isinstance(request, dict) and "value" in request: + return {**request, "value": _wrap_value(request["value"], MetricValueUpdateRequestValue)} + return request + + +def normalize_metadata_request(request: Any) -> Any: + if not isinstance(request, dict) or "metadata" not in request: + return request + from activitysmith_openapi.models.metadata_value import MetadataValue + metadata = request["metadata"] + if not isinstance(metadata, dict): + raise ValueError("ActivitySmith: metadata must be an object") + return {**request, "metadata": { + key: value if isinstance(value, MetadataValue) else MetadataValue(value) + for key, value in metadata.items() + }} diff --git a/tests/test_resources.py b/tests/test_resources.py index b9b728c..555d8b8 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -1,3 +1,4 @@ +import json from importlib.metadata import version from activitysmith.client import ActivitySmith, action, alert_badge, alert_icon, content_state, metric @@ -20,22 +21,27 @@ def __init__(self, _api_client): self.calls = [] def start_live_activity(self, **kwargs): + kwargs = json.loads(json.dumps(kwargs, default=lambda value: value.to_dict())) self.calls.append(("start", kwargs)) return kwargs def update_live_activity(self, **kwargs): + kwargs = json.loads(json.dumps(kwargs, default=lambda value: value.to_dict())) self.calls.append(("update", kwargs)) return kwargs def end_live_activity(self, **kwargs): + kwargs = json.loads(json.dumps(kwargs, default=lambda value: value.to_dict())) self.calls.append(("end", kwargs)) return kwargs def reconcile_live_activity_stream(self, **kwargs): + kwargs = json.loads(json.dumps(kwargs, default=lambda value: value.to_dict())) self.calls.append(("stream", kwargs)) return kwargs def end_live_activity_stream(self, **kwargs): + kwargs = json.loads(json.dumps(kwargs, default=lambda value: value.to_dict())) self.calls.append(("end_stream", kwargs)) return kwargs @@ -46,6 +52,7 @@ def __init__(self, _api_client): self.calls = [] def update_metric_value(self, **kwargs): + kwargs = json.loads(json.dumps(kwargs, default=lambda value: value.to_dict())) self.calls.append(kwargs) return kwargs diff --git a/tests/test_value_serialization.py b/tests/test_value_serialization.py new file mode 100644 index 0000000..b4aa215 --- /dev/null +++ b/tests/test_value_serialization.py @@ -0,0 +1,144 @@ +from copy import deepcopy + +import pytest + +from activitysmith import ActivitySmith +from activitysmith.client import content_state, metric +from activitysmith_openapi.api_client import ApiClient +from activitysmith_openapi.models.activity_metric_value import ActivityMetricValue +from activitysmith_openapi.models.metric_value_update_request_value import MetricValueUpdateRequestValue +from activitysmith_openapi.models.metric_value_update_request import MetricValueUpdateRequest + + +class RequestCaptured(Exception): + pass + + +@pytest.fixture +def requests(monkeypatch): + captured = [] + + def capture(self, method, url, header_params=None, body=None, post_params=None, **kwargs): + captured.append(body) + raise RequestCaptured + + monkeypatch.setattr(ApiClient, "call_api", capture) + return captured + + +@pytest.mark.parametrize("value", [0, 42, 3.5, "Healthy"]) +@pytest.mark.parametrize("method", ["start", "update", "end", "stream", "end_stream"]) +@pytest.mark.parametrize("form", ["dict", "named", "helper", "wrapped"]) +def test_live_activity_metric_serializes_native_values(requests, value, method, form): + activitysmith = ActivitySmith(api_key="test") + state = {"title": "Status", "type": "stats", "metrics": [{"label": "Value", "value": value}]} + if form == "wrapped": + state["metrics"][0]["value"] = ActivityMetricValue(value) + if form == "helper": + state = content_state("Status", type="stats", metrics=[metric("Value", value)]) + original = deepcopy(state) + request = {"content_state": state} + if method in ("update", "end"): + request["activity_id"] = "activity-1" + args = ["status"] if method in ("stream", "end_stream") else [] + with pytest.raises(RequestCaptured): + if form == "named": + kwargs = dict(state) + if method in ("update", "end"): + kwargs["activity_id"] = "activity-1" + getattr(activitysmith.live_activities, method)(*args, **kwargs) + else: + getattr(activitysmith.live_activities, method)(*args, request) + assert requests[-1]["content_state"]["metrics"][0]["value"] == value + assert state == original + + +@pytest.mark.parametrize("value", [0, 42, 3.5, "Healthy"]) +@pytest.mark.parametrize("form", ["scalar", "dict", "wrapped", "model", "legacy"]) +def test_widget_metric_serializes_native_values(requests, value, form): + activitysmith = ActivitySmith(api_key="test") + request = {"value": value, "timestamp": "2026-09-15T00:00:00Z"} + if form == "wrapped": + request["value"] = MetricValueUpdateRequestValue(value) + if form == "model": + request = MetricValueUpdateRequest(value=MetricValueUpdateRequestValue(value)) + original = deepcopy(request) + with pytest.raises(RequestCaptured): + if form == "scalar": + activitysmith.metrics.update("status", value) + elif form == "legacy": + activitysmith.metrics.update_metric_value("status", request) + else: + activitysmith.metrics.update("status", request) + assert requests[-1]["value"] == value + assert request == original + + +@pytest.mark.parametrize("value", [True, [], {}]) +def test_invalid_metric_values_do_not_reach_transport(requests, value): + activitysmith = ActivitySmith(api_key="test") + with pytest.raises(ValueError): + activitysmith.metrics.update("status", value) + assert requests == [] + + +@pytest.mark.parametrize("method", ["update", "end"]) +@pytest.mark.parametrize("tags", [None, ["billing"], []]) +@pytest.mark.parametrize("form", ["dict", "named"]) +def test_legacy_tags_serialized(requests, method, tags, form): + client = ActivitySmith(api_key="test") + fields = {"activity_id": "activity-1", "content_state": {"title": "Job"}} + if tags is not None: + fields["tags"] = tags + with pytest.raises(RequestCaptured): + if form == "named": + getattr(client.live_activities, method)(**fields) + else: + getattr(client.live_activities, method)(fields) + assert ("tags" in requests[-1]) == (tags is not None) + if tags is not None: + assert requests[-1]["tags"] == tags + + +@pytest.mark.parametrize("method", ["send", "start", "update", "end", "stream", "end_stream"]) +@pytest.mark.parametrize("metadata", [None, {}, {"order": "382", "ready": False, "count": 0, "empty": "", "ratio": 1.25}]) +@pytest.mark.parametrize("form", ["dict", "named"]) +def test_metadata_serialization(requests, method, metadata, form): + client = ActivitySmith(api_key="test") + fields = {"title": "Job"} if method == "send" else {"content_state": {"title": "Job", "type": "progress"}} + if method in ("update", "end"): + fields["activity_id"] = "activity-1" + if metadata is not None: + fields["metadata"] = metadata + resource = client.notifications if method == "send" else client.live_activities + args = ["job"] if method in ("stream", "end_stream") else [] + with pytest.raises(RequestCaptured): + if form == "named": + getattr(resource, method)(*args, **fields) + else: + getattr(resource, method)(*args, fields) + body = requests[-1] + assert ("metadata" in body) == (metadata is not None) + if metadata is not None: + assert body["metadata"] == metadata + assert body["metadata"].get("ready", False) is False + assert "metadata" not in body.get("content_state", {}) + + +@pytest.mark.parametrize("url", ["http://example.com", "https://example.com", "shortcuts://run-shortcut?name=Test", "spotify://", "spotify:track:123"]) +def test_external_push_urls(requests, url): + client = ActivitySmith(api_key="test") + with pytest.raises(RequestCaptured): + client.notifications.send(title="Job", redirection=url, actions=[{"title":"Open", "type":"open_url", "url":url}]) + assert requests[-1]["redirection"] == url + assert requests[-1]["actions"][0]["url"] == url + +@pytest.mark.parametrize("tags", [None, [], ["finished"]]) +def test_end_stream_tags(requests, tags): + client = ActivitySmith(api_key="test") + with pytest.raises(RequestCaptured): + client.live_activities.end_stream("job", tags=tags, metadata={}) + assert ("tags" in requests[-1]) == (tags is not None) + if tags is not None: + assert requests[-1]["tags"] == tags + assert requests[-1]["metadata"] == {} From 1cad9f7f403cb87ccbbef6ba7a1da7fde9470444 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Tue, 15 Sep 2026 20:12:46 +0700 Subject: [PATCH 03/12] fix: remove internal operations from the generated client Use the generated output from canonical backend 49ad7b083b50f53bc3d81edb77ca6597845160a2. Health checks and app changelog are first-party operations, not part of the developer API. Preserve the existing wrapper and README preparation. Verification: SDK tests passed; generated source scanned for removed operations/models; provenance matches the deployed public contract. Initiated-by: user Implemented-by: codex --- activitysmith_openapi/__init__.py | 6 - activitysmith_openapi/api/__init__.py | 1 - activitysmith_openapi/api/public_api.py | 563 ------------------ activitysmith_openapi/docs/ChangelogEntry.md | 37 -- activitysmith_openapi/docs/ChangelogItem.md | 33 - .../docs/ChangelogListResponse.md | 29 - activitysmith_openapi/docs/HealthCheck.md | 31 - activitysmith_openapi/docs/HealthResponse.md | 32 - activitysmith_openapi/docs/PublicApi.md | 145 ----- activitysmith_openapi/models/__init__.py | 5 - .../models/changelog_entry.py | 127 ---- .../models/changelog_item.py | 110 ---- .../models/changelog_list_response.py | 95 --- activitysmith_openapi/models/health_check.py | 106 ---- .../models/health_response.py | 102 ---- activitysmith_openapi/openapi-source.json | 4 +- .../test/test_changelog_entry.py | 82 --- .../test/test_changelog_item.py | 57 -- .../test/test_changelog_list_response.py | 88 --- .../test/test_health_check.py | 56 -- .../test/test_health_response.py | 68 --- activitysmith_openapi/test/test_public_api.py | 45 -- 22 files changed, 2 insertions(+), 1820 deletions(-) delete mode 100644 activitysmith_openapi/api/public_api.py delete mode 100644 activitysmith_openapi/docs/ChangelogEntry.md delete mode 100644 activitysmith_openapi/docs/ChangelogItem.md delete mode 100644 activitysmith_openapi/docs/ChangelogListResponse.md delete mode 100644 activitysmith_openapi/docs/HealthCheck.md delete mode 100644 activitysmith_openapi/docs/HealthResponse.md delete mode 100644 activitysmith_openapi/docs/PublicApi.md delete mode 100644 activitysmith_openapi/models/changelog_entry.py delete mode 100644 activitysmith_openapi/models/changelog_item.py delete mode 100644 activitysmith_openapi/models/changelog_list_response.py delete mode 100644 activitysmith_openapi/models/health_check.py delete mode 100644 activitysmith_openapi/models/health_response.py delete mode 100644 activitysmith_openapi/test/test_changelog_entry.py delete mode 100644 activitysmith_openapi/test/test_changelog_item.py delete mode 100644 activitysmith_openapi/test/test_changelog_list_response.py delete mode 100644 activitysmith_openapi/test/test_health_check.py delete mode 100644 activitysmith_openapi/test/test_health_response.py delete mode 100644 activitysmith_openapi/test/test_public_api.py diff --git a/activitysmith_openapi/__init__.py b/activitysmith_openapi/__init__.py index e456db2..5768936 100644 --- a/activitysmith_openapi/__init__.py +++ b/activitysmith_openapi/__init__.py @@ -20,7 +20,6 @@ from activitysmith_openapi.api.app_icon_badges_api import AppIconBadgesApi from activitysmith_openapi.api.live_activities_api import LiveActivitiesApi from activitysmith_openapi.api.metrics_api import MetricsApi -from activitysmith_openapi.api.public_api import PublicApi from activitysmith_openapi.api.push_notifications_api import PushNotificationsApi # import ApiClient @@ -42,16 +41,11 @@ from activitysmith_openapi.models.app_icon_badge_count_update_request import AppIconBadgeCountUpdateRequest from activitysmith_openapi.models.app_icon_badge_count_update_response import AppIconBadgeCountUpdateResponse from activitysmith_openapi.models.bad_request_error import BadRequestError -from activitysmith_openapi.models.changelog_entry import ChangelogEntry -from activitysmith_openapi.models.changelog_item import ChangelogItem -from activitysmith_openapi.models.changelog_list_response import ChangelogListResponse from activitysmith_openapi.models.channel_target import ChannelTarget from activitysmith_openapi.models.content_state_end import ContentStateEnd from activitysmith_openapi.models.content_state_start import ContentStateStart from activitysmith_openapi.models.content_state_update import ContentStateUpdate from activitysmith_openapi.models.forbidden_error import ForbiddenError -from activitysmith_openapi.models.health_check import HealthCheck -from activitysmith_openapi.models.health_response import HealthResponse from activitysmith_openapi.models.live_activity_action import LiveActivityAction from activitysmith_openapi.models.live_activity_action_type import LiveActivityActionType from activitysmith_openapi.models.live_activity_alert_badge import LiveActivityAlertBadge diff --git a/activitysmith_openapi/api/__init__.py b/activitysmith_openapi/api/__init__.py index 3f9116e..f70481e 100644 --- a/activitysmith_openapi/api/__init__.py +++ b/activitysmith_openapi/api/__init__.py @@ -4,6 +4,5 @@ from activitysmith_openapi.api.app_icon_badges_api import AppIconBadgesApi from activitysmith_openapi.api.live_activities_api import LiveActivitiesApi from activitysmith_openapi.api.metrics_api import MetricsApi -from activitysmith_openapi.api.public_api import PublicApi from activitysmith_openapi.api.push_notifications_api import PushNotificationsApi diff --git a/activitysmith_openapi/api/public_api.py b/activitysmith_openapi/api/public_api.py deleted file mode 100644 index 8749681..0000000 --- a/activitysmith_openapi/api/public_api.py +++ /dev/null @@ -1,563 +0,0 @@ -# coding: utf-8 - -""" - ActivitySmith API - - Send push notifications and Live Activities to your own devices via a single API key. - - The version of the OpenAPI document: 1.0.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - -import warnings -from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt -from typing import Any, Dict, List, Optional, Tuple, Union -from typing_extensions import Annotated - -from pydantic import Field, StrictStr -from typing import Optional -from typing_extensions import Annotated -from activitysmith_openapi.models.changelog_list_response import ChangelogListResponse -from activitysmith_openapi.models.health_response import HealthResponse - -from activitysmith_openapi.api_client import ApiClient, RequestSerialized -from activitysmith_openapi.api_response import ApiResponse -from activitysmith_openapi.rest import RESTResponseType - - -class PublicApi: - """NOTE: This class is auto generated by OpenAPI Generator - Ref: https://openapi-generator.tech - - Do not edit the class manually. - """ - - def __init__(self, api_client=None) -> None: - if api_client is None: - api_client = ApiClient.get_default() - self.api_client = api_client - - - @validate_call - def get_api_health( - self, - _request_timeout: Union[ - None, - Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] - ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = None, - _content_type: Optional[StrictStr] = None, - _headers: Optional[Dict[StrictStr, Any]] = None, - _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> HealthResponse: - """Get API Health - - Returns the current availability of the ActivitySmith API and its required services. No authentication is required. - - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :type _request_timeout: int, tuple(int, int), optional - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the - authentication in the spec for a single request. - :type _request_auth: dict, optional - :param _content_type: force content-type for the request. - :type _content_type: str, Optional - :param _headers: set to override the headers for a single - request; this effectively ignores the headers - in the spec for a single request. - :type _headers: dict, optional - :param _host_index: set to override the host_index for a single - request; this effectively ignores the host_index - in the spec for a single request. - :type _host_index: int, optional - :return: Returns the result object. - """ # noqa: E501 - - _param = self._get_api_health_serialize( - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '200': "HealthResponse", - '503': "HealthResponse", - } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - response_data.read() - return self.api_client.response_deserialize( - response_data=response_data, - response_types_map=_response_types_map, - ).data - - - @validate_call - def get_api_health_with_http_info( - self, - _request_timeout: Union[ - None, - Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] - ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = None, - _content_type: Optional[StrictStr] = None, - _headers: Optional[Dict[StrictStr, Any]] = None, - _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> ApiResponse[HealthResponse]: - """Get API Health - - Returns the current availability of the ActivitySmith API and its required services. No authentication is required. - - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :type _request_timeout: int, tuple(int, int), optional - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the - authentication in the spec for a single request. - :type _request_auth: dict, optional - :param _content_type: force content-type for the request. - :type _content_type: str, Optional - :param _headers: set to override the headers for a single - request; this effectively ignores the headers - in the spec for a single request. - :type _headers: dict, optional - :param _host_index: set to override the host_index for a single - request; this effectively ignores the host_index - in the spec for a single request. - :type _host_index: int, optional - :return: Returns the result object. - """ # noqa: E501 - - _param = self._get_api_health_serialize( - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '200': "HealthResponse", - '503': "HealthResponse", - } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - response_data.read() - return self.api_client.response_deserialize( - response_data=response_data, - response_types_map=_response_types_map, - ) - - - @validate_call - def get_api_health_without_preload_content( - self, - _request_timeout: Union[ - None, - Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] - ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = None, - _content_type: Optional[StrictStr] = None, - _headers: Optional[Dict[StrictStr, Any]] = None, - _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> RESTResponseType: - """Get API Health - - Returns the current availability of the ActivitySmith API and its required services. No authentication is required. - - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :type _request_timeout: int, tuple(int, int), optional - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the - authentication in the spec for a single request. - :type _request_auth: dict, optional - :param _content_type: force content-type for the request. - :type _content_type: str, Optional - :param _headers: set to override the headers for a single - request; this effectively ignores the headers - in the spec for a single request. - :type _headers: dict, optional - :param _host_index: set to override the host_index for a single - request; this effectively ignores the host_index - in the spec for a single request. - :type _host_index: int, optional - :return: Returns the result object. - """ # noqa: E501 - - _param = self._get_api_health_serialize( - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '200': "HealthResponse", - '503': "HealthResponse", - } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - return response_data.response - - - def _get_api_health_serialize( - self, - _request_auth, - _content_type, - _headers, - _host_index, - ) -> RequestSerialized: - - _host = None - - _collection_formats: Dict[str, str] = { - } - - _path_params: Dict[str, str] = {} - _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} - _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} - _body_params: Optional[bytes] = None - - # process the path parameters - # process the query parameters - # process the header parameters - # process the form parameters - # process the body parameter - - - # set the HTTP header `Accept` - if 'Accept' not in _header_params: - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) - - - # authentication setting - _auth_settings: List[str] = [ - ] - - return self.api_client.param_serialize( - method='GET', - resource_path='/health', - path_params=_path_params, - query_params=_query_params, - header_params=_header_params, - body=_body_params, - post_params=_form_params, - files=_files, - auth_settings=_auth_settings, - collection_formats=_collection_formats, - _host=_host, - _request_auth=_request_auth - ) - - - - - @validate_call - def list_public_changelog_entries( - self, - platform: Annotated[Optional[StrictStr], Field(description="Platform whose published changelog entries should be returned.")] = None, - limit: Annotated[Optional[Annotated[int, Field(le=20, strict=True, ge=1)]], Field(description="Maximum number of entries to return.")] = None, - _request_timeout: Union[ - None, - Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] - ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = None, - _content_type: Optional[StrictStr] = None, - _headers: Optional[Dict[StrictStr, Any]] = None, - _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> ChangelogListResponse: - """List Public Changelog Entries - - Returns published ActivitySmith app changelog entries. No authentication is required. - - :param platform: Platform whose published changelog entries should be returned. - :type platform: str - :param limit: Maximum number of entries to return. - :type limit: int - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :type _request_timeout: int, tuple(int, int), optional - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the - authentication in the spec for a single request. - :type _request_auth: dict, optional - :param _content_type: force content-type for the request. - :type _content_type: str, Optional - :param _headers: set to override the headers for a single - request; this effectively ignores the headers - in the spec for a single request. - :type _headers: dict, optional - :param _host_index: set to override the host_index for a single - request; this effectively ignores the host_index - in the spec for a single request. - :type _host_index: int, optional - :return: Returns the result object. - """ # noqa: E501 - - _param = self._list_public_changelog_entries_serialize( - platform=platform, - limit=limit, - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '200': "ChangelogListResponse", - } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - response_data.read() - return self.api_client.response_deserialize( - response_data=response_data, - response_types_map=_response_types_map, - ).data - - - @validate_call - def list_public_changelog_entries_with_http_info( - self, - platform: Annotated[Optional[StrictStr], Field(description="Platform whose published changelog entries should be returned.")] = None, - limit: Annotated[Optional[Annotated[int, Field(le=20, strict=True, ge=1)]], Field(description="Maximum number of entries to return.")] = None, - _request_timeout: Union[ - None, - Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] - ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = None, - _content_type: Optional[StrictStr] = None, - _headers: Optional[Dict[StrictStr, Any]] = None, - _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> ApiResponse[ChangelogListResponse]: - """List Public Changelog Entries - - Returns published ActivitySmith app changelog entries. No authentication is required. - - :param platform: Platform whose published changelog entries should be returned. - :type platform: str - :param limit: Maximum number of entries to return. - :type limit: int - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :type _request_timeout: int, tuple(int, int), optional - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the - authentication in the spec for a single request. - :type _request_auth: dict, optional - :param _content_type: force content-type for the request. - :type _content_type: str, Optional - :param _headers: set to override the headers for a single - request; this effectively ignores the headers - in the spec for a single request. - :type _headers: dict, optional - :param _host_index: set to override the host_index for a single - request; this effectively ignores the host_index - in the spec for a single request. - :type _host_index: int, optional - :return: Returns the result object. - """ # noqa: E501 - - _param = self._list_public_changelog_entries_serialize( - platform=platform, - limit=limit, - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '200': "ChangelogListResponse", - } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - response_data.read() - return self.api_client.response_deserialize( - response_data=response_data, - response_types_map=_response_types_map, - ) - - - @validate_call - def list_public_changelog_entries_without_preload_content( - self, - platform: Annotated[Optional[StrictStr], Field(description="Platform whose published changelog entries should be returned.")] = None, - limit: Annotated[Optional[Annotated[int, Field(le=20, strict=True, ge=1)]], Field(description="Maximum number of entries to return.")] = None, - _request_timeout: Union[ - None, - Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] - ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = None, - _content_type: Optional[StrictStr] = None, - _headers: Optional[Dict[StrictStr, Any]] = None, - _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> RESTResponseType: - """List Public Changelog Entries - - Returns published ActivitySmith app changelog entries. No authentication is required. - - :param platform: Platform whose published changelog entries should be returned. - :type platform: str - :param limit: Maximum number of entries to return. - :type limit: int - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :type _request_timeout: int, tuple(int, int), optional - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the - authentication in the spec for a single request. - :type _request_auth: dict, optional - :param _content_type: force content-type for the request. - :type _content_type: str, Optional - :param _headers: set to override the headers for a single - request; this effectively ignores the headers - in the spec for a single request. - :type _headers: dict, optional - :param _host_index: set to override the host_index for a single - request; this effectively ignores the host_index - in the spec for a single request. - :type _host_index: int, optional - :return: Returns the result object. - """ # noqa: E501 - - _param = self._list_public_changelog_entries_serialize( - platform=platform, - limit=limit, - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '200': "ChangelogListResponse", - } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - return response_data.response - - - def _list_public_changelog_entries_serialize( - self, - platform, - limit, - _request_auth, - _content_type, - _headers, - _host_index, - ) -> RequestSerialized: - - _host = None - - _collection_formats: Dict[str, str] = { - } - - _path_params: Dict[str, str] = {} - _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} - _form_params: List[Tuple[str, str]] = [] - _files: Dict[str, Union[str, bytes]] = {} - _body_params: Optional[bytes] = None - - # process the path parameters - # process the query parameters - if platform is not None: - - _query_params.append(('platform', platform)) - - if limit is not None: - - _query_params.append(('limit', limit)) - - # process the header parameters - # process the form parameters - # process the body parameter - - - # set the HTTP header `Accept` - if 'Accept' not in _header_params: - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) - - - # authentication setting - _auth_settings: List[str] = [ - ] - - return self.api_client.param_serialize( - method='GET', - resource_path='/changelog', - path_params=_path_params, - query_params=_query_params, - header_params=_header_params, - body=_body_params, - post_params=_form_params, - files=_files, - auth_settings=_auth_settings, - collection_formats=_collection_formats, - _host=_host, - _request_auth=_request_auth - ) - - diff --git a/activitysmith_openapi/docs/ChangelogEntry.md b/activitysmith_openapi/docs/ChangelogEntry.md deleted file mode 100644 index 57c121d..0000000 --- a/activitysmith_openapi/docs/ChangelogEntry.md +++ /dev/null @@ -1,37 +0,0 @@ -# ChangelogEntry - - -## Properties - -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -**id** | **str** | | -**platform** | **str** | | -**version** | **str** | | -**title** | **str** | | -**subtitle** | **str** | | -**hero_image_url** | **str** | | -**cta_title** | **str** | | -**published_at** | **datetime** | | -**items** | [**List[ChangelogItem]**](ChangelogItem.md) | | - -## Example - -```python -from activitysmith_openapi.models.changelog_entry import ChangelogEntry - -# TODO update the JSON string below -json = "{}" -# create an instance of ChangelogEntry from a JSON string -changelog_entry_instance = ChangelogEntry.from_json(json) -# print the JSON string representation of the object -print(ChangelogEntry.to_json()) - -# convert the object into a dict -changelog_entry_dict = changelog_entry_instance.to_dict() -# create an instance of ChangelogEntry from a dict -changelog_entry_from_dict = ChangelogEntry.from_dict(changelog_entry_dict) -``` -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) - - diff --git a/activitysmith_openapi/docs/ChangelogItem.md b/activitysmith_openapi/docs/ChangelogItem.md deleted file mode 100644 index 7610a15..0000000 --- a/activitysmith_openapi/docs/ChangelogItem.md +++ /dev/null @@ -1,33 +0,0 @@ -# ChangelogItem - - -## Properties - -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -**icon** | **str** | | [optional] -**title** | **str** | | -**body** | **str** | | -**image_url** | **str** | | [optional] -**accent_color** | **str** | | [optional] - -## Example - -```python -from activitysmith_openapi.models.changelog_item import ChangelogItem - -# TODO update the JSON string below -json = "{}" -# create an instance of ChangelogItem from a JSON string -changelog_item_instance = ChangelogItem.from_json(json) -# print the JSON string representation of the object -print(ChangelogItem.to_json()) - -# convert the object into a dict -changelog_item_dict = changelog_item_instance.to_dict() -# create an instance of ChangelogItem from a dict -changelog_item_from_dict = ChangelogItem.from_dict(changelog_item_dict) -``` -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) - - diff --git a/activitysmith_openapi/docs/ChangelogListResponse.md b/activitysmith_openapi/docs/ChangelogListResponse.md deleted file mode 100644 index a7f3bab..0000000 --- a/activitysmith_openapi/docs/ChangelogListResponse.md +++ /dev/null @@ -1,29 +0,0 @@ -# ChangelogListResponse - - -## Properties - -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -**changelogs** | [**List[ChangelogEntry]**](ChangelogEntry.md) | | - -## Example - -```python -from activitysmith_openapi.models.changelog_list_response import ChangelogListResponse - -# TODO update the JSON string below -json = "{}" -# create an instance of ChangelogListResponse from a JSON string -changelog_list_response_instance = ChangelogListResponse.from_json(json) -# print the JSON string representation of the object -print(ChangelogListResponse.to_json()) - -# convert the object into a dict -changelog_list_response_dict = changelog_list_response_instance.to_dict() -# create an instance of ChangelogListResponse from a dict -changelog_list_response_from_dict = ChangelogListResponse.from_dict(changelog_list_response_dict) -``` -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) - - diff --git a/activitysmith_openapi/docs/HealthCheck.md b/activitysmith_openapi/docs/HealthCheck.md deleted file mode 100644 index d96fb1c..0000000 --- a/activitysmith_openapi/docs/HealthCheck.md +++ /dev/null @@ -1,31 +0,0 @@ -# HealthCheck - - -## Properties - -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -**name** | **str** | | -**status** | **str** | | -**duration_ms** | **int** | | - -## Example - -```python -from activitysmith_openapi.models.health_check import HealthCheck - -# TODO update the JSON string below -json = "{}" -# create an instance of HealthCheck from a JSON string -health_check_instance = HealthCheck.from_json(json) -# print the JSON string representation of the object -print(HealthCheck.to_json()) - -# convert the object into a dict -health_check_dict = health_check_instance.to_dict() -# create an instance of HealthCheck from a dict -health_check_from_dict = HealthCheck.from_dict(health_check_dict) -``` -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) - - diff --git a/activitysmith_openapi/docs/HealthResponse.md b/activitysmith_openapi/docs/HealthResponse.md deleted file mode 100644 index 7704fca..0000000 --- a/activitysmith_openapi/docs/HealthResponse.md +++ /dev/null @@ -1,32 +0,0 @@ -# HealthResponse - - -## Properties - -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -**ok** | **bool** | | -**service** | **str** | | -**timestamp** | **datetime** | | -**checks** | [**List[HealthCheck]**](HealthCheck.md) | | - -## Example - -```python -from activitysmith_openapi.models.health_response import HealthResponse - -# TODO update the JSON string below -json = "{}" -# create an instance of HealthResponse from a JSON string -health_response_instance = HealthResponse.from_json(json) -# print the JSON string representation of the object -print(HealthResponse.to_json()) - -# convert the object into a dict -health_response_dict = health_response_instance.to_dict() -# create an instance of HealthResponse from a dict -health_response_from_dict = HealthResponse.from_dict(health_response_dict) -``` -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) - - diff --git a/activitysmith_openapi/docs/PublicApi.md b/activitysmith_openapi/docs/PublicApi.md deleted file mode 100644 index 932bed6..0000000 --- a/activitysmith_openapi/docs/PublicApi.md +++ /dev/null @@ -1,145 +0,0 @@ -# activitysmith_openapi.PublicApi - -All URIs are relative to *https://activitysmith.com/api* - -Method | HTTP request | Description -------------- | ------------- | ------------- -[**get_api_health**](PublicApi.md#get_api_health) | **GET** /health | Get API Health -[**list_public_changelog_entries**](PublicApi.md#list_public_changelog_entries) | **GET** /changelog | List Public Changelog Entries - - -# **get_api_health** -> HealthResponse get_api_health() - -Get API Health - -Returns the current availability of the ActivitySmith API and its required services. No authentication is required. - -### Example - - -```python -import activitysmith_openapi -from activitysmith_openapi.models.health_response import HealthResponse -from activitysmith_openapi.rest import ApiException -from pprint import pprint - -# Defining the host is optional and defaults to https://activitysmith.com/api -# See configuration.py for a list of all supported configuration parameters. -configuration = activitysmith_openapi.Configuration( - host = "https://activitysmith.com/api" -) - - -# Enter a context with an instance of the API client -with activitysmith_openapi.ApiClient(configuration) as api_client: - # Create an instance of the API class - api_instance = activitysmith_openapi.PublicApi(api_client) - - try: - # Get API Health - api_response = api_instance.get_api_health() - print("The response of PublicApi->get_api_health:\n") - pprint(api_response) - except Exception as e: - print("Exception when calling PublicApi->get_api_health: %s\n" % e) -``` - - - -### Parameters - -This endpoint does not need any parameter. - -### Return type - -[**HealthResponse**](HealthResponse.md) - -### Authorization - -No authorization required - -### HTTP request headers - - - **Content-Type**: Not defined - - **Accept**: application/json - -### HTTP response details - -| Status code | Description | Response headers | -|-------------|-------------|------------------| -**200** | The API and its required services are available. | - | -**503** | One or more required services are unavailable. | - | - -[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) - -# **list_public_changelog_entries** -> ChangelogListResponse list_public_changelog_entries(platform=platform, limit=limit) - -List Public Changelog Entries - -Returns published ActivitySmith app changelog entries. No authentication is required. - -### Example - - -```python -import activitysmith_openapi -from activitysmith_openapi.models.changelog_list_response import ChangelogListResponse -from activitysmith_openapi.rest import ApiException -from pprint import pprint - -# Defining the host is optional and defaults to https://activitysmith.com/api -# See configuration.py for a list of all supported configuration parameters. -configuration = activitysmith_openapi.Configuration( - host = "https://activitysmith.com/api" -) - - -# Enter a context with an instance of the API client -with activitysmith_openapi.ApiClient(configuration) as api_client: - # Create an instance of the API class - api_instance = activitysmith_openapi.PublicApi(api_client) - platform = 'ios' # str | Platform whose published changelog entries should be returned. (optional) (default to 'ios') - limit = 10 # int | Maximum number of entries to return. (optional) (default to 10) - - try: - # List Public Changelog Entries - api_response = api_instance.list_public_changelog_entries(platform=platform, limit=limit) - print("The response of PublicApi->list_public_changelog_entries:\n") - pprint(api_response) - except Exception as e: - print("Exception when calling PublicApi->list_public_changelog_entries: %s\n" % e) -``` - - - -### Parameters - - -Name | Type | Description | Notes -------------- | ------------- | ------------- | ------------- - **platform** | **str**| Platform whose published changelog entries should be returned. | [optional] [default to 'ios'] - **limit** | **int**| Maximum number of entries to return. | [optional] [default to 10] - -### Return type - -[**ChangelogListResponse**](ChangelogListResponse.md) - -### Authorization - -No authorization required - -### HTTP request headers - - - **Content-Type**: Not defined - - **Accept**: application/json - -### HTTP response details - -| Status code | Description | Response headers | -|-------------|-------------|------------------| -**200** | Published changelog entries ordered from newest to oldest. | - | - -[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) - diff --git a/activitysmith_openapi/models/__init__.py b/activitysmith_openapi/models/__init__.py index 8faa131..0f8f506 100644 --- a/activitysmith_openapi/models/__init__.py +++ b/activitysmith_openapi/models/__init__.py @@ -21,16 +21,11 @@ from activitysmith_openapi.models.app_icon_badge_count_update_request import AppIconBadgeCountUpdateRequest from activitysmith_openapi.models.app_icon_badge_count_update_response import AppIconBadgeCountUpdateResponse from activitysmith_openapi.models.bad_request_error import BadRequestError -from activitysmith_openapi.models.changelog_entry import ChangelogEntry -from activitysmith_openapi.models.changelog_item import ChangelogItem -from activitysmith_openapi.models.changelog_list_response import ChangelogListResponse from activitysmith_openapi.models.channel_target import ChannelTarget from activitysmith_openapi.models.content_state_end import ContentStateEnd from activitysmith_openapi.models.content_state_start import ContentStateStart from activitysmith_openapi.models.content_state_update import ContentStateUpdate from activitysmith_openapi.models.forbidden_error import ForbiddenError -from activitysmith_openapi.models.health_check import HealthCheck -from activitysmith_openapi.models.health_response import HealthResponse from activitysmith_openapi.models.live_activity_action import LiveActivityAction from activitysmith_openapi.models.live_activity_action_type import LiveActivityActionType from activitysmith_openapi.models.live_activity_alert_badge import LiveActivityAlertBadge diff --git a/activitysmith_openapi/models/changelog_entry.py b/activitysmith_openapi/models/changelog_entry.py deleted file mode 100644 index e42b808..0000000 --- a/activitysmith_openapi/models/changelog_entry.py +++ /dev/null @@ -1,127 +0,0 @@ -# coding: utf-8 - -""" - ActivitySmith API - - Send push notifications and Live Activities to your own devices via a single API key. - - The version of the OpenAPI document: 1.0.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -from __future__ import annotations -import pprint -import re # noqa: F401 -import json - -from datetime import datetime -from pydantic import BaseModel, ConfigDict, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from activitysmith_openapi.models.changelog_item import ChangelogItem -from typing import Optional, Set -from typing_extensions import Self - -class ChangelogEntry(BaseModel): - """ - ChangelogEntry - """ # noqa: E501 - id: StrictStr - platform: StrictStr - version: StrictStr - title: StrictStr - subtitle: Optional[StrictStr] - hero_image_url: Optional[StrictStr] - cta_title: StrictStr - published_at: Optional[datetime] - items: List[ChangelogItem] - __properties: ClassVar[List[str]] = ["id", "platform", "version", "title", "subtitle", "hero_image_url", "cta_title", "published_at", "items"] - - model_config = ConfigDict( - populate_by_name=True, - validate_assignment=True, - protected_namespaces=(), - ) - - - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.model_dump(by_alias=True)) - - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead - return json.dumps(self.to_dict()) - - @classmethod - def from_json(cls, json_str: str) -> Optional[Self]: - """Create an instance of ChangelogEntry from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self) -> Dict[str, Any]: - """Return the dictionary representation of the model using alias. - - This has the following differences from calling pydantic's - `self.model_dump(by_alias=True)`: - - * `None` is only added to the output dict for nullable fields that - were set at model initialization. Other fields with value `None` - are ignored. - """ - excluded_fields: Set[str] = set([ - ]) - - _dict = self.model_dump( - by_alias=True, - exclude=excluded_fields, - exclude_none=True, - ) - # override the default output from pydantic by calling `to_dict()` of each item in items (list) - _items = [] - if self.items: - for _item in self.items: - if _item: - _items.append(_item.to_dict()) - _dict['items'] = _items - # set to None if subtitle (nullable) is None - # and model_fields_set contains the field - if self.subtitle is None and "subtitle" in self.model_fields_set: - _dict['subtitle'] = None - - # set to None if hero_image_url (nullable) is None - # and model_fields_set contains the field - if self.hero_image_url is None and "hero_image_url" in self.model_fields_set: - _dict['hero_image_url'] = None - - # set to None if published_at (nullable) is None - # and model_fields_set contains the field - if self.published_at is None and "published_at" in self.model_fields_set: - _dict['published_at'] = None - - return _dict - - @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: - """Create an instance of ChangelogEntry from a dict""" - if obj is None: - return None - - if not isinstance(obj, dict): - return cls.model_validate(obj) - - _obj = cls.model_validate({ - "id": obj.get("id"), - "platform": obj.get("platform"), - "version": obj.get("version"), - "title": obj.get("title"), - "subtitle": obj.get("subtitle"), - "hero_image_url": obj.get("hero_image_url"), - "cta_title": obj.get("cta_title"), - "published_at": obj.get("published_at"), - "items": [ChangelogItem.from_dict(_item) for _item in obj["items"]] if obj.get("items") is not None else None - }) - return _obj - - diff --git a/activitysmith_openapi/models/changelog_item.py b/activitysmith_openapi/models/changelog_item.py deleted file mode 100644 index 03e4e14..0000000 --- a/activitysmith_openapi/models/changelog_item.py +++ /dev/null @@ -1,110 +0,0 @@ -# coding: utf-8 - -""" - ActivitySmith API - - Send push notifications and Live Activities to your own devices via a single API key. - - The version of the OpenAPI document: 1.0.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -from __future__ import annotations -import pprint -import re # noqa: F401 -import json - -from pydantic import BaseModel, ConfigDict, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from typing import Optional, Set -from typing_extensions import Self - -class ChangelogItem(BaseModel): - """ - ChangelogItem - """ # noqa: E501 - icon: Optional[StrictStr] = None - title: StrictStr - body: StrictStr - image_url: Optional[StrictStr] = None - accent_color: Optional[StrictStr] = None - __properties: ClassVar[List[str]] = ["icon", "title", "body", "image_url", "accent_color"] - - model_config = ConfigDict( - populate_by_name=True, - validate_assignment=True, - protected_namespaces=(), - ) - - - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.model_dump(by_alias=True)) - - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead - return json.dumps(self.to_dict()) - - @classmethod - def from_json(cls, json_str: str) -> Optional[Self]: - """Create an instance of ChangelogItem from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self) -> Dict[str, Any]: - """Return the dictionary representation of the model using alias. - - This has the following differences from calling pydantic's - `self.model_dump(by_alias=True)`: - - * `None` is only added to the output dict for nullable fields that - were set at model initialization. Other fields with value `None` - are ignored. - """ - excluded_fields: Set[str] = set([ - ]) - - _dict = self.model_dump( - by_alias=True, - exclude=excluded_fields, - exclude_none=True, - ) - # set to None if icon (nullable) is None - # and model_fields_set contains the field - if self.icon is None and "icon" in self.model_fields_set: - _dict['icon'] = None - - # set to None if image_url (nullable) is None - # and model_fields_set contains the field - if self.image_url is None and "image_url" in self.model_fields_set: - _dict['image_url'] = None - - # set to None if accent_color (nullable) is None - # and model_fields_set contains the field - if self.accent_color is None and "accent_color" in self.model_fields_set: - _dict['accent_color'] = None - - return _dict - - @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: - """Create an instance of ChangelogItem from a dict""" - if obj is None: - return None - - if not isinstance(obj, dict): - return cls.model_validate(obj) - - _obj = cls.model_validate({ - "icon": obj.get("icon"), - "title": obj.get("title"), - "body": obj.get("body"), - "image_url": obj.get("image_url"), - "accent_color": obj.get("accent_color") - }) - return _obj - - diff --git a/activitysmith_openapi/models/changelog_list_response.py b/activitysmith_openapi/models/changelog_list_response.py deleted file mode 100644 index c09c01d..0000000 --- a/activitysmith_openapi/models/changelog_list_response.py +++ /dev/null @@ -1,95 +0,0 @@ -# coding: utf-8 - -""" - ActivitySmith API - - Send push notifications and Live Activities to your own devices via a single API key. - - The version of the OpenAPI document: 1.0.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -from __future__ import annotations -import pprint -import re # noqa: F401 -import json - -from pydantic import BaseModel, ConfigDict -from typing import Any, ClassVar, Dict, List -from activitysmith_openapi.models.changelog_entry import ChangelogEntry -from typing import Optional, Set -from typing_extensions import Self - -class ChangelogListResponse(BaseModel): - """ - ChangelogListResponse - """ # noqa: E501 - changelogs: List[ChangelogEntry] - __properties: ClassVar[List[str]] = ["changelogs"] - - model_config = ConfigDict( - populate_by_name=True, - validate_assignment=True, - protected_namespaces=(), - ) - - - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.model_dump(by_alias=True)) - - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead - return json.dumps(self.to_dict()) - - @classmethod - def from_json(cls, json_str: str) -> Optional[Self]: - """Create an instance of ChangelogListResponse from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self) -> Dict[str, Any]: - """Return the dictionary representation of the model using alias. - - This has the following differences from calling pydantic's - `self.model_dump(by_alias=True)`: - - * `None` is only added to the output dict for nullable fields that - were set at model initialization. Other fields with value `None` - are ignored. - """ - excluded_fields: Set[str] = set([ - ]) - - _dict = self.model_dump( - by_alias=True, - exclude=excluded_fields, - exclude_none=True, - ) - # override the default output from pydantic by calling `to_dict()` of each item in changelogs (list) - _items = [] - if self.changelogs: - for _item in self.changelogs: - if _item: - _items.append(_item.to_dict()) - _dict['changelogs'] = _items - return _dict - - @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: - """Create an instance of ChangelogListResponse from a dict""" - if obj is None: - return None - - if not isinstance(obj, dict): - return cls.model_validate(obj) - - _obj = cls.model_validate({ - "changelogs": [ChangelogEntry.from_dict(_item) for _item in obj["changelogs"]] if obj.get("changelogs") is not None else None - }) - return _obj - - diff --git a/activitysmith_openapi/models/health_check.py b/activitysmith_openapi/models/health_check.py deleted file mode 100644 index aca8ca0..0000000 --- a/activitysmith_openapi/models/health_check.py +++ /dev/null @@ -1,106 +0,0 @@ -# coding: utf-8 - -""" - ActivitySmith API - - Send push notifications and Live Activities to your own devices via a single API key. - - The version of the OpenAPI document: 1.0.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -from __future__ import annotations -import pprint -import re # noqa: F401 -import json - -from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator -from typing import Any, ClassVar, Dict, List -from typing_extensions import Annotated -from typing import Optional, Set -from typing_extensions import Self - -class HealthCheck(BaseModel): - """ - HealthCheck - """ # noqa: E501 - name: StrictStr - status: StrictStr - duration_ms: Annotated[int, Field(strict=True, ge=0)] - __properties: ClassVar[List[str]] = ["name", "status", "duration_ms"] - - @field_validator('name') - def name_validate_enum(cls, value): - """Validates the enum""" - if value not in set(['database', 'redis']): - raise ValueError("must be one of enum values ('database', 'redis')") - return value - - @field_validator('status') - def status_validate_enum(cls, value): - """Validates the enum""" - if value not in set(['ok', 'failed']): - raise ValueError("must be one of enum values ('ok', 'failed')") - return value - - model_config = ConfigDict( - populate_by_name=True, - validate_assignment=True, - protected_namespaces=(), - ) - - - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.model_dump(by_alias=True)) - - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead - return json.dumps(self.to_dict()) - - @classmethod - def from_json(cls, json_str: str) -> Optional[Self]: - """Create an instance of HealthCheck from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self) -> Dict[str, Any]: - """Return the dictionary representation of the model using alias. - - This has the following differences from calling pydantic's - `self.model_dump(by_alias=True)`: - - * `None` is only added to the output dict for nullable fields that - were set at model initialization. Other fields with value `None` - are ignored. - """ - excluded_fields: Set[str] = set([ - ]) - - _dict = self.model_dump( - by_alias=True, - exclude=excluded_fields, - exclude_none=True, - ) - return _dict - - @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: - """Create an instance of HealthCheck from a dict""" - if obj is None: - return None - - if not isinstance(obj, dict): - return cls.model_validate(obj) - - _obj = cls.model_validate({ - "name": obj.get("name"), - "status": obj.get("status"), - "duration_ms": obj.get("duration_ms") - }) - return _obj - - diff --git a/activitysmith_openapi/models/health_response.py b/activitysmith_openapi/models/health_response.py deleted file mode 100644 index 2016e77..0000000 --- a/activitysmith_openapi/models/health_response.py +++ /dev/null @@ -1,102 +0,0 @@ -# coding: utf-8 - -""" - ActivitySmith API - - Send push notifications and Live Activities to your own devices via a single API key. - - The version of the OpenAPI document: 1.0.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -from __future__ import annotations -import pprint -import re # noqa: F401 -import json - -from datetime import datetime -from pydantic import BaseModel, ConfigDict, StrictBool, StrictStr -from typing import Any, ClassVar, Dict, List -from activitysmith_openapi.models.health_check import HealthCheck -from typing import Optional, Set -from typing_extensions import Self - -class HealthResponse(BaseModel): - """ - HealthResponse - """ # noqa: E501 - ok: StrictBool - service: StrictStr - timestamp: datetime - checks: List[HealthCheck] - __properties: ClassVar[List[str]] = ["ok", "service", "timestamp", "checks"] - - model_config = ConfigDict( - populate_by_name=True, - validate_assignment=True, - protected_namespaces=(), - ) - - - def to_str(self) -> str: - """Returns the string representation of the model using alias""" - return pprint.pformat(self.model_dump(by_alias=True)) - - def to_json(self) -> str: - """Returns the JSON representation of the model using alias""" - # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead - return json.dumps(self.to_dict()) - - @classmethod - def from_json(cls, json_str: str) -> Optional[Self]: - """Create an instance of HealthResponse from a JSON string""" - return cls.from_dict(json.loads(json_str)) - - def to_dict(self) -> Dict[str, Any]: - """Return the dictionary representation of the model using alias. - - This has the following differences from calling pydantic's - `self.model_dump(by_alias=True)`: - - * `None` is only added to the output dict for nullable fields that - were set at model initialization. Other fields with value `None` - are ignored. - """ - excluded_fields: Set[str] = set([ - ]) - - _dict = self.model_dump( - by_alias=True, - exclude=excluded_fields, - exclude_none=True, - ) - # override the default output from pydantic by calling `to_dict()` of each item in checks (list) - _items = [] - if self.checks: - for _item in self.checks: - if _item: - _items.append(_item.to_dict()) - _dict['checks'] = _items - return _dict - - @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: - """Create an instance of HealthResponse from a dict""" - if obj is None: - return None - - if not isinstance(obj, dict): - return cls.model_validate(obj) - - _obj = cls.model_validate({ - "ok": obj.get("ok"), - "service": obj.get("service"), - "timestamp": obj.get("timestamp"), - "checks": [HealthCheck.from_dict(_item) for _item in obj["checks"]] if obj.get("checks") is not None else None - }) - return _obj - - diff --git a/activitysmith_openapi/openapi-source.json b/activitysmith_openapi/openapi-source.json index 5a616d3..dc05717 100644 --- a/activitysmith_openapi/openapi-source.json +++ b/activitysmith_openapi/openapi-source.json @@ -1,6 +1,6 @@ { "repository": "ActivitySmithHQ/activitysmith-backend", - "commit": "3cd1df5f1296777bacfad731eac9f91d27d01c6e", + "commit": "49ad7b083b50f53bc3d81edb77ca6597845160a2", "path": "openapi.json", - "sha256": "e112ddb9a069dc0ad87a123d0be1286ff0a671da505fabfdf4bb94ff6bcb444f" + "sha256": "b7e33cd485df8ddc5d7fb7b57b61106fd6f8ff3ffa7cc7bef4ac1ccbbb0cede7" } diff --git a/activitysmith_openapi/test/test_changelog_entry.py b/activitysmith_openapi/test/test_changelog_entry.py deleted file mode 100644 index 27d0ba7..0000000 --- a/activitysmith_openapi/test/test_changelog_entry.py +++ /dev/null @@ -1,82 +0,0 @@ -# coding: utf-8 - -""" - ActivitySmith API - - Send push notifications and Live Activities to your own devices via a single API key. - - The version of the OpenAPI document: 1.0.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import unittest - -from activitysmith_openapi.models.changelog_entry import ChangelogEntry - -class TestChangelogEntry(unittest.TestCase): - """ChangelogEntry unit test stubs""" - - def setUp(self): - pass - - def tearDown(self): - pass - - def make_instance(self, include_optional) -> ChangelogEntry: - """Test ChangelogEntry - include_optional is a boolean, when False only required - params are included, when True both required and - optional params are included """ - # uncomment below to create an instance of `ChangelogEntry` - """ - model = ChangelogEntry() - if include_optional: - return ChangelogEntry( - id = '', - platform = '', - version = '', - title = '', - subtitle = '', - hero_image_url = '', - cta_title = '', - published_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), - items = [ - activitysmith_openapi.models.changelog_item.ChangelogItem( - icon = '', - title = '', - body = '', - image_url = '', - accent_color = '', ) - ] - ) - else: - return ChangelogEntry( - id = '', - platform = '', - version = '', - title = '', - subtitle = '', - hero_image_url = '', - cta_title = '', - published_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), - items = [ - activitysmith_openapi.models.changelog_item.ChangelogItem( - icon = '', - title = '', - body = '', - image_url = '', - accent_color = '', ) - ], - ) - """ - - def testChangelogEntry(self): - """Test ChangelogEntry""" - # inst_req_only = self.make_instance(include_optional=False) - # inst_req_and_optional = self.make_instance(include_optional=True) - -if __name__ == '__main__': - unittest.main() diff --git a/activitysmith_openapi/test/test_changelog_item.py b/activitysmith_openapi/test/test_changelog_item.py deleted file mode 100644 index c20a159..0000000 --- a/activitysmith_openapi/test/test_changelog_item.py +++ /dev/null @@ -1,57 +0,0 @@ -# coding: utf-8 - -""" - ActivitySmith API - - Send push notifications and Live Activities to your own devices via a single API key. - - The version of the OpenAPI document: 1.0.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import unittest - -from activitysmith_openapi.models.changelog_item import ChangelogItem - -class TestChangelogItem(unittest.TestCase): - """ChangelogItem unit test stubs""" - - def setUp(self): - pass - - def tearDown(self): - pass - - def make_instance(self, include_optional) -> ChangelogItem: - """Test ChangelogItem - include_optional is a boolean, when False only required - params are included, when True both required and - optional params are included """ - # uncomment below to create an instance of `ChangelogItem` - """ - model = ChangelogItem() - if include_optional: - return ChangelogItem( - icon = '', - title = '', - body = '', - image_url = '', - accent_color = '' - ) - else: - return ChangelogItem( - title = '', - body = '', - ) - """ - - def testChangelogItem(self): - """Test ChangelogItem""" - # inst_req_only = self.make_instance(include_optional=False) - # inst_req_and_optional = self.make_instance(include_optional=True) - -if __name__ == '__main__': - unittest.main() diff --git a/activitysmith_openapi/test/test_changelog_list_response.py b/activitysmith_openapi/test/test_changelog_list_response.py deleted file mode 100644 index eae19b8..0000000 --- a/activitysmith_openapi/test/test_changelog_list_response.py +++ /dev/null @@ -1,88 +0,0 @@ -# coding: utf-8 - -""" - ActivitySmith API - - Send push notifications and Live Activities to your own devices via a single API key. - - The version of the OpenAPI document: 1.0.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import unittest - -from activitysmith_openapi.models.changelog_list_response import ChangelogListResponse - -class TestChangelogListResponse(unittest.TestCase): - """ChangelogListResponse unit test stubs""" - - def setUp(self): - pass - - def tearDown(self): - pass - - def make_instance(self, include_optional) -> ChangelogListResponse: - """Test ChangelogListResponse - include_optional is a boolean, when False only required - params are included, when True both required and - optional params are included """ - # uncomment below to create an instance of `ChangelogListResponse` - """ - model = ChangelogListResponse() - if include_optional: - return ChangelogListResponse( - changelogs = [ - activitysmith_openapi.models.changelog_entry.ChangelogEntry( - id = '', - platform = '', - version = '', - title = '', - subtitle = '', - hero_image_url = '', - cta_title = '', - published_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), - items = [ - activitysmith_openapi.models.changelog_item.ChangelogItem( - icon = '', - title = '', - body = '', - image_url = '', - accent_color = '', ) - ], ) - ] - ) - else: - return ChangelogListResponse( - changelogs = [ - activitysmith_openapi.models.changelog_entry.ChangelogEntry( - id = '', - platform = '', - version = '', - title = '', - subtitle = '', - hero_image_url = '', - cta_title = '', - published_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), - items = [ - activitysmith_openapi.models.changelog_item.ChangelogItem( - icon = '', - title = '', - body = '', - image_url = '', - accent_color = '', ) - ], ) - ], - ) - """ - - def testChangelogListResponse(self): - """Test ChangelogListResponse""" - # inst_req_only = self.make_instance(include_optional=False) - # inst_req_and_optional = self.make_instance(include_optional=True) - -if __name__ == '__main__': - unittest.main() diff --git a/activitysmith_openapi/test/test_health_check.py b/activitysmith_openapi/test/test_health_check.py deleted file mode 100644 index fe37e13..0000000 --- a/activitysmith_openapi/test/test_health_check.py +++ /dev/null @@ -1,56 +0,0 @@ -# coding: utf-8 - -""" - ActivitySmith API - - Send push notifications and Live Activities to your own devices via a single API key. - - The version of the OpenAPI document: 1.0.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import unittest - -from activitysmith_openapi.models.health_check import HealthCheck - -class TestHealthCheck(unittest.TestCase): - """HealthCheck unit test stubs""" - - def setUp(self): - pass - - def tearDown(self): - pass - - def make_instance(self, include_optional) -> HealthCheck: - """Test HealthCheck - include_optional is a boolean, when False only required - params are included, when True both required and - optional params are included """ - # uncomment below to create an instance of `HealthCheck` - """ - model = HealthCheck() - if include_optional: - return HealthCheck( - name = 'database', - status = 'ok', - duration_ms = 0 - ) - else: - return HealthCheck( - name = 'database', - status = 'ok', - duration_ms = 0, - ) - """ - - def testHealthCheck(self): - """Test HealthCheck""" - # inst_req_only = self.make_instance(include_optional=False) - # inst_req_and_optional = self.make_instance(include_optional=True) - -if __name__ == '__main__': - unittest.main() diff --git a/activitysmith_openapi/test/test_health_response.py b/activitysmith_openapi/test/test_health_response.py deleted file mode 100644 index cf55ec3..0000000 --- a/activitysmith_openapi/test/test_health_response.py +++ /dev/null @@ -1,68 +0,0 @@ -# coding: utf-8 - -""" - ActivitySmith API - - Send push notifications and Live Activities to your own devices via a single API key. - - The version of the OpenAPI document: 1.0.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import unittest - -from activitysmith_openapi.models.health_response import HealthResponse - -class TestHealthResponse(unittest.TestCase): - """HealthResponse unit test stubs""" - - def setUp(self): - pass - - def tearDown(self): - pass - - def make_instance(self, include_optional) -> HealthResponse: - """Test HealthResponse - include_optional is a boolean, when False only required - params are included, when True both required and - optional params are included """ - # uncomment below to create an instance of `HealthResponse` - """ - model = HealthResponse() - if include_optional: - return HealthResponse( - ok = True, - service = '', - timestamp = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), - checks = [ - activitysmith_openapi.models.health_check.HealthCheck( - name = 'database', - status = 'ok', - duration_ms = 0, ) - ] - ) - else: - return HealthResponse( - ok = True, - service = '', - timestamp = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), - checks = [ - activitysmith_openapi.models.health_check.HealthCheck( - name = 'database', - status = 'ok', - duration_ms = 0, ) - ], - ) - """ - - def testHealthResponse(self): - """Test HealthResponse""" - # inst_req_only = self.make_instance(include_optional=False) - # inst_req_and_optional = self.make_instance(include_optional=True) - -if __name__ == '__main__': - unittest.main() diff --git a/activitysmith_openapi/test/test_public_api.py b/activitysmith_openapi/test/test_public_api.py deleted file mode 100644 index c529a30..0000000 --- a/activitysmith_openapi/test/test_public_api.py +++ /dev/null @@ -1,45 +0,0 @@ -# coding: utf-8 - -""" - ActivitySmith API - - Send push notifications and Live Activities to your own devices via a single API key. - - The version of the OpenAPI document: 1.0.0 - Generated by OpenAPI Generator (https://openapi-generator.tech) - - Do not edit the class manually. -""" # noqa: E501 - - -import unittest - -from activitysmith_openapi.api.public_api import PublicApi - - -class TestPublicApi(unittest.TestCase): - """PublicApi unit test stubs""" - - def setUp(self) -> None: - self.api = PublicApi() - - def tearDown(self) -> None: - pass - - def test_get_api_health(self) -> None: - """Test case for get_api_health - - Get API Health - """ - pass - - def test_list_public_changelog_entries(self) -> None: - """Test case for list_public_changelog_entries - - List Public Changelog Entries - """ - pass - - -if __name__ == '__main__': - unittest.main() From d037e58f216d39fc0323716cf6ab55ff24a34098 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Tue, 15 Sep 2026 20:42:44 +0700 Subject: [PATCH 04/12] docs: align README link examples with SDK documentation Repeat supported destinations within each relevant section, use iOS Shortcut terminology, and remove app-version notes. Live Activity action support remains unchanged. Verification: README sync check passed; code fences unchanged; Markdown links and whitespace checked. Initiated-by: user Implemented-by: codex --- README.md | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 538e03b..ebf82cb 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,15 @@ What will work: ### Push Notifications with Redirection -Open a web page, an iPhone Shortcut, or an installed app when someone taps the notification. Set `redirection` to an HTTP, HTTPS, or Shortcuts URL, or an app deep link such as `spotify:track:123`. +Open a web page, run an iOS Shortcut, or open an app when someone taps the notification. `redirection` supports: + +- **HTTP/HTTPS:** Web pages, e.g. `https://example.com` +- **Shortcuts:** Run Jarvis with `shortcuts://run-shortcut?name=Jarvis` +- **App deep links:** Installed apps or specific content within them + - **Spotify:** A track, e.g. `spotify:track:6rqhFgbbKwnb9MLmUQDhG6` + - **Termius:** `termius://` to open the app + - **Claude:** `claude://code` to open the Code tab + - **ChatGPT:** `chatgpt://` to open the app ```python activitysmith.notifications.send( @@ -85,7 +93,17 @@ activitysmith.notifications.send( ![Actionable Push Notification with redirection and actions](https://cdn.activitysmith.com/features/actionable-push-notifications-2.png) -For expanded notification actions, `open_url` supports HTTP, HTTPS, Shortcuts, and installed app deep links. Webhooks are executed by the ActivitySmith backend and must use HTTPS. Custom app links require iOS 1.13.4 build 2 or later and an installed app that handles the URL. +`open_url` actions open a web page, run an iOS Shortcut, or open an app when someone taps the button. Supported links: + +- **HTTP/HTTPS:** Web pages, e.g. `https://example.com` +- **Shortcuts:** Run Jarvis with `shortcuts://run-shortcut?name=Jarvis` +- **App deep links:** Installed apps or specific content within them + - **Spotify:** A track, e.g. `spotify:track:6rqhFgbbKwnb9MLmUQDhG6` + - **Termius:** `termius://` to open the app + - **Claude:** `claude://code` to open the Code tab + - **ChatGPT:** `chatgpt://` to open the app + +Webhooks are executed by the ActivitySmith backend and must use HTTPS. ```python activitysmith.notifications.send( @@ -334,12 +352,16 @@ Choose from these colors for the Live Activity accent, including progress bars a Live Activities can include an action button. -- `open_url`: open an HTTP or HTTPS URL. -- `open_url` with a `shortcuts://run-shortcut?name=...` URL: run a specific iPhone Shortcut, for example to open an app. -- `webhook`: trigger a backend GET/POST workflow. +- `open_url`: Open a web page or run an iOS Shortcut +- `webhook`: Trigger a backend GET/POST workflow #### Open URL action +Open a web page or run an iOS Shortcut when someone taps the button. Supported links: + +- **HTTP/HTTPS:** Web pages, e.g. `https://example.com` +- **Shortcuts:** Run Jarvis with `shortcuts://run-shortcut?name=Jarvis` + ```python activitysmith.live_activities.stream( "prod-web-1", From d7f7107552ce40493ebd367a0b8c5701daee52cf Mon Sep 17 00:00:00 2001 From: bardonadam Date: Tue, 15 Sep 2026 20:48:00 +0700 Subject: [PATCH 05/12] docs: omit redundant repository resources from SDK READMEs Keep Source Code resources in website docs only. Preserve package links and omit the empty Go resource section. Verification: README converter test and six-repository sync check passed; scoped diffs checked. Initiated-by: user Implemented-by: codex --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index ebf82cb..08943e4 100644 --- a/README.md +++ b/README.md @@ -593,7 +593,3 @@ Wrap API calls with `try/except`. The SDK raises exceptions for non-2xx response ### [PyPI Package](https://pypi.org/project/activitysmith/) Install the ActivitySmith Python SDK from PyPI - -### [Source Code](https://github.com/ActivitySmithHQ/activitysmith-python) - -View the Python SDK source on GitHub From 538903d98ee044900d41c6165a23eb3df6904121 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Tue, 15 Sep 2026 20:56:12 +0700 Subject: [PATCH 06/12] docs: render Live Activity previews without list bullets Use standalone preview images and captions in SDK READMEs; retain the website grid source. Verification: converter test and six-repository sync check passed; all preview images and code fences preserved. Initiated-by: user Implemented-by: codex --- README.md | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 08943e4..35682da 100644 --- a/README.md +++ b/README.md @@ -138,17 +138,29 @@ activitysmith.notifications.send( Choose the Live Activity type that matches what you want to show: -- ![Stats Live Activity with six labeled sales metrics](https://cdn.activitysmith.com/features/stats-live-activity.png) **Stats**: Show up to 8 labeled values on your Lock Screen, from revenue and orders to uptime and conversion. +![Stats Live Activity with six labeled sales metrics](https://cdn.activitysmith.com/features/stats-live-activity.png) -- ![Metrics Live Activity with CPU and memory values](https://cdn.activitysmith.com/features/metrics-live-activity-start.png) **Metrics**: Track two related values with segmented bars, such as CPU and memory. +**Stats**: Show up to 8 labeled values on your Lock Screen, from revenue and orders to uptime and conversion. -- ![Segmented Progress Live Activity showing a workflow step](https://cdn.activitysmith.com/features/update-live-activity.png) **Segmented Progress**: Show progress through a known set of steps, like build, test, deploy, and verify. +![Metrics Live Activity with CPU and memory values](https://cdn.activitysmith.com/features/metrics-live-activity-start.png) -- ![Progress Live Activity showing percentage completion](https://cdn.activitysmith.com/features/progress-live-activity.png) **Progress**: Show percentage progress for jobs that move continuously toward completion. +**Metrics**: Track two related values with segmented bars, such as CPU and memory. -- ![Alert Live Activity showing a customer reactivation update](https://cdn.activitysmith.com/features/alert-live-activity.png) **Alert**: Show status updates with a clear message, badge, and icon. When you add an action button, `color` controls the button tint. +![Segmented Progress Live Activity showing a workflow step](https://cdn.activitysmith.com/features/update-live-activity.png) -- ![Timer Live Activity showing a benchmark run countdown](https://cdn.activitysmith.com/features/timer-live-activity.png) **Timer**: Count down from a duration, or count up from 00:00 while a job runs. +**Segmented Progress**: Show progress through a known set of steps, like build, test, deploy, and verify. + +![Progress Live Activity showing percentage completion](https://cdn.activitysmith.com/features/progress-live-activity.png) + +**Progress**: Show percentage progress for jobs that move continuously toward completion. + +![Alert Live Activity showing a customer reactivation update](https://cdn.activitysmith.com/features/alert-live-activity.png) + +**Alert**: Show status updates with a clear message, badge, and icon. When you add an action button, `color` controls the button tint. + +![Timer Live Activity showing a benchmark run countdown](https://cdn.activitysmith.com/features/timer-live-activity.png) + +**Timer**: Count down from a duration, or count up from 00:00 while a job runs. ### Start & Update Live Activity From b9f45f0eaa20950ca560f59878aa0b62ec00eccb Mon Sep 17 00:00:00 2001 From: bardonadam Date: Tue, 15 Sep 2026 20:58:19 +0700 Subject: [PATCH 07/12] docs: order Metadata before Tags and Channels Match the SDK documentation feature priority. Section content and code examples are unchanged. Verification: section contents compared before and after; README sync and whitespace checks passed. Initiated-by: user Implemented-by: codex --- README.md | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 35682da..7591afb 100644 --- a/README.md +++ b/README.md @@ -523,53 +523,53 @@ Pass `0` to clear the badge. activitysmith.badge_count(0) ``` -## Tags +## Metadata -Use Tags to organize and filter Push Notification and Live Activity history. Tags are created automatically when you first use them. Sending Tags requires SDK version 1.10.0 or later. +Metadata adds information to Push Notification and Live Activity details in ActivitySmith. It does not appear in the notification or Live Activity on your device. ```python activitysmith.notifications.send( title="New subscription 💸", - message="Customer upgraded to Pro plan", - tags=["user:382", "billing"], + metadata={"customer_id": "382", "plan": "Pro", "amount": 29, "trial": False}, ) -``` -On Live Activity stream updates and legacy `update` or `end` calls, omit `tags` to keep existing Tags, supply a list to replace them, or pass `tags=[]` to clear them. - -```python -activitysmith.live_activities.update( - activity_id="YOUR_ACTIVITY_ID", +activitysmith.live_activities.stream( + "customer-import", title="Customer Import", + type="progress", percentage=60, - tags=[], + metadata={"job_id": "import-382", "records": 1200}, ) ``` -`end_stream` also accepts final Tags and Metadata. Omit them to preserve existing values, or supply empty collections to clear them. +Supported on Push Notifications, Live Activity streams (including stream ending), and legacy `start`, `update`, and `end` calls. On updates or end calls, omit `metadata` to keep it, supply an object to replace it, or send `{}` to clear it. -## Metadata +Values can be strings, numbers, or booleans. Metadata supports up to 50 entries and 16 KB of JSON, with keys up to 100 characters and strings up to 4,000 characters. Nested objects, arrays, and null values are not supported. -Metadata adds information to Push Notification and Live Activity details in ActivitySmith. It does not appear in the notification or Live Activity on your device. +## Tags + +Use Tags to organize and filter Push Notification and Live Activity history. Tags are created automatically when you first use them. Sending Tags requires SDK version 1.10.0 or later. ```python activitysmith.notifications.send( title="New subscription 💸", - metadata={"customer_id": "382", "plan": "Pro", "amount": 29, "trial": False}, + message="Customer upgraded to Pro plan", + tags=["user:382", "billing"], ) +``` -activitysmith.live_activities.stream( - "customer-import", +On Live Activity stream updates and legacy `update` or `end` calls, omit `tags` to keep existing Tags, supply a list to replace them, or pass `tags=[]` to clear them. + +```python +activitysmith.live_activities.update( + activity_id="YOUR_ACTIVITY_ID", title="Customer Import", - type="progress", percentage=60, - metadata={"job_id": "import-382", "records": 1200}, + tags=[], ) ``` -Supported on Push Notifications, Live Activity streams (including stream ending), and legacy `start`, `update`, and `end` calls. On updates or end calls, omit `metadata` to keep it, supply an object to replace it, or send `{}` to clear it. - -Values can be strings, numbers, or booleans. Metadata supports up to 50 entries and 16 KB of JSON, with keys up to 100 characters and strings up to 4,000 characters. Nested objects, arrays, and null values are not supported. +`end_stream` also accepts final Tags and Metadata. Omit them to preserve existing values, or supply empty collections to clear them. ## Channels From c9b95a5359750720aba042bd9090070be306b9bb Mon Sep 17 00:00:00 2001 From: bardonadam Date: Tue, 15 Sep 2026 21:01:15 +0700 Subject: [PATCH 08/12] docs: simplify Metadata description Describe metadata as extra information and remove the paragraph about supported operations and replacement behavior, matching the reviewed SDK docs. Verification: README sync check passed; code examples and other sections unchanged. Initiated-by: user Implemented-by: codex --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 7591afb..ab4e290 100644 --- a/README.md +++ b/README.md @@ -525,7 +525,7 @@ activitysmith.badge_count(0) ## Metadata -Metadata adds information to Push Notification and Live Activity details in ActivitySmith. It does not appear in the notification or Live Activity on your device. +Metadata adds extra information to Push Notification and Live Activity details in ActivitySmith. It does not appear in the notification or Live Activity on your device. ```python activitysmith.notifications.send( @@ -542,8 +542,6 @@ activitysmith.live_activities.stream( ) ``` -Supported on Push Notifications, Live Activity streams (including stream ending), and legacy `start`, `update`, and `end` calls. On updates or end calls, omit `metadata` to keep it, supply an object to replace it, or send `{}` to clear it. - Values can be strings, numbers, or booleans. Metadata supports up to 50 entries and 16 KB of JSON, with keys up to 100 characters and strings up to 4,000 characters. Nested objects, arrays, and null values are not supported. ## Tags From 4d0e81a41f71e91bf1940046fef4aaaabe986aa3 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Tue, 15 Sep 2026 21:02:23 +0700 Subject: [PATCH 09/12] docs: refine Metadata example and remove redundant end-stream note Include the notification message in Metadata examples and remove the final Tags and Metadata paragraph as requested. Verification: README sync and whitespace checks passed; inspected changes limited to the requested example and paragraph. Initiated-by: user Implemented-by: codex --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index ab4e290..747877a 100644 --- a/README.md +++ b/README.md @@ -530,6 +530,7 @@ Metadata adds extra information to Push Notification and Live Activity details i ```python activitysmith.notifications.send( title="New subscription 💸", + message="Customer upgraded to Pro plan", metadata={"customer_id": "382", "plan": "Pro", "amount": 29, "trial": False}, ) @@ -567,8 +568,6 @@ activitysmith.live_activities.update( ) ``` -`end_stream` also accepts final Tags and Metadata. Omit them to preserve existing values, or supply empty collections to clear them. - ## Channels Use `channels` to target specific team members or devices when sending Push Notifications, Live Activities, or App Icon Badge Count updates. Omit it for account-wide delivery. From bdd54b79e84cde21119fe025da52aa0d7cbae612 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Tue, 15 Sep 2026 21:03:53 +0700 Subject: [PATCH 10/12] docs: format Metadata examples across multiple lines Expand metadata and content-state objects to one field per line for readability. Verification: sync check passed; example tokens and CLI JSON values preserved; Python example syntax checked. Initiated-by: user Implemented-by: codex --- README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 747877a..2b9b27d 100644 --- a/README.md +++ b/README.md @@ -531,7 +531,12 @@ Metadata adds extra information to Push Notification and Live Activity details i activitysmith.notifications.send( title="New subscription 💸", message="Customer upgraded to Pro plan", - metadata={"customer_id": "382", "plan": "Pro", "amount": 29, "trial": False}, + metadata={ + "customer_id": "382", + "plan": "Pro", + "amount": 29, + "trial": False, + }, ) activitysmith.live_activities.stream( @@ -539,7 +544,10 @@ activitysmith.live_activities.stream( title="Customer Import", type="progress", percentage=60, - metadata={"job_id": "import-382", "records": 1200}, + metadata={ + "job_id": "import-382", + "records": 1200, + }, ) ``` From cf69140bc05ac6c0737721806b854f473f0fec32 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Tue, 15 Sep 2026 21:09:02 +0700 Subject: [PATCH 11/12] docs: remove stale Python metric wrapper guidance Match the shared numeric and string widget examples; the wrapper already accepts native scalar values. Verification: README sync check passed; all six widget sections reviewed for consistent structure. Initiated-by: user Implemented-by: codex --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 2b9b27d..c4eb458 100644 --- a/README.md +++ b/README.md @@ -168,8 +168,6 @@ Use a stable `stream_key` to identify the metric, job, deployment, or system you #### Stats -The current Python client requires `...` for values inside Live Activity metrics. It serializes to a plain number or string in the API request. - ![Stats Live Activity stream example](https://cdn.activitysmith.com/features/stats-live-activity.png) ```python @@ -491,7 +489,7 @@ ActivitySmith lets you display any value on your Lock Screen with widgets - SaaS ![Create widget metric](https://cdn.activitysmith.com/features/create-widget-metric.png) -Use the metric key to update its value. The current Python client requires `...` here; it serializes to the number or string expected by the API. +Use the metric key to update its value. ```python activitysmith.metrics.update("deploy.success_rate", 99.9) From b7c37201d37ea209f6cb75cd455da644939bd05c Mon Sep 17 00:00:00 2001 From: bardonadam Date: Tue, 15 Sep 2026 21:19:13 +0700 Subject: [PATCH 12/12] chore: prepare SDK 1.11.0 feature release Bump package and SDK identification versions to 1.11.0. Keep the release summary focused on Metadata, Tags, and iOS deep links. Generated package version metadata was regenerated from the unchanged API contract. Verification: package test suite passed; version metadata and scoped diffs checked. No release tags or package publishing. Initiated-by: user Implemented-by: codex --- CHANGELOG.md | 10 ++-------- activitysmith/client.py | 2 +- activitysmith_openapi/__init__.py | 2 +- activitysmith_openapi/api_client.py | 2 +- activitysmith_openapi/configuration.py | 2 +- pyproject.toml | 2 +- 6 files changed, 7 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b45b7f1..d6bf11e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,6 @@ -## Unreleased +## 1.11.0 -- Support Push Notification app deep links and final Tags/Metadata when ending a managed Live Activity stream. - -- Add Metadata to Push Notifications and Live Activity start, update, end, and stream requests, including empty-object clearing. - -- Add Tags replacement and empty-array clearing to legacy Live Activity update and end. - -- Accept native numbers and strings for Live Activity metrics and Lock Screen Widget values without generated value wrappers. +This version adds support for Metadata and iOS deep links, and expands Tags support when updating or ending Live Activities. ## 1.10.0 diff --git a/activitysmith/client.py b/activitysmith/client.py index 7468aee..8493c3e 100644 --- a/activitysmith/client.py +++ b/activitysmith/client.py @@ -16,7 +16,7 @@ from .normalization import normalize_live_activity_request, normalize_metric_request -SDK_VERSION = "1.10.0" +SDK_VERSION = "1.11.0" SDK_HEADER_NAME = "X-ActivitySmith-SDK" SDK_HEADER_VALUE = f"python-v{SDK_VERSION}" diff --git a/activitysmith_openapi/__init__.py b/activitysmith_openapi/__init__.py index 5768936..f564b29 100644 --- a/activitysmith_openapi/__init__.py +++ b/activitysmith_openapi/__init__.py @@ -14,7 +14,7 @@ """ # noqa: E501 -__version__ = "1.10.0" +__version__ = "1.11.0" # import apis into sdk package from activitysmith_openapi.api.app_icon_badges_api import AppIconBadgesApi diff --git a/activitysmith_openapi/api_client.py b/activitysmith_openapi/api_client.py index 5132b72..cd1a411 100644 --- a/activitysmith_openapi/api_client.py +++ b/activitysmith_openapi/api_client.py @@ -88,7 +88,7 @@ def __init__( self.default_headers[header_name] = header_value self.cookie = cookie # Set default User-Agent. - self.user_agent = 'OpenAPI-Generator/1.10.0/python' + self.user_agent = 'OpenAPI-Generator/1.11.0/python' self.client_side_validation = configuration.client_side_validation def __enter__(self): diff --git a/activitysmith_openapi/configuration.py b/activitysmith_openapi/configuration.py index 28e3460..d1c9eda 100644 --- a/activitysmith_openapi/configuration.py +++ b/activitysmith_openapi/configuration.py @@ -400,7 +400,7 @@ def to_debug_report(self): "OS: {env}\n"\ "Python Version: {pyversion}\n"\ "Version of the API: 1.0.0\n"\ - "SDK Package Version: 1.10.0".\ + "SDK Package Version: 1.11.0".\ format(env=sys.platform, pyversion=sys.version) def get_host_settings(self): diff --git a/pyproject.toml b/pyproject.toml index 50a91e6..60aeeff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "activitysmith" -version = "1.10.0" +version = "1.11.0" description = "Official ActivitySmith Python SDK" readme = "README.md" requires-python = ">=3.9"