diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 037c241..a391b13 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "7.4.0" + ".": "7.5.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 4b96b1e..1c57573 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 77 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-9859cb664d1a9de0323c857e96cf41d0a5ac5c5903c501059f36bf62553b1583.yml -openapi_spec_hash: d29149d60504eba35c63f583ce4bf0bc -config_hash: 3ec521d062b05b81c22bc1a25bfe3d02 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-fab4ee8a24b719456f38d4a6050f4e40158db57937a1d55035be9325df494941.yml +openapi_spec_hash: be1371c71559511c79a4285238b7131c +config_hash: 54d2059f36ceee17804ef6c2800affd2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 3670f76..0bcd48b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 7.5.0 (2025-12-22) + +Full Changelog: [v7.4.0...v7.5.0](https://github.com/trycourier/courier-python/compare/v7.4.0...v7.5.0) + +### Features + +* **api:** add slack/teams/pagerduty/webhook/audience recipient types to send ([5401702](https://github.com/trycourier/courier-python/commit/54017021e9ff5ba391c2b702ccdec08cb17b4ecc)) + + +### Bug Fixes + +* use async_to_httpx_files in patch method ([81d7991](https://github.com/trycourier/courier-python/commit/81d7991941ba20d717b289d4a2e87b16091ed6e0)) + + +### Chores + +* **internal:** add `--fix` argument to lint script ([14a2c9a](https://github.com/trycourier/courier-python/commit/14a2c9a30220a43af14730219bf9d81a406a7f8f)) +* speedup initial import ([1ce264e](https://github.com/trycourier/courier-python/commit/1ce264e0da7aac803ffd405e4672fd2f69fdfd10)) + ## 7.4.0 (2025-12-16) Full Changelog: [v7.3.0...v7.4.0](https://github.com/trycourier/courier-python/compare/v7.3.0...v7.4.0) diff --git a/README.md b/README.md index c6efc3d..e7908ea 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ response = client.send.message( message={ "data": {"foo": "bar"}, "template": "template_id", - "to": {"user_id": "example_user"}, + "to": {"user_id": "user_id"}, }, ) print(response.message) diff --git a/api.md b/api.md index af04f9a..adcda68 100644 --- a/api.md +++ b/api.md @@ -2,9 +2,15 @@ ```python from courier.types import ( + AirshipProfile, + AirshipProfileAudience, Alignment, + AudienceFilter, + AudienceRecipient, ChannelClassification, ChannelPreference, + DeviceType, + Discord, ElementalActionNodeWithType, ElementalBaseNode, ElementalChannelNode, @@ -17,19 +23,52 @@ from courier.types import ( ElementalNode, ElementalQuoteNodeWithType, ElementalTextNodeWithType, + Expo, + Intercom, + IntercomRecipient, + ListFilter, + ListPatternRecipient, + ListRecipient, MessageContext, MessageRouting, MessageRoutingChannel, + MsTeams, + MsTeamsBaseProperties, + MsTeamsRecipient, + MultipleTokens, NotificationPreferenceDetails, + Pagerduty, + PagerdutyRecipient, Paging, Preference, PreferenceStatus, - Recipient, RecipientPreferences, Rule, + SendDirectMessage, + SendToChannel, + SendToMsTeamsChannelID, + SendToMsTeamsChannelName, + SendToMsTeamsConversationID, + SendToMsTeamsEmail, + SendToMsTeamsUserID, + SendToSlackChannel, + SendToSlackEmail, + SendToSlackUserID, + Slack, + SlackBaseProperties, + SlackRecipient, TextStyle, + Token, + UserProfile, + UserProfileFirebaseToken, UserRecipient, Utm, + WebhookAuthMode, + WebhookAuthentication, + WebhookMethod, + WebhookProfile, + WebhookProfileType, + WebhookRecipient, ) ``` @@ -54,6 +93,8 @@ from courier.types import ( Audience, Filter, FilterConfig, + NestedFilterConfig, + SingleFilterConfig, AudienceUpdateResponse, AudienceListResponse, AudienceListMembersResponse, diff --git a/pyproject.toml b/pyproject.toml index e22c2a1..414a2e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "trycourier" -version = "7.4.0" +version = "7.5.0" description = "The official Python library for the Courier API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/scripts/lint b/scripts/lint index 0e4fdbb..9776f4d 100755 --- a/scripts/lint +++ b/scripts/lint @@ -4,8 +4,13 @@ set -e cd "$(dirname "$0")/.." -echo "==> Running lints" -rye run lint +if [ "$1" = "--fix" ]; then + echo "==> Running lints with --fix" + rye run fix:ruff +else + echo "==> Running lints" + rye run lint +fi echo "==> Making sure it imports" rye run python -c 'import courier' diff --git a/src/courier/_base_client.py b/src/courier/_base_client.py index 5af3866..ab0624d 100644 --- a/src/courier/_base_client.py +++ b/src/courier/_base_client.py @@ -1774,7 +1774,7 @@ async def patch( options: RequestOptions = {}, ) -> ResponseT: opts = FinalRequestOptions.construct( - method="patch", url=path, json_data=body, files=to_httpx_files(files), **options + method="patch", url=path, json_data=body, files=await async_to_httpx_files(files), **options ) return await self.request(cast_to, opts) diff --git a/src/courier/_client.py b/src/courier/_client.py index 42910f7..9af2325 100644 --- a/src/courier/_client.py +++ b/src/courier/_client.py @@ -3,7 +3,7 @@ from __future__ import annotations import os -from typing import Any, Mapping +from typing import TYPE_CHECKING, Any, Mapping from typing_extensions import Self, override import httpx @@ -20,8 +20,8 @@ not_given, ) from ._utils import is_given, get_async_library +from ._compat import cached_property from ._version import __version__ -from .resources import auth, bulk, send, brands, inbound, messages, requests, audiences, audit_events, translations from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import CourierError, APIStatusError from ._base_client import ( @@ -29,36 +29,47 @@ SyncAPIClient, AsyncAPIClient, ) -from .resources.lists import lists -from .resources.users import users -from .resources.tenants import tenants -from .resources.profiles import profiles -from .resources.automations import automations -from .resources.notifications import notifications + +if TYPE_CHECKING: + from .resources import ( + auth, + bulk, + send, + lists, + users, + brands, + inbound, + tenants, + messages, + profiles, + requests, + audiences, + automations, + audit_events, + translations, + notifications, + ) + from .resources.auth import AuthResource, AsyncAuthResource + from .resources.bulk import BulkResource, AsyncBulkResource + from .resources.send import SendResource, AsyncSendResource + from .resources.brands import BrandsResource, AsyncBrandsResource + from .resources.inbound import InboundResource, AsyncInboundResource + from .resources.messages import MessagesResource, AsyncMessagesResource + from .resources.requests import RequestsResource, AsyncRequestsResource + from .resources.audiences import AudiencesResource, AsyncAudiencesResource + from .resources.lists.lists import ListsResource, AsyncListsResource + from .resources.users.users import UsersResource, AsyncUsersResource + from .resources.audit_events import AuditEventsResource, AsyncAuditEventsResource + from .resources.translations import TranslationsResource, AsyncTranslationsResource + from .resources.tenants.tenants import TenantsResource, AsyncTenantsResource + from .resources.profiles.profiles import ProfilesResource, AsyncProfilesResource + from .resources.automations.automations import AutomationsResource, AsyncAutomationsResource + from .resources.notifications.notifications import NotificationsResource, AsyncNotificationsResource __all__ = ["Timeout", "Transport", "ProxiesTypes", "RequestOptions", "Courier", "AsyncCourier", "Client", "AsyncClient"] class Courier(SyncAPIClient): - send: send.SendResource - audiences: audiences.AudiencesResource - audit_events: audit_events.AuditEventsResource - auth: auth.AuthResource - automations: automations.AutomationsResource - brands: brands.BrandsResource - bulk: bulk.BulkResource - inbound: inbound.InboundResource - lists: lists.ListsResource - messages: messages.MessagesResource - requests: requests.RequestsResource - notifications: notifications.NotificationsResource - profiles: profiles.ProfilesResource - tenants: tenants.TenantsResource - translations: translations.TranslationsResource - users: users.UsersResource - with_raw_response: CourierWithRawResponse - with_streaming_response: CourierWithStreamedResponse - # client options api_key: str @@ -113,24 +124,109 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.send = send.SendResource(self) - self.audiences = audiences.AudiencesResource(self) - self.audit_events = audit_events.AuditEventsResource(self) - self.auth = auth.AuthResource(self) - self.automations = automations.AutomationsResource(self) - self.brands = brands.BrandsResource(self) - self.bulk = bulk.BulkResource(self) - self.inbound = inbound.InboundResource(self) - self.lists = lists.ListsResource(self) - self.messages = messages.MessagesResource(self) - self.requests = requests.RequestsResource(self) - self.notifications = notifications.NotificationsResource(self) - self.profiles = profiles.ProfilesResource(self) - self.tenants = tenants.TenantsResource(self) - self.translations = translations.TranslationsResource(self) - self.users = users.UsersResource(self) - self.with_raw_response = CourierWithRawResponse(self) - self.with_streaming_response = CourierWithStreamedResponse(self) + @cached_property + def send(self) -> SendResource: + from .resources.send import SendResource + + return SendResource(self) + + @cached_property + def audiences(self) -> AudiencesResource: + from .resources.audiences import AudiencesResource + + return AudiencesResource(self) + + @cached_property + def audit_events(self) -> AuditEventsResource: + from .resources.audit_events import AuditEventsResource + + return AuditEventsResource(self) + + @cached_property + def auth(self) -> AuthResource: + from .resources.auth import AuthResource + + return AuthResource(self) + + @cached_property + def automations(self) -> AutomationsResource: + from .resources.automations import AutomationsResource + + return AutomationsResource(self) + + @cached_property + def brands(self) -> BrandsResource: + from .resources.brands import BrandsResource + + return BrandsResource(self) + + @cached_property + def bulk(self) -> BulkResource: + from .resources.bulk import BulkResource + + return BulkResource(self) + + @cached_property + def inbound(self) -> InboundResource: + from .resources.inbound import InboundResource + + return InboundResource(self) + + @cached_property + def lists(self) -> ListsResource: + from .resources.lists import ListsResource + + return ListsResource(self) + + @cached_property + def messages(self) -> MessagesResource: + from .resources.messages import MessagesResource + + return MessagesResource(self) + + @cached_property + def requests(self) -> RequestsResource: + from .resources.requests import RequestsResource + + return RequestsResource(self) + + @cached_property + def notifications(self) -> NotificationsResource: + from .resources.notifications import NotificationsResource + + return NotificationsResource(self) + + @cached_property + def profiles(self) -> ProfilesResource: + from .resources.profiles import ProfilesResource + + return ProfilesResource(self) + + @cached_property + def tenants(self) -> TenantsResource: + from .resources.tenants import TenantsResource + + return TenantsResource(self) + + @cached_property + def translations(self) -> TranslationsResource: + from .resources.translations import TranslationsResource + + return TranslationsResource(self) + + @cached_property + def users(self) -> UsersResource: + from .resources.users import UsersResource + + return UsersResource(self) + + @cached_property + def with_raw_response(self) -> CourierWithRawResponse: + return CourierWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> CourierWithStreamedResponse: + return CourierWithStreamedResponse(self) @property @override @@ -238,25 +334,6 @@ def _make_status_error( class AsyncCourier(AsyncAPIClient): - send: send.AsyncSendResource - audiences: audiences.AsyncAudiencesResource - audit_events: audit_events.AsyncAuditEventsResource - auth: auth.AsyncAuthResource - automations: automations.AsyncAutomationsResource - brands: brands.AsyncBrandsResource - bulk: bulk.AsyncBulkResource - inbound: inbound.AsyncInboundResource - lists: lists.AsyncListsResource - messages: messages.AsyncMessagesResource - requests: requests.AsyncRequestsResource - notifications: notifications.AsyncNotificationsResource - profiles: profiles.AsyncProfilesResource - tenants: tenants.AsyncTenantsResource - translations: translations.AsyncTranslationsResource - users: users.AsyncUsersResource - with_raw_response: AsyncCourierWithRawResponse - with_streaming_response: AsyncCourierWithStreamedResponse - # client options api_key: str @@ -311,24 +388,109 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.send = send.AsyncSendResource(self) - self.audiences = audiences.AsyncAudiencesResource(self) - self.audit_events = audit_events.AsyncAuditEventsResource(self) - self.auth = auth.AsyncAuthResource(self) - self.automations = automations.AsyncAutomationsResource(self) - self.brands = brands.AsyncBrandsResource(self) - self.bulk = bulk.AsyncBulkResource(self) - self.inbound = inbound.AsyncInboundResource(self) - self.lists = lists.AsyncListsResource(self) - self.messages = messages.AsyncMessagesResource(self) - self.requests = requests.AsyncRequestsResource(self) - self.notifications = notifications.AsyncNotificationsResource(self) - self.profiles = profiles.AsyncProfilesResource(self) - self.tenants = tenants.AsyncTenantsResource(self) - self.translations = translations.AsyncTranslationsResource(self) - self.users = users.AsyncUsersResource(self) - self.with_raw_response = AsyncCourierWithRawResponse(self) - self.with_streaming_response = AsyncCourierWithStreamedResponse(self) + @cached_property + def send(self) -> AsyncSendResource: + from .resources.send import AsyncSendResource + + return AsyncSendResource(self) + + @cached_property + def audiences(self) -> AsyncAudiencesResource: + from .resources.audiences import AsyncAudiencesResource + + return AsyncAudiencesResource(self) + + @cached_property + def audit_events(self) -> AsyncAuditEventsResource: + from .resources.audit_events import AsyncAuditEventsResource + + return AsyncAuditEventsResource(self) + + @cached_property + def auth(self) -> AsyncAuthResource: + from .resources.auth import AsyncAuthResource + + return AsyncAuthResource(self) + + @cached_property + def automations(self) -> AsyncAutomationsResource: + from .resources.automations import AsyncAutomationsResource + + return AsyncAutomationsResource(self) + + @cached_property + def brands(self) -> AsyncBrandsResource: + from .resources.brands import AsyncBrandsResource + + return AsyncBrandsResource(self) + + @cached_property + def bulk(self) -> AsyncBulkResource: + from .resources.bulk import AsyncBulkResource + + return AsyncBulkResource(self) + + @cached_property + def inbound(self) -> AsyncInboundResource: + from .resources.inbound import AsyncInboundResource + + return AsyncInboundResource(self) + + @cached_property + def lists(self) -> AsyncListsResource: + from .resources.lists import AsyncListsResource + + return AsyncListsResource(self) + + @cached_property + def messages(self) -> AsyncMessagesResource: + from .resources.messages import AsyncMessagesResource + + return AsyncMessagesResource(self) + + @cached_property + def requests(self) -> AsyncRequestsResource: + from .resources.requests import AsyncRequestsResource + + return AsyncRequestsResource(self) + + @cached_property + def notifications(self) -> AsyncNotificationsResource: + from .resources.notifications import AsyncNotificationsResource + + return AsyncNotificationsResource(self) + + @cached_property + def profiles(self) -> AsyncProfilesResource: + from .resources.profiles import AsyncProfilesResource + + return AsyncProfilesResource(self) + + @cached_property + def tenants(self) -> AsyncTenantsResource: + from .resources.tenants import AsyncTenantsResource + + return AsyncTenantsResource(self) + + @cached_property + def translations(self) -> AsyncTranslationsResource: + from .resources.translations import AsyncTranslationsResource + + return AsyncTranslationsResource(self) + + @cached_property + def users(self) -> AsyncUsersResource: + from .resources.users import AsyncUsersResource + + return AsyncUsersResource(self) + + @cached_property + def with_raw_response(self) -> AsyncCourierWithRawResponse: + return AsyncCourierWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncCourierWithStreamedResponse: + return AsyncCourierWithStreamedResponse(self) @property @override @@ -436,83 +598,415 @@ def _make_status_error( class CourierWithRawResponse: + _client: Courier + def __init__(self, client: Courier) -> None: - self.send = send.SendResourceWithRawResponse(client.send) - self.audiences = audiences.AudiencesResourceWithRawResponse(client.audiences) - self.audit_events = audit_events.AuditEventsResourceWithRawResponse(client.audit_events) - self.auth = auth.AuthResourceWithRawResponse(client.auth) - self.automations = automations.AutomationsResourceWithRawResponse(client.automations) - self.brands = brands.BrandsResourceWithRawResponse(client.brands) - self.bulk = bulk.BulkResourceWithRawResponse(client.bulk) - self.inbound = inbound.InboundResourceWithRawResponse(client.inbound) - self.lists = lists.ListsResourceWithRawResponse(client.lists) - self.messages = messages.MessagesResourceWithRawResponse(client.messages) - self.requests = requests.RequestsResourceWithRawResponse(client.requests) - self.notifications = notifications.NotificationsResourceWithRawResponse(client.notifications) - self.profiles = profiles.ProfilesResourceWithRawResponse(client.profiles) - self.tenants = tenants.TenantsResourceWithRawResponse(client.tenants) - self.translations = translations.TranslationsResourceWithRawResponse(client.translations) - self.users = users.UsersResourceWithRawResponse(client.users) + self._client = client + + @cached_property + def send(self) -> send.SendResourceWithRawResponse: + from .resources.send import SendResourceWithRawResponse + + return SendResourceWithRawResponse(self._client.send) + + @cached_property + def audiences(self) -> audiences.AudiencesResourceWithRawResponse: + from .resources.audiences import AudiencesResourceWithRawResponse + + return AudiencesResourceWithRawResponse(self._client.audiences) + + @cached_property + def audit_events(self) -> audit_events.AuditEventsResourceWithRawResponse: + from .resources.audit_events import AuditEventsResourceWithRawResponse + + return AuditEventsResourceWithRawResponse(self._client.audit_events) + + @cached_property + def auth(self) -> auth.AuthResourceWithRawResponse: + from .resources.auth import AuthResourceWithRawResponse + + return AuthResourceWithRawResponse(self._client.auth) + + @cached_property + def automations(self) -> automations.AutomationsResourceWithRawResponse: + from .resources.automations import AutomationsResourceWithRawResponse + + return AutomationsResourceWithRawResponse(self._client.automations) + + @cached_property + def brands(self) -> brands.BrandsResourceWithRawResponse: + from .resources.brands import BrandsResourceWithRawResponse + + return BrandsResourceWithRawResponse(self._client.brands) + + @cached_property + def bulk(self) -> bulk.BulkResourceWithRawResponse: + from .resources.bulk import BulkResourceWithRawResponse + + return BulkResourceWithRawResponse(self._client.bulk) + + @cached_property + def inbound(self) -> inbound.InboundResourceWithRawResponse: + from .resources.inbound import InboundResourceWithRawResponse + + return InboundResourceWithRawResponse(self._client.inbound) + + @cached_property + def lists(self) -> lists.ListsResourceWithRawResponse: + from .resources.lists import ListsResourceWithRawResponse + + return ListsResourceWithRawResponse(self._client.lists) + + @cached_property + def messages(self) -> messages.MessagesResourceWithRawResponse: + from .resources.messages import MessagesResourceWithRawResponse + + return MessagesResourceWithRawResponse(self._client.messages) + + @cached_property + def requests(self) -> requests.RequestsResourceWithRawResponse: + from .resources.requests import RequestsResourceWithRawResponse + + return RequestsResourceWithRawResponse(self._client.requests) + + @cached_property + def notifications(self) -> notifications.NotificationsResourceWithRawResponse: + from .resources.notifications import NotificationsResourceWithRawResponse + + return NotificationsResourceWithRawResponse(self._client.notifications) + + @cached_property + def profiles(self) -> profiles.ProfilesResourceWithRawResponse: + from .resources.profiles import ProfilesResourceWithRawResponse + + return ProfilesResourceWithRawResponse(self._client.profiles) + + @cached_property + def tenants(self) -> tenants.TenantsResourceWithRawResponse: + from .resources.tenants import TenantsResourceWithRawResponse + + return TenantsResourceWithRawResponse(self._client.tenants) + + @cached_property + def translations(self) -> translations.TranslationsResourceWithRawResponse: + from .resources.translations import TranslationsResourceWithRawResponse + + return TranslationsResourceWithRawResponse(self._client.translations) + + @cached_property + def users(self) -> users.UsersResourceWithRawResponse: + from .resources.users import UsersResourceWithRawResponse + + return UsersResourceWithRawResponse(self._client.users) class AsyncCourierWithRawResponse: + _client: AsyncCourier + def __init__(self, client: AsyncCourier) -> None: - self.send = send.AsyncSendResourceWithRawResponse(client.send) - self.audiences = audiences.AsyncAudiencesResourceWithRawResponse(client.audiences) - self.audit_events = audit_events.AsyncAuditEventsResourceWithRawResponse(client.audit_events) - self.auth = auth.AsyncAuthResourceWithRawResponse(client.auth) - self.automations = automations.AsyncAutomationsResourceWithRawResponse(client.automations) - self.brands = brands.AsyncBrandsResourceWithRawResponse(client.brands) - self.bulk = bulk.AsyncBulkResourceWithRawResponse(client.bulk) - self.inbound = inbound.AsyncInboundResourceWithRawResponse(client.inbound) - self.lists = lists.AsyncListsResourceWithRawResponse(client.lists) - self.messages = messages.AsyncMessagesResourceWithRawResponse(client.messages) - self.requests = requests.AsyncRequestsResourceWithRawResponse(client.requests) - self.notifications = notifications.AsyncNotificationsResourceWithRawResponse(client.notifications) - self.profiles = profiles.AsyncProfilesResourceWithRawResponse(client.profiles) - self.tenants = tenants.AsyncTenantsResourceWithRawResponse(client.tenants) - self.translations = translations.AsyncTranslationsResourceWithRawResponse(client.translations) - self.users = users.AsyncUsersResourceWithRawResponse(client.users) + self._client = client + + @cached_property + def send(self) -> send.AsyncSendResourceWithRawResponse: + from .resources.send import AsyncSendResourceWithRawResponse + + return AsyncSendResourceWithRawResponse(self._client.send) + + @cached_property + def audiences(self) -> audiences.AsyncAudiencesResourceWithRawResponse: + from .resources.audiences import AsyncAudiencesResourceWithRawResponse + + return AsyncAudiencesResourceWithRawResponse(self._client.audiences) + + @cached_property + def audit_events(self) -> audit_events.AsyncAuditEventsResourceWithRawResponse: + from .resources.audit_events import AsyncAuditEventsResourceWithRawResponse + + return AsyncAuditEventsResourceWithRawResponse(self._client.audit_events) + + @cached_property + def auth(self) -> auth.AsyncAuthResourceWithRawResponse: + from .resources.auth import AsyncAuthResourceWithRawResponse + + return AsyncAuthResourceWithRawResponse(self._client.auth) + + @cached_property + def automations(self) -> automations.AsyncAutomationsResourceWithRawResponse: + from .resources.automations import AsyncAutomationsResourceWithRawResponse + + return AsyncAutomationsResourceWithRawResponse(self._client.automations) + + @cached_property + def brands(self) -> brands.AsyncBrandsResourceWithRawResponse: + from .resources.brands import AsyncBrandsResourceWithRawResponse + + return AsyncBrandsResourceWithRawResponse(self._client.brands) + + @cached_property + def bulk(self) -> bulk.AsyncBulkResourceWithRawResponse: + from .resources.bulk import AsyncBulkResourceWithRawResponse + + return AsyncBulkResourceWithRawResponse(self._client.bulk) + + @cached_property + def inbound(self) -> inbound.AsyncInboundResourceWithRawResponse: + from .resources.inbound import AsyncInboundResourceWithRawResponse + + return AsyncInboundResourceWithRawResponse(self._client.inbound) + + @cached_property + def lists(self) -> lists.AsyncListsResourceWithRawResponse: + from .resources.lists import AsyncListsResourceWithRawResponse + + return AsyncListsResourceWithRawResponse(self._client.lists) + + @cached_property + def messages(self) -> messages.AsyncMessagesResourceWithRawResponse: + from .resources.messages import AsyncMessagesResourceWithRawResponse + + return AsyncMessagesResourceWithRawResponse(self._client.messages) + + @cached_property + def requests(self) -> requests.AsyncRequestsResourceWithRawResponse: + from .resources.requests import AsyncRequestsResourceWithRawResponse + + return AsyncRequestsResourceWithRawResponse(self._client.requests) + + @cached_property + def notifications(self) -> notifications.AsyncNotificationsResourceWithRawResponse: + from .resources.notifications import AsyncNotificationsResourceWithRawResponse + + return AsyncNotificationsResourceWithRawResponse(self._client.notifications) + + @cached_property + def profiles(self) -> profiles.AsyncProfilesResourceWithRawResponse: + from .resources.profiles import AsyncProfilesResourceWithRawResponse + + return AsyncProfilesResourceWithRawResponse(self._client.profiles) + + @cached_property + def tenants(self) -> tenants.AsyncTenantsResourceWithRawResponse: + from .resources.tenants import AsyncTenantsResourceWithRawResponse + + return AsyncTenantsResourceWithRawResponse(self._client.tenants) + + @cached_property + def translations(self) -> translations.AsyncTranslationsResourceWithRawResponse: + from .resources.translations import AsyncTranslationsResourceWithRawResponse + + return AsyncTranslationsResourceWithRawResponse(self._client.translations) + + @cached_property + def users(self) -> users.AsyncUsersResourceWithRawResponse: + from .resources.users import AsyncUsersResourceWithRawResponse + + return AsyncUsersResourceWithRawResponse(self._client.users) class CourierWithStreamedResponse: + _client: Courier + def __init__(self, client: Courier) -> None: - self.send = send.SendResourceWithStreamingResponse(client.send) - self.audiences = audiences.AudiencesResourceWithStreamingResponse(client.audiences) - self.audit_events = audit_events.AuditEventsResourceWithStreamingResponse(client.audit_events) - self.auth = auth.AuthResourceWithStreamingResponse(client.auth) - self.automations = automations.AutomationsResourceWithStreamingResponse(client.automations) - self.brands = brands.BrandsResourceWithStreamingResponse(client.brands) - self.bulk = bulk.BulkResourceWithStreamingResponse(client.bulk) - self.inbound = inbound.InboundResourceWithStreamingResponse(client.inbound) - self.lists = lists.ListsResourceWithStreamingResponse(client.lists) - self.messages = messages.MessagesResourceWithStreamingResponse(client.messages) - self.requests = requests.RequestsResourceWithStreamingResponse(client.requests) - self.notifications = notifications.NotificationsResourceWithStreamingResponse(client.notifications) - self.profiles = profiles.ProfilesResourceWithStreamingResponse(client.profiles) - self.tenants = tenants.TenantsResourceWithStreamingResponse(client.tenants) - self.translations = translations.TranslationsResourceWithStreamingResponse(client.translations) - self.users = users.UsersResourceWithStreamingResponse(client.users) + self._client = client + + @cached_property + def send(self) -> send.SendResourceWithStreamingResponse: + from .resources.send import SendResourceWithStreamingResponse + + return SendResourceWithStreamingResponse(self._client.send) + + @cached_property + def audiences(self) -> audiences.AudiencesResourceWithStreamingResponse: + from .resources.audiences import AudiencesResourceWithStreamingResponse + + return AudiencesResourceWithStreamingResponse(self._client.audiences) + + @cached_property + def audit_events(self) -> audit_events.AuditEventsResourceWithStreamingResponse: + from .resources.audit_events import AuditEventsResourceWithStreamingResponse + + return AuditEventsResourceWithStreamingResponse(self._client.audit_events) + + @cached_property + def auth(self) -> auth.AuthResourceWithStreamingResponse: + from .resources.auth import AuthResourceWithStreamingResponse + + return AuthResourceWithStreamingResponse(self._client.auth) + + @cached_property + def automations(self) -> automations.AutomationsResourceWithStreamingResponse: + from .resources.automations import AutomationsResourceWithStreamingResponse + + return AutomationsResourceWithStreamingResponse(self._client.automations) + + @cached_property + def brands(self) -> brands.BrandsResourceWithStreamingResponse: + from .resources.brands import BrandsResourceWithStreamingResponse + + return BrandsResourceWithStreamingResponse(self._client.brands) + + @cached_property + def bulk(self) -> bulk.BulkResourceWithStreamingResponse: + from .resources.bulk import BulkResourceWithStreamingResponse + + return BulkResourceWithStreamingResponse(self._client.bulk) + + @cached_property + def inbound(self) -> inbound.InboundResourceWithStreamingResponse: + from .resources.inbound import InboundResourceWithStreamingResponse + + return InboundResourceWithStreamingResponse(self._client.inbound) + + @cached_property + def lists(self) -> lists.ListsResourceWithStreamingResponse: + from .resources.lists import ListsResourceWithStreamingResponse + + return ListsResourceWithStreamingResponse(self._client.lists) + + @cached_property + def messages(self) -> messages.MessagesResourceWithStreamingResponse: + from .resources.messages import MessagesResourceWithStreamingResponse + + return MessagesResourceWithStreamingResponse(self._client.messages) + + @cached_property + def requests(self) -> requests.RequestsResourceWithStreamingResponse: + from .resources.requests import RequestsResourceWithStreamingResponse + + return RequestsResourceWithStreamingResponse(self._client.requests) + + @cached_property + def notifications(self) -> notifications.NotificationsResourceWithStreamingResponse: + from .resources.notifications import NotificationsResourceWithStreamingResponse + + return NotificationsResourceWithStreamingResponse(self._client.notifications) + + @cached_property + def profiles(self) -> profiles.ProfilesResourceWithStreamingResponse: + from .resources.profiles import ProfilesResourceWithStreamingResponse + + return ProfilesResourceWithStreamingResponse(self._client.profiles) + + @cached_property + def tenants(self) -> tenants.TenantsResourceWithStreamingResponse: + from .resources.tenants import TenantsResourceWithStreamingResponse + + return TenantsResourceWithStreamingResponse(self._client.tenants) + + @cached_property + def translations(self) -> translations.TranslationsResourceWithStreamingResponse: + from .resources.translations import TranslationsResourceWithStreamingResponse + + return TranslationsResourceWithStreamingResponse(self._client.translations) + + @cached_property + def users(self) -> users.UsersResourceWithStreamingResponse: + from .resources.users import UsersResourceWithStreamingResponse + + return UsersResourceWithStreamingResponse(self._client.users) class AsyncCourierWithStreamedResponse: + _client: AsyncCourier + def __init__(self, client: AsyncCourier) -> None: - self.send = send.AsyncSendResourceWithStreamingResponse(client.send) - self.audiences = audiences.AsyncAudiencesResourceWithStreamingResponse(client.audiences) - self.audit_events = audit_events.AsyncAuditEventsResourceWithStreamingResponse(client.audit_events) - self.auth = auth.AsyncAuthResourceWithStreamingResponse(client.auth) - self.automations = automations.AsyncAutomationsResourceWithStreamingResponse(client.automations) - self.brands = brands.AsyncBrandsResourceWithStreamingResponse(client.brands) - self.bulk = bulk.AsyncBulkResourceWithStreamingResponse(client.bulk) - self.inbound = inbound.AsyncInboundResourceWithStreamingResponse(client.inbound) - self.lists = lists.AsyncListsResourceWithStreamingResponse(client.lists) - self.messages = messages.AsyncMessagesResourceWithStreamingResponse(client.messages) - self.requests = requests.AsyncRequestsResourceWithStreamingResponse(client.requests) - self.notifications = notifications.AsyncNotificationsResourceWithStreamingResponse(client.notifications) - self.profiles = profiles.AsyncProfilesResourceWithStreamingResponse(client.profiles) - self.tenants = tenants.AsyncTenantsResourceWithStreamingResponse(client.tenants) - self.translations = translations.AsyncTranslationsResourceWithStreamingResponse(client.translations) - self.users = users.AsyncUsersResourceWithStreamingResponse(client.users) + self._client = client + + @cached_property + def send(self) -> send.AsyncSendResourceWithStreamingResponse: + from .resources.send import AsyncSendResourceWithStreamingResponse + + return AsyncSendResourceWithStreamingResponse(self._client.send) + + @cached_property + def audiences(self) -> audiences.AsyncAudiencesResourceWithStreamingResponse: + from .resources.audiences import AsyncAudiencesResourceWithStreamingResponse + + return AsyncAudiencesResourceWithStreamingResponse(self._client.audiences) + + @cached_property + def audit_events(self) -> audit_events.AsyncAuditEventsResourceWithStreamingResponse: + from .resources.audit_events import AsyncAuditEventsResourceWithStreamingResponse + + return AsyncAuditEventsResourceWithStreamingResponse(self._client.audit_events) + + @cached_property + def auth(self) -> auth.AsyncAuthResourceWithStreamingResponse: + from .resources.auth import AsyncAuthResourceWithStreamingResponse + + return AsyncAuthResourceWithStreamingResponse(self._client.auth) + + @cached_property + def automations(self) -> automations.AsyncAutomationsResourceWithStreamingResponse: + from .resources.automations import AsyncAutomationsResourceWithStreamingResponse + + return AsyncAutomationsResourceWithStreamingResponse(self._client.automations) + + @cached_property + def brands(self) -> brands.AsyncBrandsResourceWithStreamingResponse: + from .resources.brands import AsyncBrandsResourceWithStreamingResponse + + return AsyncBrandsResourceWithStreamingResponse(self._client.brands) + + @cached_property + def bulk(self) -> bulk.AsyncBulkResourceWithStreamingResponse: + from .resources.bulk import AsyncBulkResourceWithStreamingResponse + + return AsyncBulkResourceWithStreamingResponse(self._client.bulk) + + @cached_property + def inbound(self) -> inbound.AsyncInboundResourceWithStreamingResponse: + from .resources.inbound import AsyncInboundResourceWithStreamingResponse + + return AsyncInboundResourceWithStreamingResponse(self._client.inbound) + + @cached_property + def lists(self) -> lists.AsyncListsResourceWithStreamingResponse: + from .resources.lists import AsyncListsResourceWithStreamingResponse + + return AsyncListsResourceWithStreamingResponse(self._client.lists) + + @cached_property + def messages(self) -> messages.AsyncMessagesResourceWithStreamingResponse: + from .resources.messages import AsyncMessagesResourceWithStreamingResponse + + return AsyncMessagesResourceWithStreamingResponse(self._client.messages) + + @cached_property + def requests(self) -> requests.AsyncRequestsResourceWithStreamingResponse: + from .resources.requests import AsyncRequestsResourceWithStreamingResponse + + return AsyncRequestsResourceWithStreamingResponse(self._client.requests) + + @cached_property + def notifications(self) -> notifications.AsyncNotificationsResourceWithStreamingResponse: + from .resources.notifications import AsyncNotificationsResourceWithStreamingResponse + + return AsyncNotificationsResourceWithStreamingResponse(self._client.notifications) + + @cached_property + def profiles(self) -> profiles.AsyncProfilesResourceWithStreamingResponse: + from .resources.profiles import AsyncProfilesResourceWithStreamingResponse + + return AsyncProfilesResourceWithStreamingResponse(self._client.profiles) + + @cached_property + def tenants(self) -> tenants.AsyncTenantsResourceWithStreamingResponse: + from .resources.tenants import AsyncTenantsResourceWithStreamingResponse + + return AsyncTenantsResourceWithStreamingResponse(self._client.tenants) + + @cached_property + def translations(self) -> translations.AsyncTranslationsResourceWithStreamingResponse: + from .resources.translations import AsyncTranslationsResourceWithStreamingResponse + + return AsyncTranslationsResourceWithStreamingResponse(self._client.translations) + + @cached_property + def users(self) -> users.AsyncUsersResourceWithStreamingResponse: + from .resources.users import AsyncUsersResourceWithStreamingResponse + + return AsyncUsersResourceWithStreamingResponse(self._client.users) Client = Courier diff --git a/src/courier/_version.py b/src/courier/_version.py index 00ac3fa..d0d0ce8 100644 --- a/src/courier/_version.py +++ b/src/courier/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "courier" -__version__ = "7.4.0" # x-release-please-version +__version__ = "7.5.0" # x-release-please-version diff --git a/src/courier/types/__init__.py b/src/courier/types/__init__.py index 7ed5c4e..d4c6054 100644 --- a/src/courier/types/__init__.py +++ b/src/courier/types/__init__.py @@ -2,7 +2,15 @@ from __future__ import annotations -from . import shared, tenants, notification_list_response +from . import ( + shared, + tenants, + audience, + nested_filter_config, + audience_list_response, + audience_update_response, + notification_list_response, +) from .. import _compat from .logo import Logo as Logo from .brand import Brand as Brand @@ -11,30 +19,69 @@ from .filter import Filter as Filter from .shared import ( Utm as Utm, + Expo as Expo, Rule as Rule, + Slack as Slack, + Token as Token, Paging as Paging, + Discord as Discord, + MsTeams as MsTeams, + Intercom as Intercom, Alignment as Alignment, - Recipient as Recipient, + Pagerduty as Pagerduty, TextStyle as TextStyle, + DeviceType as DeviceType, + ListFilter as ListFilter, Preference as Preference, + UserProfile as UserProfile, ElementalNode as ElementalNode, + ListRecipient as ListRecipient, + SendToChannel as SendToChannel, UserRecipient as UserRecipient, + WebhookMethod as WebhookMethod, + AirshipProfile as AirshipProfile, + AudienceFilter as AudienceFilter, MessageContext as MessageContext, MessageRouting as MessageRouting, + MultipleTokens as MultipleTokens, + SlackRecipient as SlackRecipient, + WebhookProfile as WebhookProfile, + WebhookAuthMode as WebhookAuthMode, ElementalContent as ElementalContent, + MsTeamsRecipient as MsTeamsRecipient, PreferenceStatus as PreferenceStatus, + SendToSlackEmail as SendToSlackEmail, + WebhookRecipient as WebhookRecipient, + AudienceRecipient as AudienceRecipient, ChannelPreference as ChannelPreference, ElementalBaseNode as ElementalBaseNode, + IntercomRecipient as IntercomRecipient, + SendDirectMessage as SendDirectMessage, + SendToSlackUserID as SendToSlackUserID, + PagerdutyRecipient as PagerdutyRecipient, + SendToMsTeamsEmail as SendToMsTeamsEmail, + SendToSlackChannel as SendToSlackChannel, + WebhookProfileType as WebhookProfileType, + SendToMsTeamsUserID as SendToMsTeamsUserID, + SlackBaseProperties as SlackBaseProperties, ElementalChannelNode as ElementalChannelNode, + ListPatternRecipient as ListPatternRecipient, RecipientPreferences as RecipientPreferences, ChannelClassification as ChannelClassification, ElementalContentSugar as ElementalContentSugar, MessageRoutingChannel as MessageRoutingChannel, + MsTeamsBaseProperties as MsTeamsBaseProperties, + WebhookAuthentication as WebhookAuthentication, + AirshipProfileAudience as AirshipProfileAudience, + SendToMsTeamsChannelID as SendToMsTeamsChannelID, + SendToMsTeamsChannelName as SendToMsTeamsChannelName, + UserProfileFirebaseToken as UserProfileFirebaseToken, ElementalMetaNodeWithType as ElementalMetaNodeWithType, ElementalTextNodeWithType as ElementalTextNodeWithType, ElementalImageNodeWithType as ElementalImageNodeWithType, ElementalQuoteNodeWithType as ElementalQuoteNodeWithType, ElementalActionNodeWithType as ElementalActionNodeWithType, + SendToMsTeamsConversationID as SendToMsTeamsConversationID, ElementalChannelNodeWithType as ElementalChannelNodeWithType, ElementalDividerNodeWithType as ElementalDividerNodeWithType, NotificationPreferenceDetails as NotificationPreferenceDetails, @@ -51,6 +98,7 @@ from .email_header import EmailHeader as EmailHeader from .filter_param import FilterParam as FilterParam from .brand_snippet import BrandSnippet as BrandSnippet +from .filter_config import FilterConfig as FilterConfig from .brand_settings import BrandSettings as BrandSettings from .brand_snippets import BrandSnippets as BrandSnippets from .brand_template import BrandTemplate as BrandTemplate @@ -73,6 +121,7 @@ from .brand_snippet_param import BrandSnippetParam as BrandSnippetParam from .brand_update_params import BrandUpdateParams as BrandUpdateParams from .default_preferences import DefaultPreferences as DefaultPreferences +from .filter_config_param import FilterConfigParam as FilterConfigParam from .message_list_params import MessageListParams as MessageListParams from .send_message_params import SendMessageParams as SendMessageParams from .audience_list_params import AudienceListParams as AudienceListParams @@ -81,6 +130,8 @@ from .brand_snippets_param import BrandSnippetsParam as BrandSnippetsParam from .brand_template_param import BrandTemplateParam as BrandTemplateParam from .inbound_bulk_message import InboundBulkMessage as InboundBulkMessage +from .nested_filter_config import NestedFilterConfig as NestedFilterConfig +from .single_filter_config import SingleFilterConfig as SingleFilterConfig from .tenant_list_response import TenantListResponse as TenantListResponse from .tenant_update_params import TenantUpdateParams as TenantUpdateParams from .brand_settings_in_app import BrandSettingsInApp as BrandSettingsInApp @@ -122,7 +173,9 @@ from .bulk_retrieve_job_response import BulkRetrieveJobResponse as BulkRetrieveJobResponse from .inbound_bulk_message_param import InboundBulkMessageParam as InboundBulkMessageParam from .inbound_track_event_params import InboundTrackEventParams as InboundTrackEventParams +from .nested_filter_config_param import NestedFilterConfigParam as NestedFilterConfigParam from .notification_list_response import NotificationListResponse as NotificationListResponse +from .single_filter_config_param import SingleFilterConfigParam as SingleFilterConfigParam from .tenant_list_users_response import TenantListUsersResponse as TenantListUsersResponse from .brand_settings_in_app_param import BrandSettingsInAppParam as BrandSettingsInAppParam from .audience_list_members_params import AudienceListMembersParams as AudienceListMembersParams @@ -140,10 +193,18 @@ # Pydantic can resolve the necessary references. # See: https://github.com/pydantic/pydantic/issues/11250 for more context. if _compat.PYDANTIC_V1: + audience.Audience.update_forward_refs() # type: ignore + nested_filter_config.NestedFilterConfig.update_forward_refs() # type: ignore + audience_update_response.AudienceUpdateResponse.update_forward_refs() # type: ignore + audience_list_response.AudienceListResponse.update_forward_refs() # type: ignore notification_list_response.NotificationListResponse.update_forward_refs() # type: ignore tenants.template_list_response.TemplateListResponse.update_forward_refs() # type: ignore shared.message_routing.MessageRouting.update_forward_refs() # type: ignore else: + audience.Audience.model_rebuild(_parent_namespace_depth=0) + nested_filter_config.NestedFilterConfig.model_rebuild(_parent_namespace_depth=0) + audience_update_response.AudienceUpdateResponse.model_rebuild(_parent_namespace_depth=0) + audience_list_response.AudienceListResponse.model_rebuild(_parent_namespace_depth=0) notification_list_response.NotificationListResponse.model_rebuild(_parent_namespace_depth=0) tenants.template_list_response.TemplateListResponse.model_rebuild(_parent_namespace_depth=0) shared.message_routing.MessageRouting.model_rebuild(_parent_namespace_depth=0) diff --git a/src/courier/types/audience.py b/src/courier/types/audience.py index c6ae6a4..d23c328 100644 --- a/src/courier/types/audience.py +++ b/src/courier/types/audience.py @@ -1,6 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .filter import Filter +from __future__ import annotations + from .._models import BaseModel __all__ = ["Audience"] @@ -15,10 +16,13 @@ class Audience(BaseModel): description: str """A description of the audience""" - filter: Filter + filter: "Filter" """A single filter to use for filtering""" name: str """The name of the audience""" updated_at: str + + +from .filter import Filter diff --git a/src/courier/types/audience_list_response.py b/src/courier/types/audience_list_response.py index 2a638a8..336ba50 100644 --- a/src/courier/types/audience_list_response.py +++ b/src/courier/types/audience_list_response.py @@ -1,15 +1,19 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from __future__ import annotations + from typing import List from .._models import BaseModel -from .audience import Audience from .shared.paging import Paging __all__ = ["AudienceListResponse"] class AudienceListResponse(BaseModel): - items: List[Audience] + items: List["Audience"] paging: Paging + + +from .audience import Audience diff --git a/src/courier/types/audience_update_params.py b/src/courier/types/audience_update_params.py index 3303bf4..8b23789 100644 --- a/src/courier/types/audience_update_params.py +++ b/src/courier/types/audience_update_params.py @@ -5,8 +5,6 @@ from typing import Optional from typing_extensions import TypedDict -from .filter_param import FilterParam - __all__ = ["AudienceUpdateParams"] @@ -14,8 +12,11 @@ class AudienceUpdateParams(TypedDict, total=False): description: Optional[str] """A description of the audience""" - filter: Optional[FilterParam] + filter: Optional["FilterParam"] """A single filter to use for filtering""" name: Optional[str] """The name of the audience""" + + +from .filter_param import FilterParam diff --git a/src/courier/types/audience_update_response.py b/src/courier/types/audience_update_response.py index 7067277..2f0f427 100644 --- a/src/courier/types/audience_update_response.py +++ b/src/courier/types/audience_update_response.py @@ -1,10 +1,14 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from __future__ import annotations + from .._models import BaseModel -from .audience import Audience __all__ = ["AudienceUpdateResponse"] class AudienceUpdateResponse(BaseModel): - audience: Audience + audience: "Audience" + + +from .audience import Audience diff --git a/src/courier/types/filter.py b/src/courier/types/filter.py index 902f6cd..e0e1e39 100644 --- a/src/courier/types/filter.py +++ b/src/courier/types/filter.py @@ -1,37 +1,14 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing_extensions import Literal +from __future__ import annotations -from .._models import BaseModel - -__all__ = ["Filter"] +from typing import Union +from typing_extensions import TypeAlias +from .single_filter_config import SingleFilterConfig -class Filter(BaseModel): - operator: Literal[ - "ENDS_WITH", - "EQ", - "EXISTS", - "GT", - "GTE", - "INCLUDES", - "IS_AFTER", - "IS_BEFORE", - "LT", - "LTE", - "NEQ", - "OMIT", - "STARTS_WITH", - "AND", - "OR", - ] - """The operator to use for filtering""" +__all__ = ["Filter"] - path: str - """ - The attribe name from profile whose value will be operated against the filter - value - """ +Filter: TypeAlias = Union[SingleFilterConfig, "NestedFilterConfig"] - value: str - """The value to use for filtering""" +from .nested_filter_config import NestedFilterConfig diff --git a/src/courier/types/filter_config.py b/src/courier/types/filter_config.py new file mode 100644 index 0000000..ad3e8e7 --- /dev/null +++ b/src/courier/types/filter_config.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Union +from typing_extensions import TypeAlias, TypeAliasType + +from .._compat import PYDANTIC_V1 +from .single_filter_config import SingleFilterConfig + +__all__ = ["FilterConfig"] + +if TYPE_CHECKING or not PYDANTIC_V1: + FilterConfig = TypeAliasType("FilterConfig", Union[SingleFilterConfig, "NestedFilterConfig"]) +else: + FilterConfig: TypeAlias = Union[SingleFilterConfig, "NestedFilterConfig"] + +from .nested_filter_config import NestedFilterConfig diff --git a/src/courier/types/filter_config_param.py b/src/courier/types/filter_config_param.py new file mode 100644 index 0000000..9024795 --- /dev/null +++ b/src/courier/types/filter_config_param.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Union +from typing_extensions import TypeAlias, TypeAliasType + +from .._compat import PYDANTIC_V1 +from .single_filter_config_param import SingleFilterConfigParam + +__all__ = ["FilterConfigParam"] + +if TYPE_CHECKING or not PYDANTIC_V1: + FilterConfigParam = TypeAliasType("FilterConfigParam", Union[SingleFilterConfigParam, "NestedFilterConfigParam"]) +else: + FilterConfigParam: TypeAlias = Union[SingleFilterConfigParam, "NestedFilterConfigParam"] + +from .nested_filter_config_param import NestedFilterConfigParam diff --git a/src/courier/types/filter_param.py b/src/courier/types/filter_param.py index 9044a3f..8c0458b 100644 --- a/src/courier/types/filter_param.py +++ b/src/courier/types/filter_param.py @@ -2,38 +2,13 @@ from __future__ import annotations -from typing_extensions import Literal, Required, TypedDict - -__all__ = ["FilterParam"] +from typing import Union +from typing_extensions import TypeAlias +from .single_filter_config_param import SingleFilterConfigParam -class FilterParam(TypedDict, total=False): - operator: Required[ - Literal[ - "ENDS_WITH", - "EQ", - "EXISTS", - "GT", - "GTE", - "INCLUDES", - "IS_AFTER", - "IS_BEFORE", - "LT", - "LTE", - "NEQ", - "OMIT", - "STARTS_WITH", - "AND", - "OR", - ] - ] - """The operator to use for filtering""" +__all__ = ["FilterParam"] - path: Required[str] - """ - The attribe name from profile whose value will be operated against the filter - value - """ +FilterParam: TypeAlias = Union[SingleFilterConfigParam, "NestedFilterConfigParam"] - value: Required[str] - """The value to use for filtering""" +from .nested_filter_config_param import NestedFilterConfigParam diff --git a/src/courier/types/nested_filter_config.py b/src/courier/types/nested_filter_config.py new file mode 100644 index 0000000..d206e21 --- /dev/null +++ b/src/courier/types/nested_filter_config.py @@ -0,0 +1,36 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["NestedFilterConfig"] + + +class NestedFilterConfig(BaseModel): + operator: Literal[ + "ENDS_WITH", + "EQ", + "EXISTS", + "GT", + "GTE", + "INCLUDES", + "IS_AFTER", + "IS_BEFORE", + "LT", + "LTE", + "NEQ", + "OMIT", + "STARTS_WITH", + "AND", + "OR", + ] + """The operator to use for filtering""" + + rules: List["FilterConfig"] + + +from .filter_config import FilterConfig diff --git a/src/courier/types/nested_filter_config_param.py b/src/courier/types/nested_filter_config_param.py new file mode 100644 index 0000000..ec79779 --- /dev/null +++ b/src/courier/types/nested_filter_config_param.py @@ -0,0 +1,36 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["NestedFilterConfigParam"] + + +class NestedFilterConfigParam(TypedDict, total=False): + operator: Required[ + Literal[ + "ENDS_WITH", + "EQ", + "EXISTS", + "GT", + "GTE", + "INCLUDES", + "IS_AFTER", + "IS_BEFORE", + "LT", + "LTE", + "NEQ", + "OMIT", + "STARTS_WITH", + "AND", + "OR", + ] + ] + """The operator to use for filtering""" + + rules: Required[Iterable["FilterConfigParam"]] + + +from .filter_config_param import FilterConfigParam diff --git a/src/courier/types/send_message_params.py b/src/courier/types/send_message_params.py index 3464e91..d51083a 100644 --- a/src/courier/types/send_message_params.py +++ b/src/courier/types/send_message_params.py @@ -2,15 +2,21 @@ from __future__ import annotations -from typing import Dict, Union, Iterable, Optional +from typing import Dict, Union, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from .._types import SequenceNotStr from .shared_params.utm import Utm -from .shared_params.recipient import Recipient +from .shared_params.list_recipient import ListRecipient from .shared_params.user_recipient import UserRecipient from .shared_params.message_context import MessageContext +from .shared_params.slack_recipient import SlackRecipient from .shared_params.elemental_content import ElementalContent +from .shared_params.webhook_recipient import WebhookRecipient +from .shared_params.audience_recipient import AudienceRecipient +from .shared_params.ms_teams_recipient import MsTeamsRecipient +from .shared_params.pagerduty_recipient import PagerdutyRecipient +from .shared_params.list_pattern_recipient import ListPatternRecipient from .shared_params.elemental_content_sugar import ElementalContentSugar __all__ = [ @@ -161,7 +167,16 @@ class MessageTimeout(TypedDict, total=False): provider: Optional[Dict[str, int]] -MessageTo: TypeAlias = Union[UserRecipient, Iterable[Recipient]] +MessageTo: TypeAlias = Union[ + UserRecipient, + AudienceRecipient, + ListRecipient, + ListPatternRecipient, + SlackRecipient, + MsTeamsRecipient, + PagerdutyRecipient, + WebhookRecipient, +] class Message(TypedDict, total=False): diff --git a/src/courier/types/shared/__init__.py b/src/courier/types/shared/__init__.py index e546703..fd02dd5 100644 --- a/src/courier/types/shared/__init__.py +++ b/src/courier/types/shared/__init__.py @@ -1,30 +1,69 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .utm import Utm as Utm +from .expo import Expo as Expo from .rule import Rule as Rule +from .slack import Slack as Slack +from .token import Token as Token from .paging import Paging as Paging +from .discord import Discord as Discord +from .intercom import Intercom as Intercom +from .ms_teams import MsTeams as MsTeams from .alignment import Alignment as Alignment -from .recipient import Recipient as Recipient +from .pagerduty import Pagerduty as Pagerduty from .preference import Preference as Preference from .text_style import TextStyle as TextStyle +from .device_type import DeviceType as DeviceType +from .list_filter import ListFilter as ListFilter +from .user_profile import UserProfile as UserProfile from .elemental_node import ElementalNode as ElementalNode +from .list_recipient import ListRecipient as ListRecipient from .user_recipient import UserRecipient as UserRecipient +from .webhook_method import WebhookMethod as WebhookMethod +from .airship_profile import AirshipProfile as AirshipProfile +from .audience_filter import AudienceFilter as AudienceFilter from .message_context import MessageContext as MessageContext from .message_routing import MessageRouting as MessageRouting +from .multiple_tokens import MultipleTokens as MultipleTokens +from .send_to_channel import SendToChannel as SendToChannel +from .slack_recipient import SlackRecipient as SlackRecipient +from .webhook_profile import WebhookProfile as WebhookProfile from .elemental_content import ElementalContent as ElementalContent from .preference_status import PreferenceStatus as PreferenceStatus +from .webhook_auth_mode import WebhookAuthMode as WebhookAuthMode +from .webhook_recipient import WebhookRecipient as WebhookRecipient +from .audience_recipient import AudienceRecipient as AudienceRecipient from .channel_preference import ChannelPreference as ChannelPreference +from .intercom_recipient import IntercomRecipient as IntercomRecipient +from .ms_teams_recipient import MsTeamsRecipient as MsTeamsRecipient from .elemental_base_node import ElementalBaseNode as ElementalBaseNode +from .pagerduty_recipient import PagerdutyRecipient as PagerdutyRecipient +from .send_direct_message import SendDirectMessage as SendDirectMessage +from .send_to_slack_email import SendToSlackEmail as SendToSlackEmail +from .webhook_profile_type import WebhookProfileType as WebhookProfileType from .recipient_preferences import RecipientPreferences as RecipientPreferences +from .send_to_slack_channel import SendToSlackChannel as SendToSlackChannel +from .send_to_slack_user_id import SendToSlackUserID as SendToSlackUserID +from .slack_base_properties import SlackBaseProperties as SlackBaseProperties from .channel_classification import ChannelClassification as ChannelClassification from .elemental_channel_node import ElementalChannelNode as ElementalChannelNode +from .list_pattern_recipient import ListPatternRecipient as ListPatternRecipient +from .send_to_ms_teams_email import SendToMsTeamsEmail as SendToMsTeamsEmail +from .webhook_authentication import WebhookAuthentication as WebhookAuthentication from .elemental_content_sugar import ElementalContentSugar as ElementalContentSugar from .message_routing_channel import MessageRoutingChannel as MessageRoutingChannel +from .airship_profile_audience import AirshipProfileAudience as AirshipProfileAudience +from .ms_teams_base_properties import MsTeamsBaseProperties as MsTeamsBaseProperties +from .send_to_ms_teams_user_id import SendToMsTeamsUserID as SendToMsTeamsUserID +from .send_to_ms_teams_channel_id import SendToMsTeamsChannelID as SendToMsTeamsChannelID +from .user_profile_firebase_token import UserProfileFirebaseToken as UserProfileFirebaseToken from .elemental_meta_node_with_type import ElementalMetaNodeWithType as ElementalMetaNodeWithType from .elemental_text_node_with_type import ElementalTextNodeWithType as ElementalTextNodeWithType +from .send_to_ms_teams_channel_name import SendToMsTeamsChannelName as SendToMsTeamsChannelName from .elemental_image_node_with_type import ElementalImageNodeWithType as ElementalImageNodeWithType from .elemental_quote_node_with_type import ElementalQuoteNodeWithType as ElementalQuoteNodeWithType from .elemental_action_node_with_type import ElementalActionNodeWithType as ElementalActionNodeWithType from .notification_preference_details import NotificationPreferenceDetails as NotificationPreferenceDetails from .elemental_channel_node_with_type import ElementalChannelNodeWithType as ElementalChannelNodeWithType from .elemental_divider_node_with_type import ElementalDividerNodeWithType as ElementalDividerNodeWithType +from .send_to_ms_teams_conversation_id import SendToMsTeamsConversationID as SendToMsTeamsConversationID diff --git a/src/courier/types/shared/airship_profile.py b/src/courier/types/shared/airship_profile.py new file mode 100644 index 0000000..9b8f757 --- /dev/null +++ b/src/courier/types/shared/airship_profile.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List + +from ..._models import BaseModel +from .device_type import DeviceType +from .airship_profile_audience import AirshipProfileAudience + +__all__ = ["AirshipProfile"] + + +class AirshipProfile(BaseModel): + audience: AirshipProfileAudience + + device_types: List[DeviceType] diff --git a/src/courier/types/shared/airship_profile_audience.py b/src/courier/types/shared/airship_profile_audience.py new file mode 100644 index 0000000..b00cb2d --- /dev/null +++ b/src/courier/types/shared/airship_profile_audience.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["AirshipProfileAudience"] + + +class AirshipProfileAudience(BaseModel): + named_user: str diff --git a/src/courier/types/shared/audience_filter.py b/src/courier/types/shared/audience_filter.py new file mode 100644 index 0000000..b1092a9 --- /dev/null +++ b/src/courier/types/shared/audience_filter.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["AudienceFilter"] + + +class AudienceFilter(BaseModel): + operator: Literal["MEMBER_OF"] + """Send to users only if they are member of the account""" + + path: Literal["account_id"] + + value: str diff --git a/src/courier/types/shared/audience_recipient.py b/src/courier/types/shared/audience_recipient.py new file mode 100644 index 0000000..f1d772d --- /dev/null +++ b/src/courier/types/shared/audience_recipient.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional + +from ..._models import BaseModel +from .audience_filter import AudienceFilter + +__all__ = ["AudienceRecipient"] + + +class AudienceRecipient(BaseModel): + """Send to all users in an audience""" + + audience_id: str + """A unique identifier associated with an Audience. + + A message will be sent to each user in the audience. + """ + + data: Optional[Dict[str, object]] = None + + filters: Optional[List[AudienceFilter]] = None diff --git a/src/courier/types/shared/device_type.py b/src/courier/types/shared/device_type.py new file mode 100644 index 0000000..add6185 --- /dev/null +++ b/src/courier/types/shared/device_type.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import TypeAlias + +__all__ = ["DeviceType"] + +DeviceType: TypeAlias = str diff --git a/src/courier/types/shared/discord.py b/src/courier/types/shared/discord.py new file mode 100644 index 0000000..f809db8 --- /dev/null +++ b/src/courier/types/shared/discord.py @@ -0,0 +1,11 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union +from typing_extensions import TypeAlias + +from .send_to_channel import SendToChannel +from .send_direct_message import SendDirectMessage + +__all__ = ["Discord"] + +Discord: TypeAlias = Union[SendToChannel, SendDirectMessage] diff --git a/src/courier/types/shared/expo.py b/src/courier/types/shared/expo.py new file mode 100644 index 0000000..f99b235 --- /dev/null +++ b/src/courier/types/shared/expo.py @@ -0,0 +1,11 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union +from typing_extensions import TypeAlias + +from .token import Token +from .multiple_tokens import MultipleTokens + +__all__ = ["Expo"] + +Expo: TypeAlias = Union[Token, MultipleTokens] diff --git a/src/courier/types/shared/intercom.py b/src/courier/types/shared/intercom.py new file mode 100644 index 0000000..f28d1f6 --- /dev/null +++ b/src/courier/types/shared/intercom.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel +from .intercom_recipient import IntercomRecipient + +__all__ = ["Intercom"] + + +class Intercom(BaseModel): + from_: str = FieldInfo(alias="from") + + to: IntercomRecipient diff --git a/src/courier/types/shared/intercom_recipient.py b/src/courier/types/shared/intercom_recipient.py new file mode 100644 index 0000000..d560f72 --- /dev/null +++ b/src/courier/types/shared/intercom_recipient.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["IntercomRecipient"] + + +class IntercomRecipient(BaseModel): + id: str diff --git a/src/courier/types/shared/list_filter.py b/src/courier/types/shared/list_filter.py new file mode 100644 index 0000000..07c5fc1 --- /dev/null +++ b/src/courier/types/shared/list_filter.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["ListFilter"] + + +class ListFilter(BaseModel): + operator: Literal["MEMBER_OF"] + """Send to users only if they are member of the account""" + + path: Literal["account_id"] + + value: str diff --git a/src/courier/types/shared/list_pattern_recipient.py b/src/courier/types/shared/list_pattern_recipient.py new file mode 100644 index 0000000..6743130 --- /dev/null +++ b/src/courier/types/shared/list_pattern_recipient.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, Optional + +from ..._models import BaseModel + +__all__ = ["ListPatternRecipient"] + + +class ListPatternRecipient(BaseModel): + """Send to users in lists matching a pattern""" + + data: Optional[Dict[str, object]] = None + + list_pattern: Optional[str] = None diff --git a/src/courier/types/shared/list_recipient.py b/src/courier/types/shared/list_recipient.py new file mode 100644 index 0000000..19a4a32 --- /dev/null +++ b/src/courier/types/shared/list_recipient.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional + +from ..._models import BaseModel +from .list_filter import ListFilter + +__all__ = ["ListRecipient"] + + +class ListRecipient(BaseModel): + """Send to all users in a specific list""" + + data: Optional[Dict[str, object]] = None + + filters: Optional[List[ListFilter]] = None + + list_id: Optional[str] = None diff --git a/src/courier/types/shared/ms_teams.py b/src/courier/types/shared/ms_teams.py new file mode 100644 index 0000000..911bb9f --- /dev/null +++ b/src/courier/types/shared/ms_teams.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union +from typing_extensions import TypeAlias + +from .send_to_ms_teams_email import SendToMsTeamsEmail +from .send_to_ms_teams_user_id import SendToMsTeamsUserID +from .send_to_ms_teams_channel_id import SendToMsTeamsChannelID +from .send_to_ms_teams_channel_name import SendToMsTeamsChannelName +from .send_to_ms_teams_conversation_id import SendToMsTeamsConversationID + +__all__ = ["MsTeams"] + +MsTeams: TypeAlias = Union[ + SendToMsTeamsUserID, + SendToMsTeamsEmail, + SendToMsTeamsChannelID, + SendToMsTeamsConversationID, + SendToMsTeamsChannelName, +] diff --git a/src/courier/types/shared/ms_teams_base_properties.py b/src/courier/types/shared/ms_teams_base_properties.py new file mode 100644 index 0000000..1764a50 --- /dev/null +++ b/src/courier/types/shared/ms_teams_base_properties.py @@ -0,0 +1,11 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["MsTeamsBaseProperties"] + + +class MsTeamsBaseProperties(BaseModel): + service_url: str + + tenant_id: str diff --git a/src/courier/types/shared/ms_teams_recipient.py b/src/courier/types/shared/ms_teams_recipient.py new file mode 100644 index 0000000..5e72575 --- /dev/null +++ b/src/courier/types/shared/ms_teams_recipient.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .ms_teams import MsTeams +from ..._models import BaseModel + +__all__ = ["MsTeamsRecipient"] + + +class MsTeamsRecipient(BaseModel): + """Send via Microsoft Teams""" + + ms_teams: MsTeams diff --git a/src/courier/types/shared/multiple_tokens.py b/src/courier/types/shared/multiple_tokens.py new file mode 100644 index 0000000..1e47c80 --- /dev/null +++ b/src/courier/types/shared/multiple_tokens.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List + +from .token import Token +from ..._models import BaseModel + +__all__ = ["MultipleTokens"] + + +class MultipleTokens(BaseModel): + tokens: List[Token] diff --git a/src/courier/types/shared/pagerduty.py b/src/courier/types/shared/pagerduty.py new file mode 100644 index 0000000..e6e5eb4 --- /dev/null +++ b/src/courier/types/shared/pagerduty.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from ..._models import BaseModel + +__all__ = ["Pagerduty"] + + +class Pagerduty(BaseModel): + event_action: Optional[str] = None + + routing_key: Optional[str] = None + + severity: Optional[str] = None + + source: Optional[str] = None diff --git a/src/courier/types/shared/pagerduty_recipient.py b/src/courier/types/shared/pagerduty_recipient.py new file mode 100644 index 0000000..c4ed95e --- /dev/null +++ b/src/courier/types/shared/pagerduty_recipient.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel +from .pagerduty import Pagerduty + +__all__ = ["PagerdutyRecipient"] + + +class PagerdutyRecipient(BaseModel): + """Send via PagerDuty""" + + pagerduty: Pagerduty diff --git a/src/courier/types/shared/recipient.py b/src/courier/types/shared/recipient.py deleted file mode 100644 index ba01ade..0000000 --- a/src/courier/types/shared/recipient.py +++ /dev/null @@ -1,52 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Dict, Optional - -from pydantic import Field as FieldInfo - -from ..._models import BaseModel -from .preference import Preference -from .message_context import MessageContext - -__all__ = ["Recipient", "Preferences"] - - -class Preferences(BaseModel): - notifications: Dict[str, Preference] - - categories: Optional[Dict[str, Preference]] = None - - template_id: Optional[str] = FieldInfo(alias="templateId", default=None) - - -class Recipient(BaseModel): - account_id: Optional[str] = None - """Deprecated - Use `tenant_id` instead.""" - - context: Optional[MessageContext] = None - """Context such as tenant_id to send the notification with.""" - - data: Optional[Dict[str, object]] = None - - email: Optional[str] = None - """The user's email address.""" - - list_id: Optional[str] = None - """The id of the list to send the message to.""" - - locale: Optional[str] = None - """The user's preferred ISO 639-1 language code.""" - - phone_number: Optional[str] = None - """The user's phone number.""" - - preferences: Optional[Preferences] = None - - tenant_id: Optional[str] = None - """The id of the tenant the user is associated with.""" - - user_id: Optional[str] = None - """The user's unique identifier. - - Typically, this will match the user id of a user in your system. - """ diff --git a/src/courier/types/shared/send_direct_message.py b/src/courier/types/shared/send_direct_message.py new file mode 100644 index 0000000..3254e24 --- /dev/null +++ b/src/courier/types/shared/send_direct_message.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["SendDirectMessage"] + + +class SendDirectMessage(BaseModel): + user_id: str diff --git a/src/courier/types/shared/send_to_channel.py b/src/courier/types/shared/send_to_channel.py new file mode 100644 index 0000000..389b448 --- /dev/null +++ b/src/courier/types/shared/send_to_channel.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["SendToChannel"] + + +class SendToChannel(BaseModel): + channel_id: str diff --git a/src/courier/types/shared/send_to_ms_teams_channel_id.py b/src/courier/types/shared/send_to_ms_teams_channel_id.py new file mode 100644 index 0000000..f51aeba --- /dev/null +++ b/src/courier/types/shared/send_to_ms_teams_channel_id.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["SendToMsTeamsChannelID"] + + +class SendToMsTeamsChannelID(BaseModel): + channel_id: str + + service_url: str + + tenant_id: str diff --git a/src/courier/types/shared/send_to_ms_teams_channel_name.py b/src/courier/types/shared/send_to_ms_teams_channel_name.py new file mode 100644 index 0000000..bfc1806 --- /dev/null +++ b/src/courier/types/shared/send_to_ms_teams_channel_name.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["SendToMsTeamsChannelName"] + + +class SendToMsTeamsChannelName(BaseModel): + channel_name: str + + service_url: str + + team_id: str + + tenant_id: str diff --git a/src/courier/types/shared/send_to_ms_teams_conversation_id.py b/src/courier/types/shared/send_to_ms_teams_conversation_id.py new file mode 100644 index 0000000..cbdf8f8 --- /dev/null +++ b/src/courier/types/shared/send_to_ms_teams_conversation_id.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["SendToMsTeamsConversationID"] + + +class SendToMsTeamsConversationID(BaseModel): + conversation_id: str + + service_url: str + + tenant_id: str diff --git a/src/courier/types/shared/send_to_ms_teams_email.py b/src/courier/types/shared/send_to_ms_teams_email.py new file mode 100644 index 0000000..bd05c24 --- /dev/null +++ b/src/courier/types/shared/send_to_ms_teams_email.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["SendToMsTeamsEmail"] + + +class SendToMsTeamsEmail(BaseModel): + email: str + + service_url: str + + tenant_id: str diff --git a/src/courier/types/shared/send_to_ms_teams_user_id.py b/src/courier/types/shared/send_to_ms_teams_user_id.py new file mode 100644 index 0000000..23787d6 --- /dev/null +++ b/src/courier/types/shared/send_to_ms_teams_user_id.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["SendToMsTeamsUserID"] + + +class SendToMsTeamsUserID(BaseModel): + service_url: str + + tenant_id: str + + user_id: str diff --git a/src/courier/types/shared/send_to_slack_channel.py b/src/courier/types/shared/send_to_slack_channel.py new file mode 100644 index 0000000..d44c9ac --- /dev/null +++ b/src/courier/types/shared/send_to_slack_channel.py @@ -0,0 +1,11 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["SendToSlackChannel"] + + +class SendToSlackChannel(BaseModel): + access_token: str + + channel: str diff --git a/src/courier/types/shared/send_to_slack_email.py b/src/courier/types/shared/send_to_slack_email.py new file mode 100644 index 0000000..83765a9 --- /dev/null +++ b/src/courier/types/shared/send_to_slack_email.py @@ -0,0 +1,11 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["SendToSlackEmail"] + + +class SendToSlackEmail(BaseModel): + access_token: str + + email: str diff --git a/src/courier/types/shared/send_to_slack_user_id.py b/src/courier/types/shared/send_to_slack_user_id.py new file mode 100644 index 0000000..0227aa8 --- /dev/null +++ b/src/courier/types/shared/send_to_slack_user_id.py @@ -0,0 +1,11 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["SendToSlackUserID"] + + +class SendToSlackUserID(BaseModel): + access_token: str + + user_id: str diff --git a/src/courier/types/shared/slack.py b/src/courier/types/shared/slack.py new file mode 100644 index 0000000..ba28a76 --- /dev/null +++ b/src/courier/types/shared/slack.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union +from typing_extensions import TypeAlias + +from .send_to_slack_email import SendToSlackEmail +from .send_to_slack_channel import SendToSlackChannel +from .send_to_slack_user_id import SendToSlackUserID + +__all__ = ["Slack"] + +Slack: TypeAlias = Union[SendToSlackChannel, SendToSlackEmail, SendToSlackUserID] diff --git a/src/courier/types/shared/slack_base_properties.py b/src/courier/types/shared/slack_base_properties.py new file mode 100644 index 0000000..bf87883 --- /dev/null +++ b/src/courier/types/shared/slack_base_properties.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["SlackBaseProperties"] + + +class SlackBaseProperties(BaseModel): + access_token: str diff --git a/src/courier/types/shared/slack_recipient.py b/src/courier/types/shared/slack_recipient.py new file mode 100644 index 0000000..e3f2f68 --- /dev/null +++ b/src/courier/types/shared/slack_recipient.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .slack import Slack +from ..._models import BaseModel + +__all__ = ["SlackRecipient"] + + +class SlackRecipient(BaseModel): + """Send via Slack (channel, email, or user_id)""" + + slack: Slack diff --git a/src/courier/types/shared/token.py b/src/courier/types/shared/token.py new file mode 100644 index 0000000..ccdade1 --- /dev/null +++ b/src/courier/types/shared/token.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel + +__all__ = ["Token"] + + +class Token(BaseModel): + token: str diff --git a/src/courier/types/shared/user_profile.py b/src/courier/types/shared/user_profile.py new file mode 100644 index 0000000..18138d9 --- /dev/null +++ b/src/courier/types/shared/user_profile.py @@ -0,0 +1,99 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, Optional + +from pydantic import Field as FieldInfo + +from .expo import Expo +from .slack import Slack +from .discord import Discord +from .intercom import Intercom +from .ms_teams import MsTeams +from ..._models import BaseModel +from .airship_profile import AirshipProfile +from .user_profile_firebase_token import UserProfileFirebaseToken + +__all__ = ["UserProfile", "Address"] + + +class Address(BaseModel): + country: str + + formatted: str + + locality: str + + postal_code: str + + region: str + + street_address: str + + +class UserProfile(BaseModel): + address: Optional[Address] = None + + airship: Optional[AirshipProfile] = None + + apn: Optional[str] = None + + birthdate: Optional[str] = None + + custom: Optional[Dict[str, object]] = None + """A free form object. + + Due to a limitation of the API Explorer, you can only enter string key/values + below, but this API accepts more complex object structures. + """ + + discord: Optional[Discord] = None + + email: Optional[str] = None + + email_verified: Optional[bool] = None + + expo: Optional[Expo] = None + + facebook_psid: Optional[str] = FieldInfo(alias="facebookPSID", default=None) + + family_name: Optional[str] = None + + firebase_token: Optional[UserProfileFirebaseToken] = FieldInfo(alias="firebaseToken", default=None) + + gender: Optional[str] = None + + given_name: Optional[str] = None + + intercom: Optional[Intercom] = None + + locale: Optional[str] = None + + middle_name: Optional[str] = None + + ms_teams: Optional[MsTeams] = None + + name: Optional[str] = None + + nickname: Optional[str] = None + + phone_number: Optional[str] = None + + phone_number_verified: Optional[bool] = None + + picture: Optional[str] = None + + preferred_name: Optional[str] = None + + profile: Optional[str] = None + + slack: Optional[Slack] = None + + sub: Optional[str] = None + + target_arn: Optional[str] = None + + updated_at: Optional[str] = None + + website: Optional[str] = None + + zoneinfo: Optional[str] = None diff --git a/src/courier/types/shared/user_profile_firebase_token.py b/src/courier/types/shared/user_profile_firebase_token.py new file mode 100644 index 0000000..dd8e208 --- /dev/null +++ b/src/courier/types/shared/user_profile_firebase_token.py @@ -0,0 +1,8 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union +from typing_extensions import TypeAlias + +__all__ = ["UserProfileFirebaseToken"] + +UserProfileFirebaseToken: TypeAlias = Union[str, List[str]] diff --git a/src/courier/types/shared/webhook_auth_mode.py b/src/courier/types/shared/webhook_auth_mode.py new file mode 100644 index 0000000..1cdb0ad --- /dev/null +++ b/src/courier/types/shared/webhook_auth_mode.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["WebhookAuthMode"] + +WebhookAuthMode: TypeAlias = Literal["none", "basic", "bearer"] diff --git a/src/courier/types/shared/webhook_authentication.py b/src/courier/types/shared/webhook_authentication.py new file mode 100644 index 0000000..0ade6be --- /dev/null +++ b/src/courier/types/shared/webhook_authentication.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from ..._models import BaseModel +from .webhook_auth_mode import WebhookAuthMode + +__all__ = ["WebhookAuthentication"] + + +class WebhookAuthentication(BaseModel): + mode: WebhookAuthMode + """The authentication mode to use. Defaults to 'none' if not specified.""" + + token: Optional[str] = None + """Token for bearer authentication.""" + + password: Optional[str] = None + """Password for basic authentication.""" + + username: Optional[str] = None + """Username for basic authentication.""" diff --git a/src/courier/types/shared/webhook_method.py b/src/courier/types/shared/webhook_method.py new file mode 100644 index 0000000..566044b --- /dev/null +++ b/src/courier/types/shared/webhook_method.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["WebhookMethod"] + +WebhookMethod: TypeAlias = Literal["POST", "PUT"] diff --git a/src/courier/types/shared/webhook_profile.py b/src/courier/types/shared/webhook_profile.py new file mode 100644 index 0000000..3177899 --- /dev/null +++ b/src/courier/types/shared/webhook_profile.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, Optional + +from ..._models import BaseModel +from .webhook_method import WebhookMethod +from .webhook_profile_type import WebhookProfileType +from .webhook_authentication import WebhookAuthentication + +__all__ = ["WebhookProfile"] + + +class WebhookProfile(BaseModel): + url: str + """The URL to send the webhook request to.""" + + authentication: Optional[WebhookAuthentication] = None + """Authentication configuration for the webhook request.""" + + headers: Optional[Dict[str, str]] = None + """Custom headers to include in the webhook request.""" + + method: Optional[WebhookMethod] = None + """The HTTP method to use for the webhook request. + + Defaults to POST if not specified. + """ + + profile: Optional[WebhookProfileType] = None + """Specifies what profile information is included in the request payload. + + Defaults to 'limited' if not specified. + """ diff --git a/src/courier/types/shared/webhook_profile_type.py b/src/courier/types/shared/webhook_profile_type.py new file mode 100644 index 0000000..0726b1e --- /dev/null +++ b/src/courier/types/shared/webhook_profile_type.py @@ -0,0 +1,7 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["WebhookProfileType"] + +WebhookProfileType: TypeAlias = Literal["limited", "expanded"] diff --git a/src/courier/types/shared/webhook_recipient.py b/src/courier/types/shared/webhook_recipient.py new file mode 100644 index 0000000..b486ad8 --- /dev/null +++ b/src/courier/types/shared/webhook_recipient.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel +from .webhook_profile import WebhookProfile + +__all__ = ["WebhookRecipient"] + + +class WebhookRecipient(BaseModel): + """Send via webhook""" + + webhook: WebhookProfile diff --git a/src/courier/types/shared_params/__init__.py b/src/courier/types/shared_params/__init__.py index a9fa4e8..be5b8bf 100644 --- a/src/courier/types/shared_params/__init__.py +++ b/src/courier/types/shared_params/__init__.py @@ -2,26 +2,50 @@ from .utm import Utm as Utm from .rule import Rule as Rule -from .recipient import Recipient as Recipient +from .slack import Slack as Slack +from .ms_teams import MsTeams as MsTeams +from .pagerduty import Pagerduty as Pagerduty from .preference import Preference as Preference +from .list_filter import ListFilter as ListFilter from .elemental_node import ElementalNode as ElementalNode +from .list_recipient import ListRecipient as ListRecipient from .user_recipient import UserRecipient as UserRecipient +from .webhook_method import WebhookMethod as WebhookMethod +from .audience_filter import AudienceFilter as AudienceFilter from .message_context import MessageContext as MessageContext from .message_routing import MessageRouting as MessageRouting +from .slack_recipient import SlackRecipient as SlackRecipient +from .webhook_profile import WebhookProfile as WebhookProfile from .elemental_content import ElementalContent as ElementalContent from .preference_status import PreferenceStatus as PreferenceStatus +from .webhook_auth_mode import WebhookAuthMode as WebhookAuthMode +from .webhook_recipient import WebhookRecipient as WebhookRecipient +from .audience_recipient import AudienceRecipient as AudienceRecipient from .channel_preference import ChannelPreference as ChannelPreference +from .ms_teams_recipient import MsTeamsRecipient as MsTeamsRecipient from .elemental_base_node import ElementalBaseNode as ElementalBaseNode +from .pagerduty_recipient import PagerdutyRecipient as PagerdutyRecipient +from .send_to_slack_email import SendToSlackEmail as SendToSlackEmail +from .webhook_profile_type import WebhookProfileType as WebhookProfileType from .recipient_preferences import RecipientPreferences as RecipientPreferences +from .send_to_slack_channel import SendToSlackChannel as SendToSlackChannel +from .send_to_slack_user_id import SendToSlackUserID as SendToSlackUserID from .channel_classification import ChannelClassification as ChannelClassification from .elemental_channel_node import ElementalChannelNode as ElementalChannelNode +from .list_pattern_recipient import ListPatternRecipient as ListPatternRecipient +from .send_to_ms_teams_email import SendToMsTeamsEmail as SendToMsTeamsEmail +from .webhook_authentication import WebhookAuthentication as WebhookAuthentication from .elemental_content_sugar import ElementalContentSugar as ElementalContentSugar from .message_routing_channel import MessageRoutingChannel as MessageRoutingChannel +from .send_to_ms_teams_user_id import SendToMsTeamsUserID as SendToMsTeamsUserID +from .send_to_ms_teams_channel_id import SendToMsTeamsChannelID as SendToMsTeamsChannelID from .elemental_meta_node_with_type import ElementalMetaNodeWithType as ElementalMetaNodeWithType from .elemental_text_node_with_type import ElementalTextNodeWithType as ElementalTextNodeWithType +from .send_to_ms_teams_channel_name import SendToMsTeamsChannelName as SendToMsTeamsChannelName from .elemental_image_node_with_type import ElementalImageNodeWithType as ElementalImageNodeWithType from .elemental_quote_node_with_type import ElementalQuoteNodeWithType as ElementalQuoteNodeWithType from .elemental_action_node_with_type import ElementalActionNodeWithType as ElementalActionNodeWithType from .notification_preference_details import NotificationPreferenceDetails as NotificationPreferenceDetails from .elemental_channel_node_with_type import ElementalChannelNodeWithType as ElementalChannelNodeWithType from .elemental_divider_node_with_type import ElementalDividerNodeWithType as ElementalDividerNodeWithType +from .send_to_ms_teams_conversation_id import SendToMsTeamsConversationID as SendToMsTeamsConversationID diff --git a/src/courier/types/shared_params/audience_filter.py b/src/courier/types/shared_params/audience_filter.py new file mode 100644 index 0000000..401bcc2 --- /dev/null +++ b/src/courier/types/shared_params/audience_filter.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["AudienceFilter"] + + +class AudienceFilter(TypedDict, total=False): + operator: Required[Literal["MEMBER_OF"]] + """Send to users only if they are member of the account""" + + path: Required[Literal["account_id"]] + + value: Required[str] diff --git a/src/courier/types/shared_params/audience_recipient.py b/src/courier/types/shared_params/audience_recipient.py new file mode 100644 index 0000000..dbea54b --- /dev/null +++ b/src/courier/types/shared_params/audience_recipient.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Iterable, Optional +from typing_extensions import Required, TypedDict + +from .audience_filter import AudienceFilter + +__all__ = ["AudienceRecipient"] + + +class AudienceRecipient(TypedDict, total=False): + """Send to all users in an audience""" + + audience_id: Required[str] + """A unique identifier associated with an Audience. + + A message will be sent to each user in the audience. + """ + + data: Optional[Dict[str, object]] + + filters: Optional[Iterable[AudienceFilter]] diff --git a/src/courier/types/shared_params/list_filter.py b/src/courier/types/shared_params/list_filter.py new file mode 100644 index 0000000..2c798cf --- /dev/null +++ b/src/courier/types/shared_params/list_filter.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["ListFilter"] + + +class ListFilter(TypedDict, total=False): + operator: Required[Literal["MEMBER_OF"]] + """Send to users only if they are member of the account""" + + path: Required[Literal["account_id"]] + + value: Required[str] diff --git a/src/courier/types/shared_params/list_pattern_recipient.py b/src/courier/types/shared_params/list_pattern_recipient.py new file mode 100644 index 0000000..25aeec2 --- /dev/null +++ b/src/courier/types/shared_params/list_pattern_recipient.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Optional +from typing_extensions import TypedDict + +__all__ = ["ListPatternRecipient"] + + +class ListPatternRecipient(TypedDict, total=False): + """Send to users in lists matching a pattern""" + + data: Optional[Dict[str, object]] + + list_pattern: Optional[str] diff --git a/src/courier/types/shared_params/list_recipient.py b/src/courier/types/shared_params/list_recipient.py new file mode 100644 index 0000000..aed51ab --- /dev/null +++ b/src/courier/types/shared_params/list_recipient.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Iterable, Optional +from typing_extensions import TypedDict + +from .list_filter import ListFilter + +__all__ = ["ListRecipient"] + + +class ListRecipient(TypedDict, total=False): + """Send to all users in a specific list""" + + data: Optional[Dict[str, object]] + + filters: Optional[Iterable[ListFilter]] + + list_id: Optional[str] diff --git a/src/courier/types/shared_params/ms_teams.py b/src/courier/types/shared_params/ms_teams.py new file mode 100644 index 0000000..876fc34 --- /dev/null +++ b/src/courier/types/shared_params/ms_teams.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import TypeAlias + +from .send_to_ms_teams_email import SendToMsTeamsEmail +from .send_to_ms_teams_user_id import SendToMsTeamsUserID +from .send_to_ms_teams_channel_id import SendToMsTeamsChannelID +from .send_to_ms_teams_channel_name import SendToMsTeamsChannelName +from .send_to_ms_teams_conversation_id import SendToMsTeamsConversationID + +__all__ = ["MsTeams"] + +MsTeams: TypeAlias = Union[ + SendToMsTeamsUserID, + SendToMsTeamsEmail, + SendToMsTeamsChannelID, + SendToMsTeamsConversationID, + SendToMsTeamsChannelName, +] diff --git a/src/courier/types/shared_params/ms_teams_recipient.py b/src/courier/types/shared_params/ms_teams_recipient.py new file mode 100644 index 0000000..4dd36ec --- /dev/null +++ b/src/courier/types/shared_params/ms_teams_recipient.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +from .ms_teams import MsTeams + +__all__ = ["MsTeamsRecipient"] + + +class MsTeamsRecipient(TypedDict, total=False): + """Send via Microsoft Teams""" + + ms_teams: Required[MsTeams] diff --git a/src/courier/types/shared_params/pagerduty.py b/src/courier/types/shared_params/pagerduty.py new file mode 100644 index 0000000..2045666 --- /dev/null +++ b/src/courier/types/shared_params/pagerduty.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import TypedDict + +__all__ = ["Pagerduty"] + + +class Pagerduty(TypedDict, total=False): + event_action: Optional[str] + + routing_key: Optional[str] + + severity: Optional[str] + + source: Optional[str] diff --git a/src/courier/types/shared_params/pagerduty_recipient.py b/src/courier/types/shared_params/pagerduty_recipient.py new file mode 100644 index 0000000..131145b --- /dev/null +++ b/src/courier/types/shared_params/pagerduty_recipient.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +from .pagerduty import Pagerduty + +__all__ = ["PagerdutyRecipient"] + + +class PagerdutyRecipient(TypedDict, total=False): + """Send via PagerDuty""" + + pagerduty: Required[Pagerduty] diff --git a/src/courier/types/shared_params/recipient.py b/src/courier/types/shared_params/recipient.py deleted file mode 100644 index 30a368a..0000000 --- a/src/courier/types/shared_params/recipient.py +++ /dev/null @@ -1,53 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Dict, Optional -from typing_extensions import Required, Annotated, TypedDict - -from ..._utils import PropertyInfo -from .preference import Preference -from .message_context import MessageContext - -__all__ = ["Recipient", "Preferences"] - - -class Preferences(TypedDict, total=False): - notifications: Required[Dict[str, Preference]] - - categories: Optional[Dict[str, Preference]] - - template_id: Annotated[Optional[str], PropertyInfo(alias="templateId")] - - -class Recipient(TypedDict, total=False): - account_id: Optional[str] - """Deprecated - Use `tenant_id` instead.""" - - context: Optional[MessageContext] - """Context such as tenant_id to send the notification with.""" - - data: Optional[Dict[str, object]] - - email: Optional[str] - """The user's email address.""" - - list_id: Optional[str] - """The id of the list to send the message to.""" - - locale: Optional[str] - """The user's preferred ISO 639-1 language code.""" - - phone_number: Optional[str] - """The user's phone number.""" - - preferences: Optional[Preferences] - - tenant_id: Optional[str] - """The id of the tenant the user is associated with.""" - - user_id: Optional[str] - """The user's unique identifier. - - Typically, this will match the user id of a user in your system. - """ diff --git a/src/courier/types/shared_params/send_to_ms_teams_channel_id.py b/src/courier/types/shared_params/send_to_ms_teams_channel_id.py new file mode 100644 index 0000000..60b130d --- /dev/null +++ b/src/courier/types/shared_params/send_to_ms_teams_channel_id.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["SendToMsTeamsChannelID"] + + +class SendToMsTeamsChannelID(TypedDict, total=False): + channel_id: Required[str] + + service_url: Required[str] + + tenant_id: Required[str] diff --git a/src/courier/types/shared_params/send_to_ms_teams_channel_name.py b/src/courier/types/shared_params/send_to_ms_teams_channel_name.py new file mode 100644 index 0000000..d39854e --- /dev/null +++ b/src/courier/types/shared_params/send_to_ms_teams_channel_name.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["SendToMsTeamsChannelName"] + + +class SendToMsTeamsChannelName(TypedDict, total=False): + channel_name: Required[str] + + service_url: Required[str] + + team_id: Required[str] + + tenant_id: Required[str] diff --git a/src/courier/types/shared_params/send_to_ms_teams_conversation_id.py b/src/courier/types/shared_params/send_to_ms_teams_conversation_id.py new file mode 100644 index 0000000..187335c --- /dev/null +++ b/src/courier/types/shared_params/send_to_ms_teams_conversation_id.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["SendToMsTeamsConversationID"] + + +class SendToMsTeamsConversationID(TypedDict, total=False): + conversation_id: Required[str] + + service_url: Required[str] + + tenant_id: Required[str] diff --git a/src/courier/types/shared_params/send_to_ms_teams_email.py b/src/courier/types/shared_params/send_to_ms_teams_email.py new file mode 100644 index 0000000..6bc5cb4 --- /dev/null +++ b/src/courier/types/shared_params/send_to_ms_teams_email.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["SendToMsTeamsEmail"] + + +class SendToMsTeamsEmail(TypedDict, total=False): + email: Required[str] + + service_url: Required[str] + + tenant_id: Required[str] diff --git a/src/courier/types/shared_params/send_to_ms_teams_user_id.py b/src/courier/types/shared_params/send_to_ms_teams_user_id.py new file mode 100644 index 0000000..43e374d --- /dev/null +++ b/src/courier/types/shared_params/send_to_ms_teams_user_id.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["SendToMsTeamsUserID"] + + +class SendToMsTeamsUserID(TypedDict, total=False): + service_url: Required[str] + + tenant_id: Required[str] + + user_id: Required[str] diff --git a/src/courier/types/shared_params/send_to_slack_channel.py b/src/courier/types/shared_params/send_to_slack_channel.py new file mode 100644 index 0000000..783058f --- /dev/null +++ b/src/courier/types/shared_params/send_to_slack_channel.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["SendToSlackChannel"] + + +class SendToSlackChannel(TypedDict, total=False): + access_token: Required[str] + + channel: Required[str] diff --git a/src/courier/types/shared_params/send_to_slack_email.py b/src/courier/types/shared_params/send_to_slack_email.py new file mode 100644 index 0000000..626ab3d --- /dev/null +++ b/src/courier/types/shared_params/send_to_slack_email.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["SendToSlackEmail"] + + +class SendToSlackEmail(TypedDict, total=False): + access_token: Required[str] + + email: Required[str] diff --git a/src/courier/types/shared_params/send_to_slack_user_id.py b/src/courier/types/shared_params/send_to_slack_user_id.py new file mode 100644 index 0000000..81af0b3 --- /dev/null +++ b/src/courier/types/shared_params/send_to_slack_user_id.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["SendToSlackUserID"] + + +class SendToSlackUserID(TypedDict, total=False): + access_token: Required[str] + + user_id: Required[str] diff --git a/src/courier/types/shared_params/slack.py b/src/courier/types/shared_params/slack.py new file mode 100644 index 0000000..a34e5c5 --- /dev/null +++ b/src/courier/types/shared_params/slack.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import TypeAlias + +from .send_to_slack_email import SendToSlackEmail +from .send_to_slack_channel import SendToSlackChannel +from .send_to_slack_user_id import SendToSlackUserID + +__all__ = ["Slack"] + +Slack: TypeAlias = Union[SendToSlackChannel, SendToSlackEmail, SendToSlackUserID] diff --git a/src/courier/types/shared_params/slack_recipient.py b/src/courier/types/shared_params/slack_recipient.py new file mode 100644 index 0000000..607c7b0 --- /dev/null +++ b/src/courier/types/shared_params/slack_recipient.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +from .slack import Slack + +__all__ = ["SlackRecipient"] + + +class SlackRecipient(TypedDict, total=False): + """Send via Slack (channel, email, or user_id)""" + + slack: Required[Slack] diff --git a/src/courier/types/shared_params/webhook_auth_mode.py b/src/courier/types/shared_params/webhook_auth_mode.py new file mode 100644 index 0000000..c813e2b --- /dev/null +++ b/src/courier/types/shared_params/webhook_auth_mode.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypeAlias + +__all__ = ["WebhookAuthMode"] + +WebhookAuthMode: TypeAlias = Literal["none", "basic", "bearer"] diff --git a/src/courier/types/shared_params/webhook_authentication.py b/src/courier/types/shared_params/webhook_authentication.py new file mode 100644 index 0000000..850471a --- /dev/null +++ b/src/courier/types/shared_params/webhook_authentication.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Required, TypedDict + +from ..shared.webhook_auth_mode import WebhookAuthMode + +__all__ = ["WebhookAuthentication"] + + +class WebhookAuthentication(TypedDict, total=False): + mode: Required[WebhookAuthMode] + """The authentication mode to use. Defaults to 'none' if not specified.""" + + token: Optional[str] + """Token for bearer authentication.""" + + password: Optional[str] + """Password for basic authentication.""" + + username: Optional[str] + """Username for basic authentication.""" diff --git a/src/courier/types/shared_params/webhook_method.py b/src/courier/types/shared_params/webhook_method.py new file mode 100644 index 0000000..08d334d --- /dev/null +++ b/src/courier/types/shared_params/webhook_method.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypeAlias + +__all__ = ["WebhookMethod"] + +WebhookMethod: TypeAlias = Literal["POST", "PUT"] diff --git a/src/courier/types/shared_params/webhook_profile.py b/src/courier/types/shared_params/webhook_profile.py new file mode 100644 index 0000000..5880401 --- /dev/null +++ b/src/courier/types/shared_params/webhook_profile.py @@ -0,0 +1,35 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Optional +from typing_extensions import Required, TypedDict + +from ..shared.webhook_method import WebhookMethod +from .webhook_authentication import WebhookAuthentication +from ..shared.webhook_profile_type import WebhookProfileType + +__all__ = ["WebhookProfile"] + + +class WebhookProfile(TypedDict, total=False): + url: Required[str] + """The URL to send the webhook request to.""" + + authentication: Optional[WebhookAuthentication] + """Authentication configuration for the webhook request.""" + + headers: Optional[Dict[str, str]] + """Custom headers to include in the webhook request.""" + + method: Optional[WebhookMethod] + """The HTTP method to use for the webhook request. + + Defaults to POST if not specified. + """ + + profile: Optional[WebhookProfileType] + """Specifies what profile information is included in the request payload. + + Defaults to 'limited' if not specified. + """ diff --git a/src/courier/types/shared_params/webhook_profile_type.py b/src/courier/types/shared_params/webhook_profile_type.py new file mode 100644 index 0000000..4501442 --- /dev/null +++ b/src/courier/types/shared_params/webhook_profile_type.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypeAlias + +__all__ = ["WebhookProfileType"] + +WebhookProfileType: TypeAlias = Literal["limited", "expanded"] diff --git a/src/courier/types/shared_params/webhook_recipient.py b/src/courier/types/shared_params/webhook_recipient.py new file mode 100644 index 0000000..60c3d1f --- /dev/null +++ b/src/courier/types/shared_params/webhook_recipient.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +from .webhook_profile import WebhookProfile + +__all__ = ["WebhookRecipient"] + + +class WebhookRecipient(TypedDict, total=False): + """Send via webhook""" + + webhook: Required[WebhookProfile] diff --git a/src/courier/types/single_filter_config.py b/src/courier/types/single_filter_config.py new file mode 100644 index 0000000..00b6724 --- /dev/null +++ b/src/courier/types/single_filter_config.py @@ -0,0 +1,37 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["SingleFilterConfig"] + + +class SingleFilterConfig(BaseModel): + operator: Literal[ + "ENDS_WITH", + "EQ", + "EXISTS", + "GT", + "GTE", + "INCLUDES", + "IS_AFTER", + "IS_BEFORE", + "LT", + "LTE", + "NEQ", + "OMIT", + "STARTS_WITH", + "AND", + "OR", + ] + """The operator to use for filtering""" + + path: str + """ + The attribe name from profile whose value will be operated against the filter + value + """ + + value: str + """The value to use for filtering""" diff --git a/src/courier/types/single_filter_config_param.py b/src/courier/types/single_filter_config_param.py new file mode 100644 index 0000000..879c6ec --- /dev/null +++ b/src/courier/types/single_filter_config_param.py @@ -0,0 +1,39 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["SingleFilterConfigParam"] + + +class SingleFilterConfigParam(TypedDict, total=False): + operator: Required[ + Literal[ + "ENDS_WITH", + "EQ", + "EXISTS", + "GT", + "GTE", + "INCLUDES", + "IS_AFTER", + "IS_BEFORE", + "LT", + "LTE", + "NEQ", + "OMIT", + "STARTS_WITH", + "AND", + "OR", + ] + ] + """The operator to use for filtering""" + + path: Required[str] + """ + The attribe name from profile whose value will be operated against the filter + value + """ + + value: Required[str] + """The value to use for filtering""" diff --git a/tests/api_resources/test_send.py b/tests/api_resources/test_send.py index 852abe9..46a39c4 100644 --- a/tests/api_resources/test_send.py +++ b/tests/api_resources/test_send.py @@ -147,7 +147,7 @@ def test_method_message_with_all_params(self, client: Courier) -> None: "template_id": "templateId", }, "tenant_id": "tenant_id", - "user_id": "example_user", + "user_id": "user_id", }, }, ) @@ -315,7 +315,7 @@ async def test_method_message_with_all_params(self, async_client: AsyncCourier) "template_id": "templateId", }, "tenant_id": "tenant_id", - "user_id": "example_user", + "user_id": "user_id", }, }, )