diff --git a/README.md b/README.md index 9d49345..60ee536 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,14 @@ python -m pip install . ```python import os -from activitysmith import ActivitySmith, action, content_state, metric +from activitysmith import ( + ActivitySmith, + action, + alert_badge, + alert_icon, + content_state, + metric, +) activitysmith = ActivitySmith( api_key=os.environ["ACTIVITYSMITH_API_KEY"], @@ -125,12 +132,13 @@ activitysmith.notifications.send( ## Live Activities -There are four types of Live Activities: +There are five types of Live Activities: - `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 ### Start & Update Live Activity @@ -235,6 +243,37 @@ activitysmith.live_activities.stream( ) ``` +#### Alert + +

+ Alert Live Activity stream example +

+ +```python +activitysmith.live_activities.stream( + "customer-ops", + content_state=content_state( + title="Reactivation", + message="Lumen came back after 2 weeks", + type="alert", + icon=alert_icon("cloud.sun", color="yellow"), + badge=alert_badge("Customer", color="magenta"), + ), +) +``` + +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 + +`icon` and `badge` are optional. If you omit either one, that element is not shown in the Live Activity. + ### 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. @@ -258,6 +297,7 @@ activitysmith.live_activities.end_stream( ### Live Activity Action Live Activities can include one optional action button. Use it to open a URL from the Live Activity or trigger a backend webhook. +For Alert Live Activities, set `content_state.color` to tint the action button. `icon.color` and `badge.color` only affect the icon and badge.

dict[str, Any]: + return _compact_dict( + { + "symbol": symbol, + "color": color, + } + ) + + +def alert_badge( + title: str, + *, + color: str | None = None, +) -> dict[str, Any]: + return _compact_dict( + { + "title": title, + "color": color, + } + ) + + +def _normalize_live_activity_content_state(content_state: Any) -> Any: + return content_state + + def content_state( title: str, *, type: str | None = None, subtitle: str | None = None, + message: str | None = None, + icon: Any | None = None, + badge: Any | None = None, metrics: Any | None = None, number_of_steps: int | None = None, current_step: int | None = None, @@ -138,11 +171,14 @@ def content_state( auto_dismiss_seconds: int | None = None, auto_dismiss_minutes: int | None = None, ) -> dict[str, Any]: - return _compact_dict( + state = _compact_dict( { "title": title, "subtitle": subtitle, "type": type, + "message": message, + "icon": icon, + "badge": badge, "metrics": metrics, "number_of_steps": number_of_steps, "current_step": current_step, @@ -155,6 +191,7 @@ def content_state( "auto_dismiss_minutes": auto_dismiss_minutes, } ) + return _normalize_live_activity_content_state(state) def _build_push_request( @@ -208,6 +245,7 @@ class LiveActivityColor: RED = "red" ORANGE = "orange" YELLOW = "yellow" + GRAY = "gray" def _build_live_activity_request( @@ -218,6 +256,9 @@ def _build_live_activity_request( title: Any | None = None, subtitle: Any | None = None, type: Any | None = None, + message: Any | None = None, + icon: Any | None = None, + badge: Any | None = None, metrics: Any | None = None, number_of_steps: Any | None = None, current_step: Any | None = None, @@ -238,6 +279,9 @@ def _build_live_activity_request( "title": title, "subtitle": subtitle, "type": type, + "message": message, + "icon": icon, + "badge": badge, "metrics": metrics, "number_of_steps": number_of_steps, "current_step": current_step, @@ -250,6 +294,7 @@ def _build_live_activity_request( "auto_dismiss_minutes": auto_dismiss_minutes, } ) + content_state_fields = _normalize_live_activity_content_state(content_state_fields) request_fields = _compact_dict( { "activity_id": activity_id, @@ -273,6 +318,7 @@ def _build_live_activity_request( ) if content_state is not None: + content_state = _normalize_live_activity_content_state(content_state) existing_content_state = normalized.get("content_state") if existing_content_state is None: normalized["content_state"] = content_state @@ -289,6 +335,9 @@ def _build_live_activity_request( normalized["content_state"] = {**existing_content_state, **content_state_fields} else: raise TypeError("ActivitySmith: content_state must be a dict") + normalized["content_state"] = _normalize_live_activity_content_state( + normalized["content_state"] + ) normalized.update(request_fields) return normalized @@ -337,6 +386,7 @@ class LiveActivitiesResource: TYPE_PROGRESS = "progress" TYPE_METRICS = "metrics" TYPE_STATS = "stats" + TYPE_ALERT = "alert" def __init__(self, api: LiveActivitiesApi) -> None: self._api = api @@ -351,6 +401,22 @@ def metric( ) -> dict[str, Any]: return metric(label, value, unit=unit, color=color) + @staticmethod + def alert_icon( + symbol: str, + *, + color: str | None = None, + ) -> dict[str, Any]: + return alert_icon(symbol, color=color) + + @staticmethod + def alert_badge( + title: str, + *, + color: str | None = None, + ) -> dict[str, Any]: + return alert_badge(title, color=color) + def start( self, request: Any | None = None, @@ -359,6 +425,9 @@ def start( title: Any | None = None, subtitle: Any | None = None, type: Any | None = None, + message: Any | None = None, + icon: Any | None = None, + badge: Any | None = None, metrics: Any | None = None, number_of_steps: Any | None = None, current_step: Any | None = None, @@ -378,6 +447,9 @@ def start( title=title, subtitle=subtitle, type=type, + message=message, + icon=icon, + badge=badge, metrics=metrics, number_of_steps=number_of_steps, current_step=current_step, @@ -404,6 +476,9 @@ def update( title: Any | None = None, subtitle: Any | None = None, type: Any | None = None, + message: Any | None = None, + icon: Any | None = None, + badge: Any | None = None, metrics: Any | None = None, number_of_steps: Any | None = None, current_step: Any | None = None, @@ -421,6 +496,9 @@ def update( title=title, subtitle=subtitle, type=type, + message=message, + icon=icon, + badge=badge, metrics=metrics, number_of_steps=number_of_steps, current_step=current_step, @@ -442,6 +520,9 @@ def end( title: Any | None = None, subtitle: Any | None = None, type: Any | None = None, + message: Any | None = None, + icon: Any | None = None, + badge: Any | None = None, metrics: Any | None = None, number_of_steps: Any | None = None, current_step: Any | None = None, @@ -460,6 +541,9 @@ def end( title=title, subtitle=subtitle, type=type, + message=message, + icon=icon, + badge=badge, metrics=metrics, number_of_steps=number_of_steps, current_step=current_step, @@ -482,6 +566,9 @@ def stream( title: Any | None = None, subtitle: Any | None = None, type: Any | None = None, + message: Any | None = None, + icon: Any | None = None, + badge: Any | None = None, metrics: Any | None = None, number_of_steps: Any | None = None, current_step: Any | None = None, @@ -501,6 +588,9 @@ def stream( title=title, subtitle=subtitle, type=type, + message=message, + icon=icon, + badge=badge, metrics=metrics, number_of_steps=number_of_steps, current_step=current_step, @@ -528,6 +618,9 @@ def end_stream( title: Any | None = None, subtitle: Any | None = None, type: Any | None = None, + message: Any | None = None, + icon: Any | None = None, + badge: Any | None = None, metrics: Any | None = None, number_of_steps: Any | None = None, current_step: Any | None = None, @@ -546,6 +639,9 @@ def end_stream( title=title, subtitle=subtitle, type=type, + message=message, + icon=icon, + badge=badge, metrics=metrics, number_of_steps=number_of_steps, current_step=current_step, diff --git a/activitysmith_openapi/__init__.py b/activitysmith_openapi/__init__.py index 952f3d3..50a13bc 100644 --- a/activitysmith_openapi/__init__.py +++ b/activitysmith_openapi/__init__.py @@ -14,7 +14,7 @@ """ # noqa: E501 -__version__ = "1.3.0" +__version__ = "1.4.2" # import apis into sdk package from activitysmith_openapi.api.live_activities_api import LiveActivitiesApi @@ -44,6 +44,9 @@ from activitysmith_openapi.models.forbidden_error import ForbiddenError 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 +from activitysmith_openapi.models.live_activity_alert_icon import LiveActivityAlertIcon +from activitysmith_openapi.models.live_activity_color import LiveActivityColor from activitysmith_openapi.models.live_activity_end_request import LiveActivityEndRequest from activitysmith_openapi.models.live_activity_end_response import LiveActivityEndResponse from activitysmith_openapi.models.live_activity_limit_error import LiveActivityLimitError diff --git a/activitysmith_openapi/api/live_activities_api.py b/activitysmith_openapi/api/live_activities_api.py index 20a2a2f..547edce 100644 --- a/activitysmith_openapi/api/live_activities_api.py +++ b/activitysmith_openapi/api/live_activities_api.py @@ -67,7 +67,7 @@ def end_live_activity( ) -> LiveActivityEndResponse: """End a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, and stats activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. + Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. :param live_activity_end_request: (required) :type live_activity_end_request: LiveActivityEndRequest @@ -136,7 +136,7 @@ def end_live_activity_with_http_info( ) -> ApiResponse[LiveActivityEndResponse]: """End a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, and stats activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. + Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. :param live_activity_end_request: (required) :type live_activity_end_request: LiveActivityEndRequest @@ -205,7 +205,7 @@ def end_live_activity_without_preload_content( ) -> RESTResponseType: """End a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, and stats activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. + Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. :param live_activity_end_request: (required) :type live_activity_end_request: LiveActivityEndRequest @@ -940,7 +940,7 @@ def start_live_activity( ) -> LiveActivityStartResponse: """Start a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, and stats activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. + Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. :param live_activity_start_request: (required) :type live_activity_start_request: LiveActivityStartRequest @@ -1011,7 +1011,7 @@ def start_live_activity_with_http_info( ) -> ApiResponse[LiveActivityStartResponse]: """Start a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, and stats activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. + Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. :param live_activity_start_request: (required) :type live_activity_start_request: LiveActivityStartRequest @@ -1082,7 +1082,7 @@ def start_live_activity_without_preload_content( ) -> RESTResponseType: """Start a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, and stats activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. + Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. :param live_activity_start_request: (required) :type live_activity_start_request: LiveActivityStartRequest @@ -1224,7 +1224,7 @@ def update_live_activity( ) -> LiveActivityUpdateResponse: """Update a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, and stats activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. + Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. :param live_activity_update_request: (required) :type live_activity_update_request: LiveActivityUpdateRequest @@ -1293,7 +1293,7 @@ def update_live_activity_with_http_info( ) -> ApiResponse[LiveActivityUpdateResponse]: """Update a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, and stats activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. + Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. :param live_activity_update_request: (required) :type live_activity_update_request: LiveActivityUpdateRequest @@ -1362,7 +1362,7 @@ def update_live_activity_without_preload_content( ) -> RESTResponseType: """Update a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, and stats activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. + Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. :param live_activity_update_request: (required) :type live_activity_update_request: LiveActivityUpdateRequest diff --git a/activitysmith_openapi/api_client.py b/activitysmith_openapi/api_client.py index 7e5128b..c788ea0 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.3.0/python' + self.user_agent = 'OpenAPI-Generator/1.4.2/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 51021ca..66437ec 100644 --- a/activitysmith_openapi/configuration.py +++ b/activitysmith_openapi/configuration.py @@ -393,7 +393,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.3.0".\ + "SDK Package Version: 1.4.2".\ format(env=sys.platform, pyversion=sys.version) def get_host_settings(self): diff --git a/activitysmith_openapi/docs/ContentStateEnd.md b/activitysmith_openapi/docs/ContentStateEnd.md index 9523ee9..66275af 100644 --- a/activitysmith_openapi/docs/ContentStateEnd.md +++ b/activitysmith_openapi/docs/ContentStateEnd.md @@ -1,23 +1,26 @@ # ContentStateEnd -End payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. Type is optional when ending an existing activity. You can send an updated number_of_steps here if the workflow changed after start. +End payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message, with optional icon and badge. Type is optional when ending an existing activity. You can send an updated number_of_steps here if the workflow changed after start. ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**title** | **str** | | -**subtitle** | **str** | | [optional] -**number_of_steps** | **int** | Total number of steps. Use for type=segmented_progress. Optional on end, and safe to change if the final workflow used more or fewer steps than originally planned. | [optional] -**current_step** | **int** | Current step. Use for type=segmented_progress. | [optional] -**percentage** | **float** | Progress percentage (0–100). Use for type=progress. Takes precedence over value/upper_limit if both are provided. | [optional] -**value** | **float** | Current progress value. Use with upper_limit for type=progress. | [optional] -**upper_limit** | **float** | Maximum progress value. Use with value for type=progress. | [optional] -**metrics** | [**List[ActivityMetric]**](ActivityMetric.md) | Use for type=metrics or type=stats. | [optional] -**type** | **str** | Optional. When omitted, the API uses the existing Live Activity type. | [optional] -**color** | **str** | Optional. Accent color for the Live Activity. Defaults to blue. | [optional] [default to 'blue'] -**step_color** | **str** | Optional. Overrides color for the current step. Only applies to type=segmented_progress. | [optional] -**step_colors** | **List[str]** | Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step. | [optional] +**title** | **str** | | +**subtitle** | **str** | | [optional] +**number_of_steps** | **int** | Total number of steps. Use for type=segmented_progress. Optional on end, and safe to change if the final workflow used more or fewer steps than originally planned. | [optional] +**current_step** | **int** | Current step. Use for type=segmented_progress. | [optional] +**percentage** | **float** | Progress percentage (0–100). Use for type=progress. Takes precedence over value/upper_limit if both are provided. | [optional] +**value** | **float** | Current progress value. Use with upper_limit for type=progress. | [optional] +**upper_limit** | **float** | Maximum progress value. Use with value for type=progress. | [optional] +**metrics** | [**List[ActivityMetric]**](ActivityMetric.md) | Use for type=metrics or type=stats. | [optional] +**message** | **str** | Alert message. Use for type=alert. | [optional] +**icon** | [**LiveActivityAlertIcon**](LiveActivityAlertIcon.md) | Optional SF Symbol icon for type=alert. | [optional] +**badge** | [**LiveActivityAlertBadge**](LiveActivityAlertBadge.md) | Optional badge for type=alert. | [optional] +**type** | **str** | Optional. When omitted, the API uses the existing Live Activity type. | [optional] +**color** | **str** | Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included. | [optional] +**step_color** | **str** | Optional. Overrides color for the current step. Only applies to type=segmented_progress. | [optional] +**step_colors** | **List[str]** | Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step. | [optional] **auto_dismiss_minutes** | **int** | Optional. Minutes before the ended Live Activity is dismissed. Default 3. Set 0 for immediate dismissal. iOS will dismiss ended Live Activities after ~4 hours max. | [optional] [default to 3] ## Example diff --git a/activitysmith_openapi/docs/ContentStateStart.md b/activitysmith_openapi/docs/ContentStateStart.md index bf65f9b..5ccee0a 100644 --- a/activitysmith_openapi/docs/ContentStateStart.md +++ b/activitysmith_openapi/docs/ContentStateStart.md @@ -1,23 +1,26 @@ # ContentStateStart -Start payload requires title and type. For segmented_progress include number_of_steps and current_step. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For segmented_progress, number_of_steps is not locked and can be changed in later update or end calls. +Start payload requires title and type. For segmented_progress include number_of_steps and current_step. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message, with optional icon and badge. For segmented_progress, number_of_steps is not locked and can be changed in later update or end calls. ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**title** | **str** | | -**subtitle** | **str** | | [optional] -**number_of_steps** | **int** | Total number of steps. Use for type=segmented_progress. This value can be increased or decreased later when updating or ending the same activity. | [optional] -**current_step** | **int** | Current step. Use for type=segmented_progress. | [optional] -**percentage** | **float** | Progress percentage (0–100). Use for type=progress. Takes precedence over value/upper_limit if both are provided. | [optional] -**value** | **float** | Current progress value. Use with upper_limit for type=progress. | [optional] -**upper_limit** | **float** | Maximum progress value. Use with value for type=progress. | [optional] -**metrics** | [**List[ActivityMetric]**](ActivityMetric.md) | Use for type=metrics or type=stats. | [optional] -**type** | **str** | | -**color** | **str** | Optional. Accent color for the Live Activity. Defaults to blue. | [optional] [default to 'blue'] -**step_color** | **str** | Optional. Overrides color for the current step. Only applies to type=segmented_progress. | [optional] -**step_colors** | **List[str]** | Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step. | [optional] +**title** | **str** | | +**subtitle** | **str** | | [optional] +**number_of_steps** | **int** | Total number of steps. Use for type=segmented_progress. This value can be increased or decreased later when updating or ending the same activity. | [optional] +**current_step** | **int** | Current step. Use for type=segmented_progress. | [optional] +**percentage** | **float** | Progress percentage (0–100). Use for type=progress. Takes precedence over value/upper_limit if both are provided. | [optional] +**value** | **float** | Current progress value. Use with upper_limit for type=progress. | [optional] +**upper_limit** | **float** | Maximum progress value. Use with value for type=progress. | [optional] +**metrics** | [**List[ActivityMetric]**](ActivityMetric.md) | Use for type=metrics or type=stats. | [optional] +**message** | **str** | Required for type=alert. | [optional] +**icon** | [**LiveActivityAlertIcon**](LiveActivityAlertIcon.md) | Optional SF Symbol icon for type=alert. | [optional] +**badge** | [**LiveActivityAlertBadge**](LiveActivityAlertBadge.md) | Optional badge for type=alert. | [optional] +**type** | **str** | | +**color** | **str** | Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included. | [optional] +**step_color** | **str** | Optional. Overrides color for the current step. Only applies to type=segmented_progress. | [optional] +**step_colors** | **List[str]** | Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step. | [optional] ## Example diff --git a/activitysmith_openapi/docs/ContentStateUpdate.md b/activitysmith_openapi/docs/ContentStateUpdate.md index fc2f398..933312a 100644 --- a/activitysmith_openapi/docs/ContentStateUpdate.md +++ b/activitysmith_openapi/docs/ContentStateUpdate.md @@ -1,23 +1,26 @@ # ContentStateUpdate -Update payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. Type is optional when updating an existing activity. You can increase or decrease number_of_steps during updates. +Update payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message, with optional icon and badge. Type is optional when updating an existing activity. You can increase or decrease number_of_steps during updates. ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**title** | **str** | | -**subtitle** | **str** | | [optional] -**number_of_steps** | **int** | Total number of steps. Use for type=segmented_progress. Optional on update, and safe to change if the workflow gains or loses steps. | [optional] -**current_step** | **int** | Current step. Use for type=segmented_progress. | [optional] -**percentage** | **float** | Progress percentage (0–100). Use for type=progress. Takes precedence over value/upper_limit if both are provided. | [optional] -**value** | **float** | Current progress value. Use with upper_limit for type=progress. | [optional] -**upper_limit** | **float** | Maximum progress value. Use with value for type=progress. | [optional] -**metrics** | [**List[ActivityMetric]**](ActivityMetric.md) | Use for type=metrics or type=stats. | [optional] -**type** | **str** | Optional. When omitted, the API uses the existing Live Activity type. | [optional] -**color** | **str** | Optional. Accent color for the Live Activity. Defaults to blue. | [optional] [default to 'blue'] -**step_color** | **str** | Optional. Overrides color for the current step. Only applies to type=segmented_progress. | [optional] -**step_colors** | **List[str]** | Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step. | [optional] +**title** | **str** | | +**subtitle** | **str** | | [optional] +**number_of_steps** | **int** | Total number of steps. Use for type=segmented_progress. Optional on update, and safe to change if the workflow gains or loses steps. | [optional] +**current_step** | **int** | Current step. Use for type=segmented_progress. | [optional] +**percentage** | **float** | Progress percentage (0–100). Use for type=progress. Takes precedence over value/upper_limit if both are provided. | [optional] +**value** | **float** | Current progress value. Use with upper_limit for type=progress. | [optional] +**upper_limit** | **float** | Maximum progress value. Use with value for type=progress. | [optional] +**metrics** | [**List[ActivityMetric]**](ActivityMetric.md) | Use for type=metrics or type=stats. | [optional] +**message** | **str** | Alert message. Use for type=alert. | [optional] +**icon** | [**LiveActivityAlertIcon**](LiveActivityAlertIcon.md) | Optional SF Symbol icon for type=alert. | [optional] +**badge** | [**LiveActivityAlertBadge**](LiveActivityAlertBadge.md) | Optional badge for type=alert. | [optional] +**type** | **str** | Optional. When omitted, the API uses the existing Live Activity type. | [optional] +**color** | **str** | Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included. | [optional] +**step_color** | **str** | Optional. Overrides color for the current step. Only applies to type=segmented_progress. | [optional] +**step_colors** | **List[str]** | Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step. | [optional] ## Example diff --git a/activitysmith_openapi/docs/LiveActivitiesApi.md b/activitysmith_openapi/docs/LiveActivitiesApi.md index dfa668e..1f32675 100644 --- a/activitysmith_openapi/docs/LiveActivitiesApi.md +++ b/activitysmith_openapi/docs/LiveActivitiesApi.md @@ -16,7 +16,7 @@ Method | HTTP request | Description End a Live Activity (legacy manual lifecycle) -Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, and stats activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. +Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. ### Example @@ -266,7 +266,7 @@ Name | Type | Description | Notes Start a Live Activity (legacy manual lifecycle) -Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, and stats activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. +Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. ### Example @@ -349,7 +349,7 @@ Name | Type | Description | Notes Update a Live Activity (legacy manual lifecycle) -Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, and stats activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. +Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. ### Example diff --git a/activitysmith_openapi/docs/LiveActivityAlertBadge.md b/activitysmith_openapi/docs/LiveActivityAlertBadge.md new file mode 100644 index 0000000..81fc3e0 --- /dev/null +++ b/activitysmith_openapi/docs/LiveActivityAlertBadge.md @@ -0,0 +1,31 @@ +# LiveActivityAlertBadge + +Optional badge for Alert Live Activities. + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**title** | **str** | | +**color** | [**LiveActivityColor**](LiveActivityColor.md) | Optional badge color. | [optional] + +## Example + +```python +from activitysmith_openapi.models.live_activity_alert_badge import LiveActivityAlertBadge + +# TODO update the JSON string below +json = "{}" +# create an instance of LiveActivityAlertBadge from a JSON string +live_activity_alert_badge_instance = LiveActivityAlertBadge.from_json(json) +# print the JSON string representation of the object +print(LiveActivityAlertBadge.to_json()) + +# convert the object into a dict +live_activity_alert_badge_dict = live_activity_alert_badge_instance.to_dict() +# create an instance of LiveActivityAlertBadge from a dict +live_activity_alert_badge_from_dict = LiveActivityAlertBadge.from_dict(live_activity_alert_badge_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/LiveActivityAlertIcon.md b/activitysmith_openapi/docs/LiveActivityAlertIcon.md new file mode 100644 index 0000000..fa25371 --- /dev/null +++ b/activitysmith_openapi/docs/LiveActivityAlertIcon.md @@ -0,0 +1,31 @@ +# LiveActivityAlertIcon + +Optional SF Symbol icon for Alert Live Activities. + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**symbol** | **str** | Apple SF Symbol name. | +**color** | [**LiveActivityColor**](LiveActivityColor.md) | Optional icon color. | [optional] + +## Example + +```python +from activitysmith_openapi.models.live_activity_alert_icon import LiveActivityAlertIcon + +# TODO update the JSON string below +json = "{}" +# create an instance of LiveActivityAlertIcon from a JSON string +live_activity_alert_icon_instance = LiveActivityAlertIcon.from_json(json) +# print the JSON string representation of the object +print(LiveActivityAlertIcon.to_json()) + +# convert the object into a dict +live_activity_alert_icon_dict = live_activity_alert_icon_instance.to_dict() +# create an instance of LiveActivityAlertIcon from a dict +live_activity_alert_icon_from_dict = LiveActivityAlertIcon.from_dict(live_activity_alert_icon_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/LiveActivityColor.md b/activitysmith_openapi/docs/LiveActivityColor.md new file mode 100644 index 0000000..343a0a7 --- /dev/null +++ b/activitysmith_openapi/docs/LiveActivityColor.md @@ -0,0 +1,28 @@ +# LiveActivityColor + + +## Enum + +* `LIME` (value: `'lime'`) + +* `GREEN` (value: `'green'`) + +* `CYAN` (value: `'cyan'`) + +* `BLUE` (value: `'blue'`) + +* `PURPLE` (value: `'purple'`) + +* `MAGENTA` (value: `'magenta'`) + +* `RED` (value: `'red'`) + +* `ORANGE` (value: `'orange'`) + +* `YELLOW` (value: `'yellow'`) + +* `GRAY` (value: `'gray'`) + +[[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/StreamContentState.md b/activitysmith_openapi/docs/StreamContentState.md index 1175334..da407b4 100644 --- a/activitysmith_openapi/docs/StreamContentState.md +++ b/activitysmith_openapi/docs/StreamContentState.md @@ -1,25 +1,28 @@ # StreamContentState -Current state for a managed Live Activity stream. Include type on the first PUT, and whenever the stream may need to start a fresh activity. Supports segmented_progress, progress, metrics, and stats types. +Current state for a managed Live Activity stream. Include type on the first PUT, and whenever the stream may need to start a fresh activity. Supports segmented_progress, progress, metrics, stats, and alert types. ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**title** | **str** | | -**subtitle** | **str** | | [optional] -**number_of_steps** | **int** | Use for segmented_progress. | [optional] -**current_step** | **int** | Use for segmented_progress. | [optional] -**percentage** | **float** | Use for progress. Takes precedence over value/upper_limit if both are provided. | [optional] -**value** | **float** | Current progress value. Use with upper_limit for progress. | [optional] -**upper_limit** | **float** | Maximum progress value. Use with value for progress. | [optional] -**type** | **str** | Required on the first PUT or whenever the stream cannot infer the current activity type. | [optional] -**color** | **str** | Optional. Accent color for the Live Activity. Defaults to blue. | [optional] [default to 'blue'] -**step_color** | **str** | Optional. Overrides color for the current step. Only applies to segmented_progress. | [optional] -**step_colors** | **List[str]** | Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step. | [optional] -**metrics** | [**List[ActivityMetric]**](ActivityMetric.md) | Use for metrics and stats activities. | [optional] -**auto_dismiss_seconds** | **int** | Optional. Seconds before the ended Live Activity is dismissed. | [optional] -**auto_dismiss_minutes** | **int** | Optional. Minutes before the ended Live Activity is dismissed. | [optional] +**title** | **str** | | +**subtitle** | **str** | | [optional] +**number_of_steps** | **int** | Use for segmented_progress. | [optional] +**current_step** | **int** | Use for segmented_progress. | [optional] +**percentage** | **float** | Use for progress. Takes precedence over value/upper_limit if both are provided. | [optional] +**value** | **float** | Current progress value. Use with upper_limit for progress. | [optional] +**upper_limit** | **float** | Maximum progress value. Use with value for progress. | [optional] +**type** | **str** | Required on the first PUT or whenever the stream cannot infer the current activity type. | [optional] +**color** | **str** | Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included. | [optional] +**step_color** | **str** | Optional. Overrides color for the current step. Only applies to segmented_progress. | [optional] +**step_colors** | **List[str]** | Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step. | [optional] +**metrics** | [**List[ActivityMetric]**](ActivityMetric.md) | Use for metrics and stats activities. | [optional] +**message** | **str** | Required for type=alert. | [optional] +**icon** | [**LiveActivityAlertIcon**](LiveActivityAlertIcon.md) | Optional SF Symbol icon for type=alert. | [optional] +**badge** | [**LiveActivityAlertBadge**](LiveActivityAlertBadge.md) | Optional badge for type=alert. | [optional] +**auto_dismiss_seconds** | **int** | Optional. Seconds before the ended Live Activity is dismissed. | [optional] +**auto_dismiss_minutes** | **int** | Optional. Minutes before the ended Live Activity is dismissed. | [optional] ## Example diff --git a/activitysmith_openapi/models/__init__.py b/activitysmith_openapi/models/__init__.py index 20012de..10f918d 100644 --- a/activitysmith_openapi/models/__init__.py +++ b/activitysmith_openapi/models/__init__.py @@ -25,6 +25,9 @@ from activitysmith_openapi.models.forbidden_error import ForbiddenError 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 +from activitysmith_openapi.models.live_activity_alert_icon import LiveActivityAlertIcon +from activitysmith_openapi.models.live_activity_color import LiveActivityColor from activitysmith_openapi.models.live_activity_end_request import LiveActivityEndRequest from activitysmith_openapi.models.live_activity_end_response import LiveActivityEndResponse from activitysmith_openapi.models.live_activity_limit_error import LiveActivityLimitError diff --git a/activitysmith_openapi/models/activity_metric.py b/activitysmith_openapi/models/activity_metric.py index 980f03f..8a45c63 100644 --- a/activitysmith_openapi/models/activity_metric.py +++ b/activitysmith_openapi/models/activity_metric.py @@ -41,8 +41,8 @@ def color_validate_enum(cls, value): if value is None: return value - if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow']): - raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow')") + if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray']): + raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray')") return value model_config = ConfigDict( diff --git a/activitysmith_openapi/models/content_state_end.py b/activitysmith_openapi/models/content_state_end.py index 078baaf..7e41627 100644 --- a/activitysmith_openapi/models/content_state_end.py +++ b/activitysmith_openapi/models/content_state_end.py @@ -21,12 +21,14 @@ from typing import Any, ClassVar, Dict, List, Optional, Union from typing_extensions import Annotated from activitysmith_openapi.models.activity_metric import ActivityMetric +from activitysmith_openapi.models.live_activity_alert_badge import LiveActivityAlertBadge +from activitysmith_openapi.models.live_activity_alert_icon import LiveActivityAlertIcon from typing import Optional, Set from typing_extensions import Self class ContentStateEnd(BaseModel): """ - End payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. Type is optional when ending an existing activity. You can send an updated number_of_steps here if the workflow changed after start. + End payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message, with optional icon and badge. Type is optional when ending an existing activity. You can send an updated number_of_steps here if the workflow changed after start. """ # noqa: E501 title: StrictStr subtitle: Optional[StrictStr] = None @@ -36,13 +38,16 @@ class ContentStateEnd(BaseModel): value: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Current progress value. Use with upper_limit for type=progress.") upper_limit: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Maximum progress value. Use with value for type=progress.") metrics: Optional[Annotated[List[ActivityMetric], Field(min_length=1, max_length=8)]] = Field(default=None, description="Use for type=metrics or type=stats.") + message: Optional[Annotated[str, Field(min_length=1, strict=True)]] = Field(default=None, description="Alert message. Use for type=alert.") + icon: Optional[LiveActivityAlertIcon] = Field(default=None, description="Optional SF Symbol icon for type=alert.") + badge: Optional[LiveActivityAlertBadge] = Field(default=None, description="Optional badge for type=alert.") type: Optional[StrictStr] = Field(default=None, description="Optional. When omitted, the API uses the existing Live Activity type.") - color: Optional[StrictStr] = Field(default='blue', description="Optional. Accent color for the Live Activity. Defaults to blue.") + color: Optional[StrictStr] = Field(default=None, description="Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included.") step_color: Optional[StrictStr] = Field(default=None, description="Optional. Overrides color for the current step. Only applies to type=segmented_progress.") step_colors: Optional[List[StrictStr]] = Field(default=None, description="Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step.") auto_dismiss_minutes: Optional[Annotated[int, Field(strict=True, ge=0)]] = Field(default=3, description="Optional. Minutes before the ended Live Activity is dismissed. Default 3. Set 0 for immediate dismissal. iOS will dismiss ended Live Activities after ~4 hours max.") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "metrics", "type", "color", "step_color", "step_colors", "auto_dismiss_minutes"] + __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "metrics", "message", "icon", "badge", "type", "color", "step_color", "step_colors", "auto_dismiss_minutes"] @field_validator('type') def type_validate_enum(cls, value): @@ -50,8 +55,8 @@ def type_validate_enum(cls, value): if value is None: return value - if value not in set(['segmented_progress', 'progress', 'metrics', 'stats']): - raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats')") + if value not in set(['segmented_progress', 'progress', 'metrics', 'stats', 'alert']): + raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats', 'alert')") return value @field_validator('color') @@ -60,8 +65,8 @@ def color_validate_enum(cls, value): if value is None: return value - if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow']): - raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow')") + if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray']): + raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray')") return value @field_validator('step_color') @@ -70,8 +75,8 @@ def step_color_validate_enum(cls, value): if value is None: return value - if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow']): - raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow')") + if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray']): + raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray')") return value @field_validator('step_colors') @@ -81,8 +86,8 @@ def step_colors_validate_enum(cls, value): return value for i in value: - if i not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow']): - raise ValueError("each list item must be one of ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow')") + if i not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray']): + raise ValueError("each list item must be one of ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray')") return value model_config = ConfigDict( @@ -133,6 +138,12 @@ def to_dict(self) -> Dict[str, Any]: if _item: _items.append(_item.to_dict()) _dict['metrics'] = _items + # override the default output from pydantic by calling `to_dict()` of icon + if self.icon: + _dict['icon'] = self.icon.to_dict() + # override the default output from pydantic by calling `to_dict()` of badge + if self.badge: + _dict['badge'] = self.badge.to_dict() # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: for _key, _value in self.additional_properties.items(): @@ -158,8 +169,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "value": obj.get("value"), "upper_limit": obj.get("upper_limit"), "metrics": [ActivityMetric.from_dict(_item) for _item in obj["metrics"]] if obj.get("metrics") is not None else None, + "message": obj.get("message"), + "icon": LiveActivityAlertIcon.from_dict(obj["icon"]) if obj.get("icon") is not None else None, + "badge": LiveActivityAlertBadge.from_dict(obj["badge"]) if obj.get("badge") is not None else None, "type": obj.get("type"), - "color": obj.get("color") if obj.get("color") is not None else 'blue', + "color": obj.get("color"), "step_color": obj.get("step_color"), "step_colors": obj.get("step_colors"), "auto_dismiss_minutes": obj.get("auto_dismiss_minutes") if obj.get("auto_dismiss_minutes") is not None else 3 diff --git a/activitysmith_openapi/models/content_state_start.py b/activitysmith_openapi/models/content_state_start.py index dbf7886..7edef0c 100644 --- a/activitysmith_openapi/models/content_state_start.py +++ b/activitysmith_openapi/models/content_state_start.py @@ -21,12 +21,14 @@ from typing import Any, ClassVar, Dict, List, Optional, Union from typing_extensions import Annotated from activitysmith_openapi.models.activity_metric import ActivityMetric +from activitysmith_openapi.models.live_activity_alert_badge import LiveActivityAlertBadge +from activitysmith_openapi.models.live_activity_alert_icon import LiveActivityAlertIcon from typing import Optional, Set from typing_extensions import Self class ContentStateStart(BaseModel): """ - Start payload requires title and type. For segmented_progress include number_of_steps and current_step. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For segmented_progress, number_of_steps is not locked and can be changed in later update or end calls. + Start payload requires title and type. For segmented_progress include number_of_steps and current_step. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message, with optional icon and badge. For segmented_progress, number_of_steps is not locked and can be changed in later update or end calls. """ # noqa: E501 title: StrictStr subtitle: Optional[StrictStr] = None @@ -36,18 +38,21 @@ class ContentStateStart(BaseModel): value: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Current progress value. Use with upper_limit for type=progress.") upper_limit: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Maximum progress value. Use with value for type=progress.") metrics: Optional[Annotated[List[ActivityMetric], Field(min_length=1, max_length=8)]] = Field(default=None, description="Use for type=metrics or type=stats.") + message: Optional[Annotated[str, Field(min_length=1, strict=True)]] = Field(default=None, description="Required for type=alert.") + icon: Optional[LiveActivityAlertIcon] = Field(default=None, description="Optional SF Symbol icon for type=alert.") + badge: Optional[LiveActivityAlertBadge] = Field(default=None, description="Optional badge for type=alert.") type: StrictStr - color: Optional[StrictStr] = Field(default='blue', description="Optional. Accent color for the Live Activity. Defaults to blue.") + color: Optional[StrictStr] = Field(default=None, description="Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included.") step_color: Optional[StrictStr] = Field(default=None, description="Optional. Overrides color for the current step. Only applies to type=segmented_progress.") step_colors: Optional[List[StrictStr]] = Field(default=None, description="Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step.") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "metrics", "type", "color", "step_color", "step_colors"] + __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "metrics", "message", "icon", "badge", "type", "color", "step_color", "step_colors"] @field_validator('type') def type_validate_enum(cls, value): """Validates the enum""" - if value not in set(['segmented_progress', 'progress', 'metrics', 'stats']): - raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats')") + if value not in set(['segmented_progress', 'progress', 'metrics', 'stats', 'alert']): + raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats', 'alert')") return value @field_validator('color') @@ -56,8 +61,8 @@ def color_validate_enum(cls, value): if value is None: return value - if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow']): - raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow')") + if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray']): + raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray')") return value @field_validator('step_color') @@ -66,8 +71,8 @@ def step_color_validate_enum(cls, value): if value is None: return value - if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow']): - raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow')") + if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray']): + raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray')") return value @field_validator('step_colors') @@ -77,8 +82,8 @@ def step_colors_validate_enum(cls, value): return value for i in value: - if i not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow']): - raise ValueError("each list item must be one of ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow')") + if i not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray']): + raise ValueError("each list item must be one of ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray')") return value model_config = ConfigDict( @@ -129,6 +134,12 @@ def to_dict(self) -> Dict[str, Any]: if _item: _items.append(_item.to_dict()) _dict['metrics'] = _items + # override the default output from pydantic by calling `to_dict()` of icon + if self.icon: + _dict['icon'] = self.icon.to_dict() + # override the default output from pydantic by calling `to_dict()` of badge + if self.badge: + _dict['badge'] = self.badge.to_dict() # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: for _key, _value in self.additional_properties.items(): @@ -154,8 +165,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "value": obj.get("value"), "upper_limit": obj.get("upper_limit"), "metrics": [ActivityMetric.from_dict(_item) for _item in obj["metrics"]] if obj.get("metrics") is not None else None, + "message": obj.get("message"), + "icon": LiveActivityAlertIcon.from_dict(obj["icon"]) if obj.get("icon") is not None else None, + "badge": LiveActivityAlertBadge.from_dict(obj["badge"]) if obj.get("badge") is not None else None, "type": obj.get("type"), - "color": obj.get("color") if obj.get("color") is not None else 'blue', + "color": obj.get("color"), "step_color": obj.get("step_color"), "step_colors": obj.get("step_colors") }) diff --git a/activitysmith_openapi/models/content_state_update.py b/activitysmith_openapi/models/content_state_update.py index 1847774..550e93c 100644 --- a/activitysmith_openapi/models/content_state_update.py +++ b/activitysmith_openapi/models/content_state_update.py @@ -21,12 +21,14 @@ from typing import Any, ClassVar, Dict, List, Optional, Union from typing_extensions import Annotated from activitysmith_openapi.models.activity_metric import ActivityMetric +from activitysmith_openapi.models.live_activity_alert_badge import LiveActivityAlertBadge +from activitysmith_openapi.models.live_activity_alert_icon import LiveActivityAlertIcon from typing import Optional, Set from typing_extensions import Self class ContentStateUpdate(BaseModel): """ - Update payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. Type is optional when updating an existing activity. You can increase or decrease number_of_steps during updates. + Update payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message, with optional icon and badge. Type is optional when updating an existing activity. You can increase or decrease number_of_steps during updates. """ # noqa: E501 title: StrictStr subtitle: Optional[StrictStr] = None @@ -36,12 +38,15 @@ class ContentStateUpdate(BaseModel): value: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Current progress value. Use with upper_limit for type=progress.") upper_limit: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Maximum progress value. Use with value for type=progress.") metrics: Optional[Annotated[List[ActivityMetric], Field(min_length=1, max_length=8)]] = Field(default=None, description="Use for type=metrics or type=stats.") + message: Optional[Annotated[str, Field(min_length=1, strict=True)]] = Field(default=None, description="Alert message. Use for type=alert.") + icon: Optional[LiveActivityAlertIcon] = Field(default=None, description="Optional SF Symbol icon for type=alert.") + badge: Optional[LiveActivityAlertBadge] = Field(default=None, description="Optional badge for type=alert.") type: Optional[StrictStr] = Field(default=None, description="Optional. When omitted, the API uses the existing Live Activity type.") - color: Optional[StrictStr] = Field(default='blue', description="Optional. Accent color for the Live Activity. Defaults to blue.") + color: Optional[StrictStr] = Field(default=None, description="Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included.") step_color: Optional[StrictStr] = Field(default=None, description="Optional. Overrides color for the current step. Only applies to type=segmented_progress.") step_colors: Optional[List[StrictStr]] = Field(default=None, description="Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step.") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "metrics", "type", "color", "step_color", "step_colors"] + __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "metrics", "message", "icon", "badge", "type", "color", "step_color", "step_colors"] @field_validator('type') def type_validate_enum(cls, value): @@ -49,8 +54,8 @@ def type_validate_enum(cls, value): if value is None: return value - if value not in set(['segmented_progress', 'progress', 'metrics', 'stats']): - raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats')") + if value not in set(['segmented_progress', 'progress', 'metrics', 'stats', 'alert']): + raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats', 'alert')") return value @field_validator('color') @@ -59,8 +64,8 @@ def color_validate_enum(cls, value): if value is None: return value - if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow']): - raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow')") + if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray']): + raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray')") return value @field_validator('step_color') @@ -69,8 +74,8 @@ def step_color_validate_enum(cls, value): if value is None: return value - if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow']): - raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow')") + if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray']): + raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray')") return value @field_validator('step_colors') @@ -80,8 +85,8 @@ def step_colors_validate_enum(cls, value): return value for i in value: - if i not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow']): - raise ValueError("each list item must be one of ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow')") + if i not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray']): + raise ValueError("each list item must be one of ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray')") return value model_config = ConfigDict( @@ -132,6 +137,12 @@ def to_dict(self) -> Dict[str, Any]: if _item: _items.append(_item.to_dict()) _dict['metrics'] = _items + # override the default output from pydantic by calling `to_dict()` of icon + if self.icon: + _dict['icon'] = self.icon.to_dict() + # override the default output from pydantic by calling `to_dict()` of badge + if self.badge: + _dict['badge'] = self.badge.to_dict() # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: for _key, _value in self.additional_properties.items(): @@ -157,8 +168,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "value": obj.get("value"), "upper_limit": obj.get("upper_limit"), "metrics": [ActivityMetric.from_dict(_item) for _item in obj["metrics"]] if obj.get("metrics") is not None else None, + "message": obj.get("message"), + "icon": LiveActivityAlertIcon.from_dict(obj["icon"]) if obj.get("icon") is not None else None, + "badge": LiveActivityAlertBadge.from_dict(obj["badge"]) if obj.get("badge") is not None else None, "type": obj.get("type"), - "color": obj.get("color") if obj.get("color") is not None else 'blue', + "color": obj.get("color"), "step_color": obj.get("step_color"), "step_colors": obj.get("step_colors") }) diff --git a/activitysmith_openapi/models/live_activity_alert_badge.py b/activitysmith_openapi/models/live_activity_alert_badge.py new file mode 100644 index 0000000..c499df7 --- /dev/null +++ b/activitysmith_openapi/models/live_activity_alert_badge.py @@ -0,0 +1,104 @@ +# 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 +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from activitysmith_openapi.models.live_activity_color import LiveActivityColor +from typing import Optional, Set +from typing_extensions import Self + +class LiveActivityAlertBadge(BaseModel): + """ + Optional badge for Alert Live Activities. + """ # noqa: E501 + title: Annotated[str, Field(min_length=1, strict=True)] + color: Optional[LiveActivityColor] = Field(default=None, description="Optional badge color.") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["title", "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 LiveActivityAlertBadge 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. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of LiveActivityAlertBadge from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "title": obj.get("title"), + "color": obj.get("color") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/activitysmith_openapi/models/live_activity_alert_icon.py b/activitysmith_openapi/models/live_activity_alert_icon.py new file mode 100644 index 0000000..06a1ed2 --- /dev/null +++ b/activitysmith_openapi/models/live_activity_alert_icon.py @@ -0,0 +1,104 @@ +# 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 +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from activitysmith_openapi.models.live_activity_color import LiveActivityColor +from typing import Optional, Set +from typing_extensions import Self + +class LiveActivityAlertIcon(BaseModel): + """ + Optional SF Symbol icon for Alert Live Activities. + """ # noqa: E501 + symbol: Annotated[str, Field(min_length=1, strict=True)] = Field(description="Apple SF Symbol name.") + color: Optional[LiveActivityColor] = Field(default=None, description="Optional icon color.") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["symbol", "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 LiveActivityAlertIcon 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. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of LiveActivityAlertIcon from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "symbol": obj.get("symbol"), + "color": obj.get("color") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/activitysmith_openapi/models/live_activity_color.py b/activitysmith_openapi/models/live_activity_color.py new file mode 100644 index 0000000..08905e6 --- /dev/null +++ b/activitysmith_openapi/models/live_activity_color.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 + + +from __future__ import annotations +import json +from enum import Enum +from typing_extensions import Self + + +class LiveActivityColor(str, Enum): + """ + LiveActivityColor + """ + + """ + allowed enum values + """ + LIME = 'lime' + GREEN = 'green' + CYAN = 'cyan' + BLUE = 'blue' + PURPLE = 'purple' + MAGENTA = 'magenta' + RED = 'red' + ORANGE = 'orange' + YELLOW = 'yellow' + GRAY = 'gray' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of LiveActivityColor from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/activitysmith_openapi/models/stream_content_state.py b/activitysmith_openapi/models/stream_content_state.py index d74f951..bf399d6 100644 --- a/activitysmith_openapi/models/stream_content_state.py +++ b/activitysmith_openapi/models/stream_content_state.py @@ -21,12 +21,14 @@ from typing import Any, ClassVar, Dict, List, Optional, Union from typing_extensions import Annotated from activitysmith_openapi.models.activity_metric import ActivityMetric +from activitysmith_openapi.models.live_activity_alert_badge import LiveActivityAlertBadge +from activitysmith_openapi.models.live_activity_alert_icon import LiveActivityAlertIcon from typing import Optional, Set from typing_extensions import Self class StreamContentState(BaseModel): """ - Current state for a managed Live Activity stream. Include type on the first PUT, and whenever the stream may need to start a fresh activity. Supports segmented_progress, progress, metrics, and stats types. + Current state for a managed Live Activity stream. Include type on the first PUT, and whenever the stream may need to start a fresh activity. Supports segmented_progress, progress, metrics, stats, and alert types. """ # noqa: E501 title: StrictStr subtitle: Optional[StrictStr] = None @@ -36,14 +38,17 @@ class StreamContentState(BaseModel): value: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Current progress value. Use with upper_limit for progress.") upper_limit: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Maximum progress value. Use with value for progress.") type: Optional[StrictStr] = Field(default=None, description="Required on the first PUT or whenever the stream cannot infer the current activity type.") - color: Optional[StrictStr] = Field(default='blue', description="Optional. Accent color for the Live Activity. Defaults to blue.") + color: Optional[StrictStr] = Field(default=None, description="Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included.") step_color: Optional[StrictStr] = Field(default=None, description="Optional. Overrides color for the current step. Only applies to segmented_progress.") step_colors: Optional[List[StrictStr]] = Field(default=None, description="Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step.") metrics: Optional[Annotated[List[ActivityMetric], Field(min_length=1, max_length=8)]] = Field(default=None, description="Use for metrics and stats activities.") + message: Optional[Annotated[str, Field(min_length=1, strict=True)]] = Field(default=None, description="Required for type=alert.") + icon: Optional[LiveActivityAlertIcon] = Field(default=None, description="Optional SF Symbol icon for type=alert.") + badge: Optional[LiveActivityAlertBadge] = Field(default=None, description="Optional badge for type=alert.") auto_dismiss_seconds: Optional[Annotated[int, Field(strict=True, ge=0)]] = Field(default=None, description="Optional. Seconds before the ended Live Activity is dismissed.") auto_dismiss_minutes: Optional[Annotated[int, Field(strict=True, ge=0)]] = Field(default=None, description="Optional. Minutes before the ended Live Activity is dismissed.") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "type", "color", "step_color", "step_colors", "metrics", "auto_dismiss_seconds", "auto_dismiss_minutes"] + __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "type", "color", "step_color", "step_colors", "metrics", "message", "icon", "badge", "auto_dismiss_seconds", "auto_dismiss_minutes"] @field_validator('type') def type_validate_enum(cls, value): @@ -51,8 +56,8 @@ def type_validate_enum(cls, value): if value is None: return value - if value not in set(['segmented_progress', 'progress', 'metrics', 'stats']): - raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats')") + if value not in set(['segmented_progress', 'progress', 'metrics', 'stats', 'alert']): + raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats', 'alert')") return value @field_validator('color') @@ -61,8 +66,8 @@ def color_validate_enum(cls, value): if value is None: return value - if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow']): - raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow')") + if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray']): + raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray')") return value @field_validator('step_color') @@ -71,8 +76,8 @@ def step_color_validate_enum(cls, value): if value is None: return value - if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow']): - raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow')") + if value not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray']): + raise ValueError("must be one of enum values ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray')") return value @field_validator('step_colors') @@ -82,8 +87,8 @@ def step_colors_validate_enum(cls, value): return value for i in value: - if i not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow']): - raise ValueError("each list item must be one of ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow')") + if i not in set(['lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray']): + raise ValueError("each list item must be one of ('lime', 'green', 'cyan', 'blue', 'purple', 'magenta', 'red', 'orange', 'yellow', 'gray')") return value model_config = ConfigDict( @@ -134,6 +139,12 @@ def to_dict(self) -> Dict[str, Any]: if _item: _items.append(_item.to_dict()) _dict['metrics'] = _items + # override the default output from pydantic by calling `to_dict()` of icon + if self.icon: + _dict['icon'] = self.icon.to_dict() + # override the default output from pydantic by calling `to_dict()` of badge + if self.badge: + _dict['badge'] = self.badge.to_dict() # puts key-value pairs in additional_properties in the top level if self.additional_properties is not None: for _key, _value in self.additional_properties.items(): @@ -159,10 +170,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "value": obj.get("value"), "upper_limit": obj.get("upper_limit"), "type": obj.get("type"), - "color": obj.get("color") if obj.get("color") is not None else 'blue', + "color": obj.get("color"), "step_color": obj.get("step_color"), "step_colors": obj.get("step_colors"), "metrics": [ActivityMetric.from_dict(_item) for _item in obj["metrics"]] if obj.get("metrics") is not None else None, + "message": obj.get("message"), + "icon": LiveActivityAlertIcon.from_dict(obj["icon"]) if obj.get("icon") is not None else None, + "badge": LiveActivityAlertBadge.from_dict(obj["badge"]) if obj.get("badge") is not None else None, "auto_dismiss_seconds": obj.get("auto_dismiss_seconds"), "auto_dismiss_minutes": obj.get("auto_dismiss_minutes") }) diff --git a/activitysmith_openapi/test/test_content_state_end.py b/activitysmith_openapi/test/test_content_state_end.py index 8c2e988..92199b1 100644 --- a/activitysmith_openapi/test/test_content_state_end.py +++ b/activitysmith_openapi/test/test_content_state_end.py @@ -45,8 +45,11 @@ def make_instance(self, include_optional) -> ContentStateEnd: metrics = [ { } ], + message = '0', + icon = { }, + badge = { }, type = 'segmented_progress', - color = 'blue', + color = 'lime', step_color = 'lime', step_colors = [ 'lime' diff --git a/activitysmith_openapi/test/test_content_state_start.py b/activitysmith_openapi/test/test_content_state_start.py index 088ba0c..0f82e65 100644 --- a/activitysmith_openapi/test/test_content_state_start.py +++ b/activitysmith_openapi/test/test_content_state_start.py @@ -45,8 +45,11 @@ def make_instance(self, include_optional) -> ContentStateStart: metrics = [ { } ], + message = '0', + icon = { }, + badge = { }, type = 'segmented_progress', - color = 'blue', + color = 'lime', step_color = 'lime', step_colors = [ 'lime' diff --git a/activitysmith_openapi/test/test_content_state_update.py b/activitysmith_openapi/test/test_content_state_update.py index b6de82a..b273f79 100644 --- a/activitysmith_openapi/test/test_content_state_update.py +++ b/activitysmith_openapi/test/test_content_state_update.py @@ -45,8 +45,11 @@ def make_instance(self, include_optional) -> ContentStateUpdate: metrics = [ { } ], + message = '0', + icon = { }, + badge = { }, type = 'segmented_progress', - color = 'blue', + color = 'lime', step_color = 'lime', step_colors = [ 'lime' diff --git a/activitysmith_openapi/test/test_live_activity_alert_badge.py b/activitysmith_openapi/test/test_live_activity_alert_badge.py new file mode 100644 index 0000000..90a7ed9 --- /dev/null +++ b/activitysmith_openapi/test/test_live_activity_alert_badge.py @@ -0,0 +1,53 @@ +# 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.live_activity_alert_badge import LiveActivityAlertBadge + +class TestLiveActivityAlertBadge(unittest.TestCase): + """LiveActivityAlertBadge unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> LiveActivityAlertBadge: + """Test LiveActivityAlertBadge + 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 `LiveActivityAlertBadge` + """ + model = LiveActivityAlertBadge() + if include_optional: + return LiveActivityAlertBadge( + title = '0', + color = 'lime' + ) + else: + return LiveActivityAlertBadge( + title = '0', + ) + """ + + def testLiveActivityAlertBadge(self): + """Test LiveActivityAlertBadge""" + # 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_alert_icon.py b/activitysmith_openapi/test/test_live_activity_alert_icon.py new file mode 100644 index 0000000..ead2e64 --- /dev/null +++ b/activitysmith_openapi/test/test_live_activity_alert_icon.py @@ -0,0 +1,53 @@ +# 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.live_activity_alert_icon import LiveActivityAlertIcon + +class TestLiveActivityAlertIcon(unittest.TestCase): + """LiveActivityAlertIcon unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> LiveActivityAlertIcon: + """Test LiveActivityAlertIcon + 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 `LiveActivityAlertIcon` + """ + model = LiveActivityAlertIcon() + if include_optional: + return LiveActivityAlertIcon( + symbol = '0', + color = 'lime' + ) + else: + return LiveActivityAlertIcon( + symbol = '0', + ) + """ + + def testLiveActivityAlertIcon(self): + """Test LiveActivityAlertIcon""" + # 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_color.py b/activitysmith_openapi/test/test_live_activity_color.py new file mode 100644 index 0000000..fc35221 --- /dev/null +++ b/activitysmith_openapi/test/test_live_activity_color.py @@ -0,0 +1,33 @@ +# 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.live_activity_color import LiveActivityColor + +class TestLiveActivityColor(unittest.TestCase): + """LiveActivityColor unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testLiveActivityColor(self): + """Test LiveActivityColor""" + # inst = LiveActivityColor() + +if __name__ == '__main__': + unittest.main() diff --git a/activitysmith_openapi/test/test_stream_content_state.py b/activitysmith_openapi/test/test_stream_content_state.py index e97bbe9..5e00f46 100644 --- a/activitysmith_openapi/test/test_stream_content_state.py +++ b/activitysmith_openapi/test/test_stream_content_state.py @@ -43,7 +43,7 @@ def make_instance(self, include_optional) -> StreamContentState: value = 1.337, upper_limit = 1.337, type = 'segmented_progress', - color = 'blue', + color = 'lime', step_color = 'lime', step_colors = [ 'lime' @@ -51,6 +51,9 @@ def make_instance(self, include_optional) -> StreamContentState: metrics = [ { } ], + message = '0', + icon = { }, + badge = { }, auto_dismiss_seconds = 0, auto_dismiss_minutes = 0 ) diff --git a/pyproject.toml b/pyproject.toml index 35ef89e..cad6769 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "activitysmith" -version = "1.4.2" +version = "1.5.0" description = "Official ActivitySmith Python SDK" readme = "README.md" requires-python = ">=3.9" diff --git a/tests/test_resources.py b/tests/test_resources.py index 234bc98..8db8a4f 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -1,6 +1,6 @@ from importlib.metadata import version -from activitysmith.client import ActivitySmith, action, content_state, metric +from activitysmith.client import ActivitySmith, action, alert_badge, alert_icon, content_state, metric import activitysmith.client as client_module @@ -321,6 +321,68 @@ def test_live_activities_support_stats_payloads(monkeypatch): ] +def test_live_activities_support_alert_helpers(monkeypatch): + monkeypatch.setattr(client_module, "PushNotificationsApi", FakePushNotificationsApi) + monkeypatch.setattr(client_module, "LiveActivitiesApi", FakeLiveActivitiesApi) + monkeypatch.setattr(client_module, "MetricsApi", FakeMetricsApi) + + client = ActivitySmith(api_key="x") + state_payload = content_state( + title="Reactivation", + message="Lumen came back after 2 weeks", + type=client.live_activities.TYPE_ALERT, + icon=alert_icon("cloud.sun", color="yellow"), + badge=alert_badge("Customer", color="magenta"), + color="red", + ) + + client.live_activities.stream("customer-ops", content_state=state_payload) + client.live_activities.update( + activity_id="act-1", + title="Onboarding", + message="A customer is stuck at workspace setup", + type=client.live_activities.TYPE_ALERT, + icon=client.live_activities.alert_icon("person.crop.circle.badge.questionmark"), + badge=client.live_activities.alert_badge("Customer", color="gray"), + color="red", + ) + + assert client.live_activities._api.calls == [ + ( + "stream", + { + "stream_key": "customer-ops", + "live_activity_stream_request": { + "content_state": { + "title": "Reactivation", + "message": "Lumen came back after 2 weeks", + "type": client.live_activities.TYPE_ALERT, + "color": "red", + "icon": {"symbol": "cloud.sun", "color": "yellow"}, + "badge": {"title": "Customer", "color": "magenta"}, + }, + }, + }, + ), + ( + "update", + { + "live_activity_update_request": { + "activity_id": "act-1", + "content_state": { + "title": "Onboarding", + "message": "A customer is stuck at workspace setup", + "type": client.live_activities.TYPE_ALERT, + "color": "red", + "icon": {"symbol": "person.crop.circle.badge.questionmark"}, + "badge": {"title": "Customer", "color": "gray"}, + }, + } + }, + ), + ] + + def test_live_activities_build_requests_from_named_fields(monkeypatch): monkeypatch.setattr(client_module, "PushNotificationsApi", FakePushNotificationsApi) monkeypatch.setattr(client_module, "LiveActivitiesApi", FakeLiveActivitiesApi)