diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1332969b..c7159c1a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1" + ".": "0.0.2" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 3f7f73d5..ff4a3e82 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 76 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc%2Fwhopsdk-493b08fc2ae996eaf1758fa74f56163b2e40d4e1abeaa9672b8d1a039df30d75.yml -openapi_spec_hash: 212470480a88cabb38a58b5b6867c733 -config_hash: d72e5036b7f668d3a99a5a96248c4052 +configured_endpoints: 81 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/frostedinc%2Fwhopsdk-e8bcfd8a19f54624e644a1bc061df234a2e12af010a6c595d5a698cdd0e20682.yml +openapi_spec_hash: b47bb36fbc4c9ebdf3cf6b06f33356ef +config_hash: 131e5271eed10cf11ebc421d5a0c5f8a diff --git a/CHANGELOG.md b/CHANGELOG.md index 56ea1ae3..c5c855ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 0.0.2 (2025-10-22) + +Full Changelog: [v0.0.1...v0.0.2](https://github.com/whopio/whopsdk-python/compare/v0.0.1...v0.0.2) + +### Features + +* **api:** api update ([2d9ebee](https://github.com/whopio/whopsdk-python/commit/2d9ebeebfa02aed3ec8b515d0e5b11de07062a38)) +* **api:** api update ([5663cf4](https://github.com/whopio/whopsdk-python/commit/5663cf45944bf6f9d236b7a77aac23ce7f17fb61)) +* **api:** api update ([d3d6d23](https://github.com/whopio/whopsdk-python/commit/d3d6d2364fbac6ec7e828471093c27e5bdba8527)) +* **api:** api update ([f05be6f](https://github.com/whopio/whopsdk-python/commit/f05be6fd65bbd8fca4400d2e38e727153a72de43)) +* **api:** api update ([cb2935f](https://github.com/whopio/whopsdk-python/commit/cb2935feaef3aa0fe324bf2bb2bb193c96b12275)) +* **api:** api update ([d66c088](https://github.com/whopio/whopsdk-python/commit/d66c08873a123a5b65a5fa6f17e66ec6668e37a3)) +* **api:** manual updates ([e0bea9f](https://github.com/whopio/whopsdk-python/commit/e0bea9ff169b03e85ba7111ccd7cbe1f4a1eb4cf)) + + +### Chores + +* bump `httpx-aiohttp` version to 0.1.9 ([a946c15](https://github.com/whopio/whopsdk-python/commit/a946c15a8d418258f8d259714e725922e44c9389)) + ## 0.0.1 (2025-10-16) Full Changelog: [v0.0.1...v0.0.1](https://github.com/whopio/whopsdk-python/compare/v0.0.1...v0.0.1) diff --git a/api.md b/api.md index 11565652..4195aa21 100644 --- a/api.md +++ b/api.md @@ -2,6 +2,7 @@ ```python from whop_sdk.types import ( + AccessLevel, AccessPassType, App, AppBuild, @@ -21,9 +22,11 @@ from whop_sdk.types import ( CustomCta, Direction, DmsPostTypes, + EmailNotificationPreferences, Entry, EntryStatus, Experience, + Forum, ForumPost, FriendlyReceiptStatus, GlobalAffiliateStatus, @@ -31,6 +34,8 @@ from whop_sdk.types import ( Invoice, InvoiceListItem, InvoiceStatus, + MemberMostRecentActions, + MemberStatuses, Membership, MembershipStatus, Message, @@ -53,7 +58,9 @@ from whop_sdk.types import ( Transfer, Visibility, VisibilityFilter, + WhoCanCommentTypes, WhoCanPost, + WhoCanPostTypes, WhoCanReact, ) ``` @@ -127,6 +134,16 @@ from whop_sdk.types import ( InvoicePaidWebhookEvent, InvoicePastDueWebhookEvent, InvoiceVoidedWebhookEvent, + MembershipActivatedWebhookEvent, + MembershipDeactivatedWebhookEvent, + EntryCreatedWebhookEvent, + EntryApprovedWebhookEvent, + EntryDeniedWebhookEvent, + EntryDeletedWebhookEvent, + CourseLessonInteractionCompletedWebhookEvent, + PaymentSucceededWebhookEvent, + PaymentFailedWebhookEvent, + PaymentPendingWebhookEvent, UnwrapWebhookEvent, ) ``` @@ -377,3 +394,30 @@ Methods: - client.reactions.create(\*\*params) -> Reaction - client.reactions.retrieve(id) -> Reaction - client.reactions.list(\*\*params) -> SyncCursorPage[ReactionListResponse] + +# Members + +Types: + +```python +from whop_sdk.types import MemberRetrieveResponse, MemberListResponse +``` + +Methods: + +- client.members.retrieve(id) -> MemberRetrieveResponse +- client.members.list(\*\*params) -> SyncCursorPage[MemberListResponse] + +# Forums + +Types: + +```python +from whop_sdk.types import ForumListResponse +``` + +Methods: + +- client.forums.retrieve(id) -> Forum +- client.forums.update(id, \*\*params) -> Forum +- client.forums.list(\*\*params) -> SyncCursorPage[ForumListResponse] diff --git a/pyproject.toml b/pyproject.toml index bc987eb1..1af33a1c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "whop-sdk" -version = "0.0.1" +version = "0.0.2" description = "The official Python library for the Whop API" dynamic = ["readme"] license = "Apache-2.0" @@ -39,7 +39,7 @@ Homepage = "https://github.com/whopio/whopsdk-python" Repository = "https://github.com/whopio/whopsdk-python" [project.optional-dependencies] -aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.8"] +aiohttp = ["aiohttp", "httpx_aiohttp>=0.1.9"] webhooks = ["standardwebhooks"] [tool.rye] diff --git a/requirements-dev.lock b/requirements-dev.lock index a64267f8..ffac584f 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -60,7 +60,7 @@ httpx==0.28.1 # via respx # via standardwebhooks # via whop-sdk -httpx-aiohttp==0.1.8 +httpx-aiohttp==0.1.9 # via whop-sdk idna==3.4 # via anyio diff --git a/requirements.lock b/requirements.lock index 62e1973c..2f47ddb5 100644 --- a/requirements.lock +++ b/requirements.lock @@ -47,7 +47,7 @@ httpx==0.28.1 # via httpx-aiohttp # via standardwebhooks # via whop-sdk -httpx-aiohttp==0.1.8 +httpx-aiohttp==0.1.9 # via whop-sdk idna==3.4 # via anyio diff --git a/src/whop_sdk/_client.py b/src/whop_sdk/_client.py index 68216b31..196ca7fb 100644 --- a/src/whop_sdk/_client.py +++ b/src/whop_sdk/_client.py @@ -25,7 +25,9 @@ apps, plans, users, + forums, entries, + members, invoices, messages, payments, @@ -81,6 +83,8 @@ class Whop(SyncAPIClient): support_channels: support_channels.SupportChannelsResource experiences: experiences.ExperiencesResource reactions: reactions.ReactionsResource + members: members.MembersResource + forums: forums.ForumsResource with_raw_response: WhopWithRawResponse with_streaming_response: WhopWithStreamedResponse @@ -180,6 +184,8 @@ def __init__( self.support_channels = support_channels.SupportChannelsResource(self) self.experiences = experiences.ExperiencesResource(self) self.reactions = reactions.ReactionsResource(self) + self.members = members.MembersResource(self) + self.forums = forums.ForumsResource(self) self.with_raw_response = WhopWithRawResponse(self) self.with_streaming_response = WhopWithStreamedResponse(self) @@ -317,6 +323,8 @@ class AsyncWhop(AsyncAPIClient): support_channels: support_channels.AsyncSupportChannelsResource experiences: experiences.AsyncExperiencesResource reactions: reactions.AsyncReactionsResource + members: members.AsyncMembersResource + forums: forums.AsyncForumsResource with_raw_response: AsyncWhopWithRawResponse with_streaming_response: AsyncWhopWithStreamedResponse @@ -416,6 +424,8 @@ def __init__( self.support_channels = support_channels.AsyncSupportChannelsResource(self) self.experiences = experiences.AsyncExperiencesResource(self) self.reactions = reactions.AsyncReactionsResource(self) + self.members = members.AsyncMembersResource(self) + self.forums = forums.AsyncForumsResource(self) self.with_raw_response = AsyncWhopWithRawResponse(self) self.with_streaming_response = AsyncWhopWithStreamedResponse(self) @@ -557,6 +567,8 @@ def __init__(self, client: Whop) -> None: self.support_channels = support_channels.SupportChannelsResourceWithRawResponse(client.support_channels) self.experiences = experiences.ExperiencesResourceWithRawResponse(client.experiences) self.reactions = reactions.ReactionsResourceWithRawResponse(client.reactions) + self.members = members.MembersResourceWithRawResponse(client.members) + self.forums = forums.ForumsResourceWithRawResponse(client.forums) class AsyncWhopWithRawResponse: @@ -589,6 +601,8 @@ def __init__(self, client: AsyncWhop) -> None: self.support_channels = support_channels.AsyncSupportChannelsResourceWithRawResponse(client.support_channels) self.experiences = experiences.AsyncExperiencesResourceWithRawResponse(client.experiences) self.reactions = reactions.AsyncReactionsResourceWithRawResponse(client.reactions) + self.members = members.AsyncMembersResourceWithRawResponse(client.members) + self.forums = forums.AsyncForumsResourceWithRawResponse(client.forums) class WhopWithStreamedResponse: @@ -621,6 +635,8 @@ def __init__(self, client: Whop) -> None: self.support_channels = support_channels.SupportChannelsResourceWithStreamingResponse(client.support_channels) self.experiences = experiences.ExperiencesResourceWithStreamingResponse(client.experiences) self.reactions = reactions.ReactionsResourceWithStreamingResponse(client.reactions) + self.members = members.MembersResourceWithStreamingResponse(client.members) + self.forums = forums.ForumsResourceWithStreamingResponse(client.forums) class AsyncWhopWithStreamedResponse: @@ -657,6 +673,8 @@ def __init__(self, client: AsyncWhop) -> None: ) self.experiences = experiences.AsyncExperiencesResourceWithStreamingResponse(client.experiences) self.reactions = reactions.AsyncReactionsResourceWithStreamingResponse(client.reactions) + self.members = members.AsyncMembersResourceWithStreamingResponse(client.members) + self.forums = forums.AsyncForumsResourceWithStreamingResponse(client.forums) Client = Whop diff --git a/src/whop_sdk/_version.py b/src/whop_sdk/_version.py index 35444f45..d3607fd9 100644 --- a/src/whop_sdk/_version.py +++ b/src/whop_sdk/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "whop_sdk" -__version__ = "0.0.1" # x-release-please-version +__version__ = "0.0.2" # x-release-please-version diff --git a/src/whop_sdk/resources/__init__.py b/src/whop_sdk/resources/__init__.py index 44113820..f3d55211 100644 --- a/src/whop_sdk/resources/__init__.py +++ b/src/whop_sdk/resources/__init__.py @@ -24,6 +24,14 @@ UsersResourceWithStreamingResponse, AsyncUsersResourceWithStreamingResponse, ) +from .forums import ( + ForumsResource, + AsyncForumsResource, + ForumsResourceWithRawResponse, + AsyncForumsResourceWithRawResponse, + ForumsResourceWithStreamingResponse, + AsyncForumsResourceWithStreamingResponse, +) from .entries import ( EntriesResource, AsyncEntriesResource, @@ -32,6 +40,14 @@ EntriesResourceWithStreamingResponse, AsyncEntriesResourceWithStreamingResponse, ) +from .members import ( + MembersResource, + AsyncMembersResource, + MembersResourceWithRawResponse, + AsyncMembersResourceWithRawResponse, + MembersResourceWithStreamingResponse, + AsyncMembersResourceWithStreamingResponse, +) from .invoices import ( InvoicesResource, AsyncInvoicesResource, @@ -313,4 +329,16 @@ "AsyncReactionsResourceWithRawResponse", "ReactionsResourceWithStreamingResponse", "AsyncReactionsResourceWithStreamingResponse", + "MembersResource", + "AsyncMembersResource", + "MembersResourceWithRawResponse", + "AsyncMembersResourceWithRawResponse", + "MembersResourceWithStreamingResponse", + "AsyncMembersResourceWithStreamingResponse", + "ForumsResource", + "AsyncForumsResource", + "ForumsResourceWithRawResponse", + "AsyncForumsResourceWithRawResponse", + "ForumsResourceWithStreamingResponse", + "AsyncForumsResourceWithStreamingResponse", ] diff --git a/src/whop_sdk/resources/checkout_configurations.py b/src/whop_sdk/resources/checkout_configurations.py index d2a63268..756aaa60 100644 --- a/src/whop_sdk/resources/checkout_configurations.py +++ b/src/whop_sdk/resources/checkout_configurations.py @@ -62,7 +62,7 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CheckoutConfiguration: """ - Creates a new checkout session + Creates a new checkout configuration Required permissions: @@ -70,15 +70,15 @@ def create( - `plan:create` Args: - affiliate_code: The affiliate code to use for the checkout session + affiliate_code: The affiliate code to use for the checkout configuration - metadata: The metadata to use for the checkout session + metadata: The metadata to use for the checkout configuration - plan: Pass this object to create a new plan for this checkout session + plan: Pass this object to create a new plan for this checkout configuration - plan_id: The ID of the plan to use for the checkout session + plan_id: The ID of the plan to use for the checkout configuration - redirect_url: The URL to redirect the user to after the checkout session is created + redirect_url: The URL to redirect the user to after the checkout configuration is created extra_headers: Send extra headers @@ -251,7 +251,7 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> CheckoutConfiguration: """ - Creates a new checkout session + Creates a new checkout configuration Required permissions: @@ -259,15 +259,15 @@ async def create( - `plan:create` Args: - affiliate_code: The affiliate code to use for the checkout session + affiliate_code: The affiliate code to use for the checkout configuration - metadata: The metadata to use for the checkout session + metadata: The metadata to use for the checkout configuration - plan: Pass this object to create a new plan for this checkout session + plan: Pass this object to create a new plan for this checkout configuration - plan_id: The ID of the plan to use for the checkout session + plan_id: The ID of the plan to use for the checkout configuration - redirect_url: The URL to redirect the user to after the checkout session is created + redirect_url: The URL to redirect the user to after the checkout configuration is created extra_headers: Send extra headers diff --git a/src/whop_sdk/resources/forums.py b/src/whop_sdk/resources/forums.py new file mode 100644 index 00000000..57c19dfa --- /dev/null +++ b/src/whop_sdk/resources/forums.py @@ -0,0 +1,446 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional + +import httpx + +from ..types import forum_list_params, forum_update_params +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from .._utils import maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..pagination import SyncCursorPage, AsyncCursorPage +from .._base_client import AsyncPaginator, make_request_options +from ..types.shared.forum import Forum +from ..types.forum_list_response import ForumListResponse +from ..types.shared.who_can_post_types import WhoCanPostTypes +from ..types.shared.who_can_comment_types import WhoCanCommentTypes +from ..types.shared.email_notification_preferences import EmailNotificationPreferences + +__all__ = ["ForumsResource", "AsyncForumsResource"] + + +class ForumsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> ForumsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/whopio/whopsdk-python#accessing-raw-response-data-eg-headers + """ + return ForumsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ForumsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/whopio/whopsdk-python#with_streaming_response + """ + return ForumsResourceWithStreamingResponse(self) + + def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Forum: + """ + Retrieves a forum + + Required permissions: + + - `forum:read` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get( + f"/forums/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Forum, + ) + + def update( + self, + id: str, + *, + email_notification_preference: Optional[EmailNotificationPreferences] | Omit = omit, + who_can_comment: Optional[WhoCanCommentTypes] | Omit = omit, + who_can_post: Optional[WhoCanPostTypes] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Forum: + """ + Updates a forum + + Required permissions: + + - `forum:moderate` + + Args: + email_notification_preference: Email notification preference option for a forum feed + + who_can_comment: Who can comment on a forum feed + + who_can_post: Who can post on a forum feed + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._patch( + f"/forums/{id}", + body=maybe_transform( + { + "email_notification_preference": email_notification_preference, + "who_can_comment": who_can_comment, + "who_can_post": who_can_post, + }, + forum_update_params.ForumUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Forum, + ) + + def list( + self, + *, + company_id: str, + after: Optional[str] | Omit = omit, + before: Optional[str] | Omit = omit, + first: Optional[int] | Omit = omit, + last: Optional[int] | Omit = omit, + product_id: Optional[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SyncCursorPage[ForumListResponse]: + """ + Lists forums inside a company + + Required permissions: + + - `forum:read` + + Args: + company_id: The ID of the company to list forums for + + after: Returns the elements in the list that come after the specified cursor. + + before: Returns the elements in the list that come before the specified cursor. + + first: Returns the first _n_ elements from the list. + + last: Returns the last _n_ elements from the list. + + product_id: If provided, only forums connected to this product are returned + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/forums", + page=SyncCursorPage[ForumListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "company_id": company_id, + "after": after, + "before": before, + "first": first, + "last": last, + "product_id": product_id, + }, + forum_list_params.ForumListParams, + ), + ), + model=ForumListResponse, + ) + + +class AsyncForumsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncForumsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/whopio/whopsdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncForumsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncForumsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/whopio/whopsdk-python#with_streaming_response + """ + return AsyncForumsResourceWithStreamingResponse(self) + + async def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Forum: + """ + Retrieves a forum + + Required permissions: + + - `forum:read` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._get( + f"/forums/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Forum, + ) + + async def update( + self, + id: str, + *, + email_notification_preference: Optional[EmailNotificationPreferences] | Omit = omit, + who_can_comment: Optional[WhoCanCommentTypes] | Omit = omit, + who_can_post: Optional[WhoCanPostTypes] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Forum: + """ + Updates a forum + + Required permissions: + + - `forum:moderate` + + Args: + email_notification_preference: Email notification preference option for a forum feed + + who_can_comment: Who can comment on a forum feed + + who_can_post: Who can post on a forum feed + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._patch( + f"/forums/{id}", + body=await async_maybe_transform( + { + "email_notification_preference": email_notification_preference, + "who_can_comment": who_can_comment, + "who_can_post": who_can_post, + }, + forum_update_params.ForumUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Forum, + ) + + def list( + self, + *, + company_id: str, + after: Optional[str] | Omit = omit, + before: Optional[str] | Omit = omit, + first: Optional[int] | Omit = omit, + last: Optional[int] | Omit = omit, + product_id: Optional[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncPaginator[ForumListResponse, AsyncCursorPage[ForumListResponse]]: + """ + Lists forums inside a company + + Required permissions: + + - `forum:read` + + Args: + company_id: The ID of the company to list forums for + + after: Returns the elements in the list that come after the specified cursor. + + before: Returns the elements in the list that come before the specified cursor. + + first: Returns the first _n_ elements from the list. + + last: Returns the last _n_ elements from the list. + + product_id: If provided, only forums connected to this product are returned + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/forums", + page=AsyncCursorPage[ForumListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "company_id": company_id, + "after": after, + "before": before, + "first": first, + "last": last, + "product_id": product_id, + }, + forum_list_params.ForumListParams, + ), + ), + model=ForumListResponse, + ) + + +class ForumsResourceWithRawResponse: + def __init__(self, forums: ForumsResource) -> None: + self._forums = forums + + self.retrieve = to_raw_response_wrapper( + forums.retrieve, + ) + self.update = to_raw_response_wrapper( + forums.update, + ) + self.list = to_raw_response_wrapper( + forums.list, + ) + + +class AsyncForumsResourceWithRawResponse: + def __init__(self, forums: AsyncForumsResource) -> None: + self._forums = forums + + self.retrieve = async_to_raw_response_wrapper( + forums.retrieve, + ) + self.update = async_to_raw_response_wrapper( + forums.update, + ) + self.list = async_to_raw_response_wrapper( + forums.list, + ) + + +class ForumsResourceWithStreamingResponse: + def __init__(self, forums: ForumsResource) -> None: + self._forums = forums + + self.retrieve = to_streamed_response_wrapper( + forums.retrieve, + ) + self.update = to_streamed_response_wrapper( + forums.update, + ) + self.list = to_streamed_response_wrapper( + forums.list, + ) + + +class AsyncForumsResourceWithStreamingResponse: + def __init__(self, forums: AsyncForumsResource) -> None: + self._forums = forums + + self.retrieve = async_to_streamed_response_wrapper( + forums.retrieve, + ) + self.update = async_to_streamed_response_wrapper( + forums.update, + ) + self.list = async_to_streamed_response_wrapper( + forums.list, + ) diff --git a/src/whop_sdk/resources/members.py b/src/whop_sdk/resources/members.py new file mode 100644 index 00000000..5cf6f0cf --- /dev/null +++ b/src/whop_sdk/resources/members.py @@ -0,0 +1,421 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union, Optional +from datetime import datetime +from typing_extensions import Literal + +import httpx + +from ..types import member_list_params +from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given +from .._utils import maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..pagination import SyncCursorPage, AsyncCursorPage +from .._base_client import AsyncPaginator, make_request_options +from ..types.shared.direction import Direction +from ..types.shared.access_level import AccessLevel +from ..types.member_list_response import MemberListResponse +from ..types.shared.member_statuses import MemberStatuses +from ..types.member_retrieve_response import MemberRetrieveResponse +from ..types.shared.member_most_recent_actions import MemberMostRecentActions + +__all__ = ["MembersResource", "AsyncMembersResource"] + + +class MembersResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> MembersResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/whopio/whopsdk-python#accessing-raw-response-data-eg-headers + """ + return MembersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> MembersResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/whopio/whopsdk-python#with_streaming_response + """ + return MembersResourceWithStreamingResponse(self) + + def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> MemberRetrieveResponse: + """ + Retrieves a member of a company by ID + + Required permissions: + + - `member:basic:read` + - `member:email:read` + - `member:phone:read` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get( + f"/members/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MemberRetrieveResponse, + ) + + def list( + self, + *, + company_id: str, + access_level: Optional[AccessLevel] | Omit = omit, + access_pass_ids: Optional[SequenceNotStr[str]] | Omit = omit, + after: Optional[str] | Omit = omit, + before: Optional[str] | Omit = omit, + created_after: Union[str, datetime, None] | Omit = omit, + created_before: Union[str, datetime, None] | Omit = omit, + direction: Optional[Direction] | Omit = omit, + first: Optional[int] | Omit = omit, + last: Optional[int] | Omit = omit, + most_recent_actions: Optional[List[MemberMostRecentActions]] | Omit = omit, + order: Optional[Literal["id", "usd_total_spent", "created_at", "joined_at", "most_recent_action"]] + | Omit = omit, + plan_ids: Optional[SequenceNotStr[str]] | Omit = omit, + promo_code_ids: Optional[SequenceNotStr[str]] | Omit = omit, + query: Optional[str] | Omit = omit, + statuses: Optional[List[MemberStatuses]] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SyncCursorPage[MemberListResponse]: + """ + List the members of a company + + Required permissions: + + - `member:basic:read` + - `member:email:read` + - `member:phone:read` + + Args: + company_id: The ID of the company to list members for + + access_level: The access level a given user (or company) has to an access pass or company. + + access_pass_ids: The access pass IDs to filter the members by + + after: Returns the elements in the list that come after the specified cursor. + + before: Returns the elements in the list that come before the specified cursor. + + created_after: The minimum creation date to filter by + + created_before: The maximum creation date to filter by + + direction: The direction of the sort. + + first: Returns the first _n_ elements from the list. + + last: Returns the last _n_ elements from the list. + + most_recent_actions: The most recent actions to filter the members by + + order: Which columns can be used to sort. + + plan_ids: The plan IDs to filter the members by + + promo_code_ids: The promo code IDs to filter the members by + + query: The name, username, or email to filter the members by. The email filter will + only apply if the current actor has the `member:email:read` permission. + + statuses: The statuses to filter the members by + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/members", + page=SyncCursorPage[MemberListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "company_id": company_id, + "access_level": access_level, + "access_pass_ids": access_pass_ids, + "after": after, + "before": before, + "created_after": created_after, + "created_before": created_before, + "direction": direction, + "first": first, + "last": last, + "most_recent_actions": most_recent_actions, + "order": order, + "plan_ids": plan_ids, + "promo_code_ids": promo_code_ids, + "query": query, + "statuses": statuses, + }, + member_list_params.MemberListParams, + ), + ), + model=MemberListResponse, + ) + + +class AsyncMembersResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncMembersResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/whopio/whopsdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncMembersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncMembersResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/whopio/whopsdk-python#with_streaming_response + """ + return AsyncMembersResourceWithStreamingResponse(self) + + async def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> MemberRetrieveResponse: + """ + Retrieves a member of a company by ID + + Required permissions: + + - `member:basic:read` + - `member:email:read` + - `member:phone:read` + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._get( + f"/members/{id}", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MemberRetrieveResponse, + ) + + def list( + self, + *, + company_id: str, + access_level: Optional[AccessLevel] | Omit = omit, + access_pass_ids: Optional[SequenceNotStr[str]] | Omit = omit, + after: Optional[str] | Omit = omit, + before: Optional[str] | Omit = omit, + created_after: Union[str, datetime, None] | Omit = omit, + created_before: Union[str, datetime, None] | Omit = omit, + direction: Optional[Direction] | Omit = omit, + first: Optional[int] | Omit = omit, + last: Optional[int] | Omit = omit, + most_recent_actions: Optional[List[MemberMostRecentActions]] | Omit = omit, + order: Optional[Literal["id", "usd_total_spent", "created_at", "joined_at", "most_recent_action"]] + | Omit = omit, + plan_ids: Optional[SequenceNotStr[str]] | Omit = omit, + promo_code_ids: Optional[SequenceNotStr[str]] | Omit = omit, + query: Optional[str] | Omit = omit, + statuses: Optional[List[MemberStatuses]] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncPaginator[MemberListResponse, AsyncCursorPage[MemberListResponse]]: + """ + List the members of a company + + Required permissions: + + - `member:basic:read` + - `member:email:read` + - `member:phone:read` + + Args: + company_id: The ID of the company to list members for + + access_level: The access level a given user (or company) has to an access pass or company. + + access_pass_ids: The access pass IDs to filter the members by + + after: Returns the elements in the list that come after the specified cursor. + + before: Returns the elements in the list that come before the specified cursor. + + created_after: The minimum creation date to filter by + + created_before: The maximum creation date to filter by + + direction: The direction of the sort. + + first: Returns the first _n_ elements from the list. + + last: Returns the last _n_ elements from the list. + + most_recent_actions: The most recent actions to filter the members by + + order: Which columns can be used to sort. + + plan_ids: The plan IDs to filter the members by + + promo_code_ids: The promo code IDs to filter the members by + + query: The name, username, or email to filter the members by. The email filter will + only apply if the current actor has the `member:email:read` permission. + + statuses: The statuses to filter the members by + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/members", + page=AsyncCursorPage[MemberListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "company_id": company_id, + "access_level": access_level, + "access_pass_ids": access_pass_ids, + "after": after, + "before": before, + "created_after": created_after, + "created_before": created_before, + "direction": direction, + "first": first, + "last": last, + "most_recent_actions": most_recent_actions, + "order": order, + "plan_ids": plan_ids, + "promo_code_ids": promo_code_ids, + "query": query, + "statuses": statuses, + }, + member_list_params.MemberListParams, + ), + ), + model=MemberListResponse, + ) + + +class MembersResourceWithRawResponse: + def __init__(self, members: MembersResource) -> None: + self._members = members + + self.retrieve = to_raw_response_wrapper( + members.retrieve, + ) + self.list = to_raw_response_wrapper( + members.list, + ) + + +class AsyncMembersResourceWithRawResponse: + def __init__(self, members: AsyncMembersResource) -> None: + self._members = members + + self.retrieve = async_to_raw_response_wrapper( + members.retrieve, + ) + self.list = async_to_raw_response_wrapper( + members.list, + ) + + +class MembersResourceWithStreamingResponse: + def __init__(self, members: MembersResource) -> None: + self._members = members + + self.retrieve = to_streamed_response_wrapper( + members.retrieve, + ) + self.list = to_streamed_response_wrapper( + members.list, + ) + + +class AsyncMembersResourceWithStreamingResponse: + def __init__(self, members: AsyncMembersResource) -> None: + self._members = members + + self.retrieve = async_to_streamed_response_wrapper( + members.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + members.list, + ) diff --git a/src/whop_sdk/resources/plans.py b/src/whop_sdk/resources/plans.py index d536a330..873be659 100644 --- a/src/whop_sdk/resources/plans.py +++ b/src/whop_sdk/resources/plans.py @@ -107,7 +107,9 @@ def create( image: An image for the plan. This will be visible on the product page to customers. - initial_price: An additional amount charged upon first purchase. + initial_price: An additional amount charged upon first purchase. Use only if a one time payment + OR you want to charge an additional amount on top of the renewal price. Provided + as a number in dollars. Eg: 10.43 for $10.43 internal_notes: A personal description or notes section for the business. @@ -118,7 +120,8 @@ def create( release_method: The methods of how a plan can be released. - renewal_price: The amount the customer is charged every billing period. + renewal_price: The amount the customer is charged every billing period. Use only if a recurring + payment. Provided as a number in dollars. Eg: 10.43 for $10.43 title: The title of the plan. This will be visible on the product page to customers. @@ -501,7 +504,9 @@ async def create( image: An image for the plan. This will be visible on the product page to customers. - initial_price: An additional amount charged upon first purchase. + initial_price: An additional amount charged upon first purchase. Use only if a one time payment + OR you want to charge an additional amount on top of the renewal price. Provided + as a number in dollars. Eg: 10.43 for $10.43 internal_notes: A personal description or notes section for the business. @@ -512,7 +517,8 @@ async def create( release_method: The methods of how a plan can be released. - renewal_price: The amount the customer is charged every billing period. + renewal_price: The amount the customer is charged every billing period. Use only if a recurring + payment. Provided as a number in dollars. Eg: 10.43 for $10.43 title: The title of the plan. This will be visible on the product page to customers. diff --git a/src/whop_sdk/types/__init__.py b/src/whop_sdk/types/__init__.py index f1d170f3..37c1e57a 100644 --- a/src/whop_sdk/types/__init__.py +++ b/src/whop_sdk/types/__init__.py @@ -6,6 +6,7 @@ App as App, Plan as Plan, Entry as Entry, + Forum as Forum, Company as Company, Invoice as Invoice, Message as Message, @@ -27,6 +28,7 @@ Membership as Membership, Visibility as Visibility, WhoCanPost as WhoCanPost, + AccessLevel as AccessLevel, AppStatuses as AppStatuses, AppViewType as AppViewType, ChatChannel as ChatChannel, @@ -39,22 +41,27 @@ ReceiptStatus as ReceiptStatus, ReleaseMethod as ReleaseMethod, AccessPassType as AccessPassType, + MemberStatuses as MemberStatuses, ShipmentStatus as ShipmentStatus, SupportChannel as SupportChannel, InvoiceListItem as InvoiceListItem, ProductListItem as ProductListItem, ShipmentCarrier as ShipmentCarrier, + WhoCanPostTypes as WhoCanPostTypes, AppBuildStatuses as AppBuildStatuses, CollectionMethod as CollectionMethod, MembershipStatus as MembershipStatus, VisibilityFilter as VisibilityFilter, AppBuildPlatforms as AppBuildPlatforms, ShipmentSubstatus as ShipmentSubstatus, + WhoCanCommentTypes as WhoCanCommentTypes, AuthorizedUserRoles as AuthorizedUserRoles, CheckoutConfiguration as CheckoutConfiguration, FriendlyReceiptStatus as FriendlyReceiptStatus, GlobalAffiliateStatus as GlobalAffiliateStatus, CourseLessonInteraction as CourseLessonInteraction, + MemberMostRecentActions as MemberMostRecentActions, + EmailNotificationPreferences as EmailNotificationPreferences, CourseLessonInteractionListItem as CourseLessonInteractionListItem, ) from .app_list_params import AppListParams as AppListParams @@ -63,14 +70,19 @@ from .app_list_response import AppListResponse as AppListResponse from .app_update_params import AppUpdateParams as AppUpdateParams from .entry_list_params import EntryListParams as EntryListParams +from .forum_list_params import ForumListParams as ForumListParams +from .member_list_params import MemberListParams as MemberListParams from .plan_create_params import PlanCreateParams as PlanCreateParams from .plan_list_response import PlanListResponse as PlanListResponse from .plan_update_params import PlanUpdateParams as PlanUpdateParams from .entry_list_response import EntryListResponse as EntryListResponse +from .forum_list_response import ForumListResponse as ForumListResponse +from .forum_update_params import ForumUpdateParams as ForumUpdateParams from .invoice_list_params import InvoiceListParams as InvoiceListParams from .message_list_params import MessageListParams as MessageListParams from .payment_list_params import PaymentListParams as PaymentListParams from .product_list_params import ProductListParams as ProductListParams +from .member_list_response import MemberListResponse as MemberListResponse from .plan_delete_response import PlanDeleteResponse as PlanDeleteResponse from .reaction_list_params import ReactionListParams as ReactionListParams from .shipment_list_params import ShipmentListParams as ShipmentListParams @@ -109,27 +121,40 @@ from .experience_update_params import ExperienceUpdateParams as ExperienceUpdateParams from .forum_post_create_params import ForumPostCreateParams as ForumPostCreateParams from .forum_post_list_response import ForumPostListResponse as ForumPostListResponse +from .member_retrieve_response import MemberRetrieveResponse as MemberRetrieveResponse from .membership_cancel_params import MembershipCancelParams as MembershipCancelParams from .membership_list_response import MembershipListResponse as MembershipListResponse from .membership_update_params import MembershipUpdateParams as MembershipUpdateParams from .chat_channel_list_response import ChatChannelListResponse as ChatChannelListResponse from .chat_channel_update_params import ChatChannelUpdateParams as ChatChannelUpdateParams +from .entry_denied_webhook_event import EntryDeniedWebhookEvent as EntryDeniedWebhookEvent from .experience_delete_response import ExperienceDeleteResponse as ExperienceDeleteResponse from .invoice_paid_webhook_event import InvoicePaidWebhookEvent as InvoicePaidWebhookEvent from .user_check_access_response import UserCheckAccessResponse as UserCheckAccessResponse from .authorized_user_list_params import AuthorizedUserListParams as AuthorizedUserListParams +from .entry_created_webhook_event import EntryCreatedWebhookEvent as EntryCreatedWebhookEvent +from .entry_deleted_webhook_event import EntryDeletedWebhookEvent as EntryDeletedWebhookEvent from .support_channel_list_params import SupportChannelListParams as SupportChannelListParams +from .entry_approved_webhook_event import EntryApprovedWebhookEvent as EntryApprovedWebhookEvent from .invoice_voided_webhook_event import InvoiceVoidedWebhookEvent as InvoiceVoidedWebhookEvent +from .payment_failed_webhook_event import PaymentFailedWebhookEvent as PaymentFailedWebhookEvent from .authorized_user_list_response import AuthorizedUserListResponse as AuthorizedUserListResponse from .invoice_created_webhook_event import InvoiceCreatedWebhookEvent as InvoiceCreatedWebhookEvent +from .payment_pending_webhook_event import PaymentPendingWebhookEvent as PaymentPendingWebhookEvent from .support_channel_create_params import SupportChannelCreateParams as SupportChannelCreateParams from .support_channel_list_response import SupportChannelListResponse as SupportChannelListResponse from .invoice_past_due_webhook_event import InvoicePastDueWebhookEvent as InvoicePastDueWebhookEvent +from .payment_succeeded_webhook_event import PaymentSucceededWebhookEvent as PaymentSucceededWebhookEvent from .ledger_account_retrieve_response import LedgerAccountRetrieveResponse as LedgerAccountRetrieveResponse from .authorized_user_retrieve_response import AuthorizedUserRetrieveResponse as AuthorizedUserRetrieveResponse from .checkout_configuration_list_params import CheckoutConfigurationListParams as CheckoutConfigurationListParams +from .membership_activated_webhook_event import MembershipActivatedWebhookEvent as MembershipActivatedWebhookEvent from .checkout_configuration_create_params import CheckoutConfigurationCreateParams as CheckoutConfigurationCreateParams from .checkout_configuration_list_response import CheckoutConfigurationListResponse as CheckoutConfigurationListResponse +from .membership_deactivated_webhook_event import MembershipDeactivatedWebhookEvent as MembershipDeactivatedWebhookEvent from .course_lesson_interaction_list_params import ( CourseLessonInteractionListParams as CourseLessonInteractionListParams, ) +from .course_lesson_interaction_completed_webhook_event import ( + CourseLessonInteractionCompletedWebhookEvent as CourseLessonInteractionCompletedWebhookEvent, +) diff --git a/src/whop_sdk/types/app_list_response.py b/src/whop_sdk/types/app_list_response.py index 09b1f1ff..cd049343 100644 --- a/src/whop_sdk/types/app_list_response.py +++ b/src/whop_sdk/types/app_list_response.py @@ -5,7 +5,7 @@ from .._models import BaseModel from .shared.app_statuses import AppStatuses -__all__ = ["AppListResponse", "Company", "Creator"] +__all__ = ["AppListResponse", "Company", "Creator", "Icon"] class Company(BaseModel): @@ -27,6 +27,14 @@ class Creator(BaseModel): """The username of the user from their Whop account.""" +class Icon(BaseModel): + url: Optional[str] = None + """This is the URL you use to render optimized attachments on the client. + + This should be used for apps. + """ + + class AppListResponse(BaseModel): id: str """The ID of the app""" @@ -71,6 +79,13 @@ class AppListResponse(BaseModel): /experiences/[experienceId] """ + icon: Optional[Icon] = None + """The icon for the app. + + This icon is shown on discovery, on the product page, on checkout, and as a + default icon for the experiences. + """ + name: str """The name of the app""" diff --git a/src/whop_sdk/types/checkout_configuration_create_params.py b/src/whop_sdk/types/checkout_configuration_create_params.py index d20a63e6..4d40fff3 100644 --- a/src/whop_sdk/types/checkout_configuration_create_params.py +++ b/src/whop_sdk/types/checkout_configuration_create_params.py @@ -16,19 +16,19 @@ class CheckoutConfigurationCreateParams(TypedDict, total=False): affiliate_code: Optional[str] - """The affiliate code to use for the checkout session""" + """The affiliate code to use for the checkout configuration""" metadata: Optional[Dict[str, object]] - """The metadata to use for the checkout session""" + """The metadata to use for the checkout configuration""" plan: Optional[Plan] - """Pass this object to create a new plan for this checkout session""" + """Pass this object to create a new plan for this checkout configuration""" plan_id: Optional[str] - """The ID of the plan to use for the checkout session""" + """The ID of the plan to use for the checkout configuration""" redirect_url: Optional[str] - """The URL to redirect the user to after the checkout session is created""" + """The URL to redirect the user to after the checkout configuration is created""" class PlanCustomField(TypedDict, total=False): diff --git a/src/whop_sdk/types/checkout_configuration_list_response.py b/src/whop_sdk/types/checkout_configuration_list_response.py index b8582b94..07c1f4b2 100644 --- a/src/whop_sdk/types/checkout_configuration_list_response.py +++ b/src/whop_sdk/types/checkout_configuration_list_response.py @@ -45,22 +45,22 @@ class Plan(BaseModel): class CheckoutConfigurationListResponse(BaseModel): id: str - """The ID of the checkout session""" + """The ID of the checkout configuration""" - affiliate_code: str - """The affiliate code to use for the checkout session""" + affiliate_code: Optional[str] = None + """The affiliate code to use for the checkout configuration""" company_id: str - """The ID of the company to use for the checkout session""" + """The ID of the company to use for the checkout configuration""" metadata: Dict[str, object] - """The metadata to use for the checkout session""" + """The metadata to use for the checkout configuration""" plan: Plan - """The plan to use for the checkout session""" + """The plan to use for the checkout configuration""" purchase_url: str - """The URL to redirect the user to after the checkout session is created""" + """The URL to redirect the user to after the checkout configuration is created""" - redirect_url: str - """The URL to redirect the user to after the checkout session is created""" + redirect_url: Optional[str] = None + """The URL to redirect the user to after the checkout configuration is created""" diff --git a/src/whop_sdk/types/course_lesson_interaction_completed_webhook_event.py b/src/whop_sdk/types/course_lesson_interaction_completed_webhook_event.py new file mode 100644 index 00000000..afe55710 --- /dev/null +++ b/src/whop_sdk/types/course_lesson_interaction_completed_webhook_event.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .shared.course_lesson_interaction import CourseLessonInteraction + +__all__ = ["CourseLessonInteractionCompletedWebhookEvent"] + + +class CourseLessonInteractionCompletedWebhookEvent(BaseModel): + id: str + """A unique ID for every single webhook request""" + + api_version: Literal["v1"] + """The API version for this webhook""" + + data: CourseLessonInteraction + """A lesson interaction tracking user progress in courses""" + + timestamp: datetime + """The timestamp in ISO 8601 format that the webhook was sent at on the server""" + + type: Literal["course_lesson_interaction.completed"] + """The webhook event type""" diff --git a/src/whop_sdk/types/entry_approved_webhook_event.py b/src/whop_sdk/types/entry_approved_webhook_event.py new file mode 100644 index 00000000..29f31d4f --- /dev/null +++ b/src/whop_sdk/types/entry_approved_webhook_event.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .shared.entry import Entry + +__all__ = ["EntryApprovedWebhookEvent"] + + +class EntryApprovedWebhookEvent(BaseModel): + id: str + """A unique ID for every single webhook request""" + + api_version: Literal["v1"] + """The API version for this webhook""" + + data: Entry + """An object representing an entry in a waitlist.""" + + timestamp: datetime + """The timestamp in ISO 8601 format that the webhook was sent at on the server""" + + type: Literal["entry.approved"] + """The webhook event type""" diff --git a/src/whop_sdk/types/entry_created_webhook_event.py b/src/whop_sdk/types/entry_created_webhook_event.py new file mode 100644 index 00000000..e8c80656 --- /dev/null +++ b/src/whop_sdk/types/entry_created_webhook_event.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .shared.entry import Entry + +__all__ = ["EntryCreatedWebhookEvent"] + + +class EntryCreatedWebhookEvent(BaseModel): + id: str + """A unique ID for every single webhook request""" + + api_version: Literal["v1"] + """The API version for this webhook""" + + data: Entry + """An object representing an entry in a waitlist.""" + + timestamp: datetime + """The timestamp in ISO 8601 format that the webhook was sent at on the server""" + + type: Literal["entry.created"] + """The webhook event type""" diff --git a/src/whop_sdk/types/entry_deleted_webhook_event.py b/src/whop_sdk/types/entry_deleted_webhook_event.py new file mode 100644 index 00000000..abe3e7e1 --- /dev/null +++ b/src/whop_sdk/types/entry_deleted_webhook_event.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .shared.entry import Entry + +__all__ = ["EntryDeletedWebhookEvent"] + + +class EntryDeletedWebhookEvent(BaseModel): + id: str + """A unique ID for every single webhook request""" + + api_version: Literal["v1"] + """The API version for this webhook""" + + data: Entry + """An object representing an entry in a waitlist.""" + + timestamp: datetime + """The timestamp in ISO 8601 format that the webhook was sent at on the server""" + + type: Literal["entry.deleted"] + """The webhook event type""" diff --git a/src/whop_sdk/types/entry_denied_webhook_event.py b/src/whop_sdk/types/entry_denied_webhook_event.py new file mode 100644 index 00000000..94df91e7 --- /dev/null +++ b/src/whop_sdk/types/entry_denied_webhook_event.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .shared.entry import Entry + +__all__ = ["EntryDeniedWebhookEvent"] + + +class EntryDeniedWebhookEvent(BaseModel): + id: str + """A unique ID for every single webhook request""" + + api_version: Literal["v1"] + """The API version for this webhook""" + + data: Entry + """An object representing an entry in a waitlist.""" + + timestamp: datetime + """The timestamp in ISO 8601 format that the webhook was sent at on the server""" + + type: Literal["entry.denied"] + """The webhook event type""" diff --git a/src/whop_sdk/types/experience_list_response.py b/src/whop_sdk/types/experience_list_response.py index 13c5444e..1322df0d 100644 --- a/src/whop_sdk/types/experience_list_response.py +++ b/src/whop_sdk/types/experience_list_response.py @@ -5,13 +5,28 @@ from .._models import BaseModel -__all__ = ["ExperienceListResponse", "App", "Company"] +__all__ = ["ExperienceListResponse", "App", "AppIcon", "Company", "Image"] + + +class AppIcon(BaseModel): + url: Optional[str] = None + """This is the URL you use to render optimized attachments on the client. + + This should be used for apps. + """ class App(BaseModel): id: str """The ID of the app""" + icon: Optional[AppIcon] = None + """The icon for the app. + + This icon is shown on discovery, on the product page, on checkout, and as a + default icon for the experiences. + """ + name: str """The name of the app""" @@ -27,6 +42,14 @@ class Company(BaseModel): """The title of the company.""" +class Image(BaseModel): + url: Optional[str] = None + """This is the URL you use to render optimized attachments on the client. + + This should be used for apps. + """ + + class ExperienceListResponse(BaseModel): id: str """The unique ID representing this experience""" @@ -40,6 +63,9 @@ class ExperienceListResponse(BaseModel): created_at: datetime """The timestamp of when this experience was created.""" + image: Optional[Image] = None + """The logo for the experience.""" + name: str """The written name of the description.""" diff --git a/src/whop_sdk/types/forum_list_params.py b/src/whop_sdk/types/forum_list_params.py new file mode 100644 index 00000000..1e8e6d53 --- /dev/null +++ b/src/whop_sdk/types/forum_list_params.py @@ -0,0 +1,28 @@ +# 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 + +__all__ = ["ForumListParams"] + + +class ForumListParams(TypedDict, total=False): + company_id: Required[str] + """The ID of the company to list forums for""" + + after: Optional[str] + """Returns the elements in the list that come after the specified cursor.""" + + before: Optional[str] + """Returns the elements in the list that come before the specified cursor.""" + + first: Optional[int] + """Returns the first _n_ elements from the list.""" + + last: Optional[int] + """Returns the last _n_ elements from the list.""" + + product_id: Optional[str] + """If provided, only forums connected to this product are returned""" diff --git a/src/whop_sdk/types/forum_list_response.py b/src/whop_sdk/types/forum_list_response.py new file mode 100644 index 00000000..c2baf84a --- /dev/null +++ b/src/whop_sdk/types/forum_list_response.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .._models import BaseModel +from .shared.who_can_post_types import WhoCanPostTypes +from .shared.who_can_comment_types import WhoCanCommentTypes +from .shared.email_notification_preferences import EmailNotificationPreferences + +__all__ = ["ForumListResponse", "Experience"] + + +class Experience(BaseModel): + id: str + """The unique ID representing this experience""" + + name: str + """The written name of the description.""" + + +class ForumListResponse(BaseModel): + id: str + """The unique identifier for the entity""" + + email_notification_preference: EmailNotificationPreferences + """The email notification preference for this forum""" + + experience: Experience + """The experience for this forum""" + + who_can_comment: WhoCanCommentTypes + """Who can comment on this forum""" + + who_can_post: WhoCanPostTypes + """Who can post on this forum""" diff --git a/src/whop_sdk/types/forum_update_params.py b/src/whop_sdk/types/forum_update_params.py new file mode 100644 index 00000000..2e2a97bc --- /dev/null +++ b/src/whop_sdk/types/forum_update_params.py @@ -0,0 +1,23 @@ +# 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 + +from .shared.who_can_post_types import WhoCanPostTypes +from .shared.who_can_comment_types import WhoCanCommentTypes +from .shared.email_notification_preferences import EmailNotificationPreferences + +__all__ = ["ForumUpdateParams"] + + +class ForumUpdateParams(TypedDict, total=False): + email_notification_preference: Optional[EmailNotificationPreferences] + """Email notification preference option for a forum feed""" + + who_can_comment: Optional[WhoCanCommentTypes] + """Who can comment on a forum feed""" + + who_can_post: Optional[WhoCanPostTypes] + """Who can post on a forum feed""" diff --git a/src/whop_sdk/types/invoice_create_params.py b/src/whop_sdk/types/invoice_create_params.py index a5cef691..803f0ccb 100644 --- a/src/whop_sdk/types/invoice_create_params.py +++ b/src/whop_sdk/types/invoice_create_params.py @@ -108,7 +108,11 @@ class Plan(TypedDict, total=False): """The interval at which the plan charges (expiration plans).""" initial_price: Optional[float] - """An additional amount charged upon first purchase.""" + """An additional amount charged upon first purchase. + + Use only if a one time payment OR you want to charge an additional amount on top + of the renewal price. Provided as a number in dollars. Eg: 10.43 for $10.43 + """ internal_notes: Optional[str] """A personal description or notes section for the business.""" @@ -120,7 +124,11 @@ class Plan(TypedDict, total=False): """The methods of how a plan can be released.""" renewal_price: Optional[float] - """The amount the customer is charged every billing period.""" + """The amount the customer is charged every billing period. + + Use only if a recurring payment. Provided as a number in dollars. Eg: 10.43 for + $10.43 + """ trial_period_days: Optional[int] """The number of free trial days added before a renewal plan.""" diff --git a/src/whop_sdk/types/member_list_params.py b/src/whop_sdk/types/member_list_params.py new file mode 100644 index 00000000..f139719e --- /dev/null +++ b/src/whop_sdk/types/member_list_params.py @@ -0,0 +1,70 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union, Optional +from datetime import datetime +from typing_extensions import Literal, Required, Annotated, TypedDict + +from .._types import SequenceNotStr +from .._utils import PropertyInfo +from .shared.direction import Direction +from .shared.access_level import AccessLevel +from .shared.member_statuses import MemberStatuses +from .shared.member_most_recent_actions import MemberMostRecentActions + +__all__ = ["MemberListParams"] + + +class MemberListParams(TypedDict, total=False): + company_id: Required[str] + """The ID of the company to list members for""" + + access_level: Optional[AccessLevel] + """The access level a given user (or company) has to an access pass or company.""" + + access_pass_ids: Optional[SequenceNotStr[str]] + """The access pass IDs to filter the members by""" + + after: Optional[str] + """Returns the elements in the list that come after the specified cursor.""" + + before: Optional[str] + """Returns the elements in the list that come before the specified cursor.""" + + created_after: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """The minimum creation date to filter by""" + + created_before: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """The maximum creation date to filter by""" + + direction: Optional[Direction] + """The direction of the sort.""" + + first: Optional[int] + """Returns the first _n_ elements from the list.""" + + last: Optional[int] + """Returns the last _n_ elements from the list.""" + + most_recent_actions: Optional[List[MemberMostRecentActions]] + """The most recent actions to filter the members by""" + + order: Optional[Literal["id", "usd_total_spent", "created_at", "joined_at", "most_recent_action"]] + """Which columns can be used to sort.""" + + plan_ids: Optional[SequenceNotStr[str]] + """The plan IDs to filter the members by""" + + promo_code_ids: Optional[SequenceNotStr[str]] + """The promo code IDs to filter the members by""" + + query: Optional[str] + """The name, username, or email to filter the members by. + + The email filter will only apply if the current actor has the + `member:email:read` permission. + """ + + statuses: Optional[List[MemberStatuses]] + """The statuses to filter the members by""" diff --git a/src/whop_sdk/types/member_list_response.py b/src/whop_sdk/types/member_list_response.py new file mode 100644 index 00000000..f1fb1708 --- /dev/null +++ b/src/whop_sdk/types/member_list_response.py @@ -0,0 +1,65 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime + +from .._models import BaseModel +from .shared.access_level import AccessLevel +from .shared.member_statuses import MemberStatuses +from .shared.member_most_recent_actions import MemberMostRecentActions + +__all__ = ["MemberListResponse", "User"] + + +class User(BaseModel): + id: str + """The internal ID of the user account.""" + + email: Optional[str] = None + """The digital mailing address of the user.""" + + name: Optional[str] = None + """The user's full name.""" + + username: str + """The whop username.""" + + +class MemberListResponse(BaseModel): + id: str + """The ID of the member""" + + access_level: AccessLevel + """The access level of the product member. + + If its admin, the member is an authorized user of the access pass. If its + customer, the member has a valid membership to the access pass. If its + no_access, the member does not have access to the access pass. + """ + + created_at: datetime + """When the member was created""" + + joined_at: datetime + """When the member joined the company""" + + most_recent_action: Optional[MemberMostRecentActions] = None + """The different most recent actions a member can have.""" + + most_recent_action_at: Optional[datetime] = None + """The time for the most recent action, if applicable.""" + + phone: Optional[str] = None + """The phone number for the member, if available.""" + + status: MemberStatuses + """The status of the member""" + + updated_at: datetime + """The timestamp of when this member was last updated""" + + usd_total_spent: float + """How much money this customer has spent on the company's products and plans""" + + user: Optional[User] = None + """The user for this member, if any.""" diff --git a/src/whop_sdk/types/member_retrieve_response.py b/src/whop_sdk/types/member_retrieve_response.py new file mode 100644 index 00000000..c45b1b62 --- /dev/null +++ b/src/whop_sdk/types/member_retrieve_response.py @@ -0,0 +1,79 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime + +from .._models import BaseModel +from .shared.access_level import AccessLevel +from .shared.member_statuses import MemberStatuses +from .shared.member_most_recent_actions import MemberMostRecentActions + +__all__ = ["MemberRetrieveResponse", "Company", "User"] + + +class Company(BaseModel): + id: str + """The ID of the company""" + + route: str + """The slug/route of the company on the Whop site.""" + + title: str + """The written name of the company.""" + + +class User(BaseModel): + id: str + """The internal ID of the user account.""" + + email: Optional[str] = None + """The digital mailing address of the user.""" + + name: Optional[str] = None + """The user's full name.""" + + username: str + """The whop username.""" + + +class MemberRetrieveResponse(BaseModel): + id: str + """The ID of the member""" + + access_level: AccessLevel + """The access level of the product member. + + If its admin, the member is an authorized user of the access pass. If its + customer, the member has a valid membership to the access pass. If its + no_access, the member does not have access to the access pass. + """ + + company: Company + """The company for the member.""" + + created_at: datetime + """When the member was created""" + + joined_at: datetime + """When the member joined the company""" + + most_recent_action: Optional[MemberMostRecentActions] = None + """The different most recent actions a member can have.""" + + most_recent_action_at: Optional[datetime] = None + """The time for the most recent action, if applicable.""" + + phone: Optional[str] = None + """The phone number for the member, if available.""" + + status: MemberStatuses + """The status of the member""" + + updated_at: datetime + """The timestamp of when this member was last updated""" + + usd_total_spent: float + """How much money this customer has spent on the company's products and plans""" + + user: Optional[User] = None + """The user for this member, if any.""" diff --git a/src/whop_sdk/types/membership_activated_webhook_event.py b/src/whop_sdk/types/membership_activated_webhook_event.py new file mode 100644 index 00000000..0c636159 --- /dev/null +++ b/src/whop_sdk/types/membership_activated_webhook_event.py @@ -0,0 +1,29 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .shared.membership import Membership + +__all__ = ["MembershipActivatedWebhookEvent"] + + +class MembershipActivatedWebhookEvent(BaseModel): + id: str + """A unique ID for every single webhook request""" + + api_version: Literal["v1"] + """The API version for this webhook""" + + data: Membership + """ + A membership represents a purchase between a User and a Company for a specific + Product. + """ + + timestamp: datetime + """The timestamp in ISO 8601 format that the webhook was sent at on the server""" + + type: Literal["membership.activated"] + """The webhook event type""" diff --git a/src/whop_sdk/types/membership_deactivated_webhook_event.py b/src/whop_sdk/types/membership_deactivated_webhook_event.py new file mode 100644 index 00000000..34e28d7c --- /dev/null +++ b/src/whop_sdk/types/membership_deactivated_webhook_event.py @@ -0,0 +1,29 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .shared.membership import Membership + +__all__ = ["MembershipDeactivatedWebhookEvent"] + + +class MembershipDeactivatedWebhookEvent(BaseModel): + id: str + """A unique ID for every single webhook request""" + + api_version: Literal["v1"] + """The API version for this webhook""" + + data: Membership + """ + A membership represents a purchase between a User and a Company for a specific + Product. + """ + + timestamp: datetime + """The timestamp in ISO 8601 format that the webhook was sent at on the server""" + + type: Literal["membership.deactivated"] + """The webhook event type""" diff --git a/src/whop_sdk/types/payment_failed_webhook_event.py b/src/whop_sdk/types/payment_failed_webhook_event.py new file mode 100644 index 00000000..98a848c1 --- /dev/null +++ b/src/whop_sdk/types/payment_failed_webhook_event.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .shared.payment import Payment + +__all__ = ["PaymentFailedWebhookEvent"] + + +class PaymentFailedWebhookEvent(BaseModel): + id: str + """A unique ID for every single webhook request""" + + api_version: Literal["v1"] + """The API version for this webhook""" + + data: Payment + """An object representing a receipt for a membership.""" + + timestamp: datetime + """The timestamp in ISO 8601 format that the webhook was sent at on the server""" + + type: Literal["payment.failed"] + """The webhook event type""" diff --git a/src/whop_sdk/types/payment_pending_webhook_event.py b/src/whop_sdk/types/payment_pending_webhook_event.py new file mode 100644 index 00000000..e5919ff2 --- /dev/null +++ b/src/whop_sdk/types/payment_pending_webhook_event.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .shared.payment import Payment + +__all__ = ["PaymentPendingWebhookEvent"] + + +class PaymentPendingWebhookEvent(BaseModel): + id: str + """A unique ID for every single webhook request""" + + api_version: Literal["v1"] + """The API version for this webhook""" + + data: Payment + """An object representing a receipt for a membership.""" + + timestamp: datetime + """The timestamp in ISO 8601 format that the webhook was sent at on the server""" + + type: Literal["payment.pending"] + """The webhook event type""" diff --git a/src/whop_sdk/types/payment_succeeded_webhook_event.py b/src/whop_sdk/types/payment_succeeded_webhook_event.py new file mode 100644 index 00000000..f4427c17 --- /dev/null +++ b/src/whop_sdk/types/payment_succeeded_webhook_event.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .shared.payment import Payment + +__all__ = ["PaymentSucceededWebhookEvent"] + + +class PaymentSucceededWebhookEvent(BaseModel): + id: str + """A unique ID for every single webhook request""" + + api_version: Literal["v1"] + """The API version for this webhook""" + + data: Payment + """An object representing a receipt for a membership.""" + + timestamp: datetime + """The timestamp in ISO 8601 format that the webhook was sent at on the server""" + + type: Literal["payment.succeeded"] + """The webhook event type""" diff --git a/src/whop_sdk/types/plan_create_params.py b/src/whop_sdk/types/plan_create_params.py index 3de2cab1..04aee462 100644 --- a/src/whop_sdk/types/plan_create_params.py +++ b/src/whop_sdk/types/plan_create_params.py @@ -40,7 +40,11 @@ class PlanCreateParams(TypedDict, total=False): """An image for the plan. This will be visible on the product page to customers.""" initial_price: Optional[float] - """An additional amount charged upon first purchase.""" + """An additional amount charged upon first purchase. + + Use only if a one time payment OR you want to charge an additional amount on top + of the renewal price. Provided as a number in dollars. Eg: 10.43 for $10.43 + """ internal_notes: Optional[str] """A personal description or notes section for the business.""" @@ -58,7 +62,11 @@ class PlanCreateParams(TypedDict, total=False): """The methods of how a plan can be released.""" renewal_price: Optional[float] - """The amount the customer is charged every billing period.""" + """The amount the customer is charged every billing period. + + Use only if a recurring payment. Provided as a number in dollars. Eg: 10.43 for + $10.43 + """ title: Optional[str] """The title of the plan. This will be visible on the product page to customers.""" diff --git a/src/whop_sdk/types/shared/__init__.py b/src/whop_sdk/types/shared/__init__.py index 8738118d..e35962fe 100644 --- a/src/whop_sdk/types/shared/__init__.py +++ b/src/whop_sdk/types/shared/__init__.py @@ -3,6 +3,7 @@ from .app import App as App from .plan import Plan as Plan from .entry import Entry as Entry +from .forum import Forum as Forum from .company import Company as Company from .invoice import Invoice as Invoice from .message import Message as Message @@ -23,6 +24,7 @@ from .membership import Membership as Membership from .promo_type import PromoType as PromoType from .visibility import Visibility as Visibility +from .access_level import AccessLevel as AccessLevel from .app_statuses import AppStatuses as AppStatuses from .chat_channel import ChatChannel as ChatChannel from .entry_status import EntryStatus as EntryStatus @@ -35,6 +37,7 @@ from .invoice_status import InvoiceStatus as InvoiceStatus from .receipt_status import ReceiptStatus as ReceiptStatus from .release_method import ReleaseMethod as ReleaseMethod +from .member_statuses import MemberStatuses as MemberStatuses from .shipment_status import ShipmentStatus as ShipmentStatus from .support_channel import SupportChannel as SupportChannel from .access_pass_type import AccessPassType as AccessPassType @@ -46,10 +49,14 @@ from .visibility_filter import VisibilityFilter as VisibilityFilter from .app_build_statuses import AppBuildStatuses as AppBuildStatuses from .shipment_substatus import ShipmentSubstatus as ShipmentSubstatus +from .who_can_post_types import WhoCanPostTypes as WhoCanPostTypes from .app_build_platforms import AppBuildPlatforms as AppBuildPlatforms from .authorized_user_roles import AuthorizedUserRoles as AuthorizedUserRoles +from .who_can_comment_types import WhoCanCommentTypes as WhoCanCommentTypes from .checkout_configuration import CheckoutConfiguration as CheckoutConfiguration from .friendly_receipt_status import FriendlyReceiptStatus as FriendlyReceiptStatus from .global_affiliate_status import GlobalAffiliateStatus as GlobalAffiliateStatus from .course_lesson_interaction import CourseLessonInteraction as CourseLessonInteraction +from .member_most_recent_actions import MemberMostRecentActions as MemberMostRecentActions +from .email_notification_preferences import EmailNotificationPreferences as EmailNotificationPreferences from .course_lesson_interaction_list_item import CourseLessonInteractionListItem as CourseLessonInteractionListItem diff --git a/src/whop_sdk/types/shared/access_level.py b/src/whop_sdk/types/shared/access_level.py new file mode 100644 index 00000000..f5dd8ca1 --- /dev/null +++ b/src/whop_sdk/types/shared/access_level.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__ = ["AccessLevel"] + +AccessLevel: TypeAlias = Literal["no_access", "admin", "customer"] diff --git a/src/whop_sdk/types/shared/app.py b/src/whop_sdk/types/shared/app.py index 04fad1f0..c4725e98 100644 --- a/src/whop_sdk/types/shared/app.py +++ b/src/whop_sdk/types/shared/app.py @@ -6,7 +6,16 @@ from ..._models import BaseModel from .app_statuses import AppStatuses -__all__ = ["App", "APIKey", "Company", "Creator", "RequestedPermission", "RequestedPermissionPermissionAction", "Stats"] +__all__ = [ + "App", + "APIKey", + "Company", + "Creator", + "Icon", + "RequestedPermission", + "RequestedPermissionPermissionAction", + "Stats", +] class APIKey(BaseModel): @@ -39,6 +48,14 @@ class Creator(BaseModel): """The username of the user from their Whop account.""" +class Icon(BaseModel): + url: Optional[str] = None + """This is the URL you use to render optimized attachments on the client. + + This should be used for apps. + """ + + class RequestedPermissionPermissionAction(BaseModel): action: str """The identifier of the action.""" @@ -130,6 +147,13 @@ class App(BaseModel): /experiences/[experienceId] """ + icon: Optional[Icon] = None + """The icon for the app. + + This icon is shown on discovery, on the product page, on checkout, and as a + default icon for the experiences. + """ + name: str """The name of the app""" diff --git a/src/whop_sdk/types/shared/checkout_configuration.py b/src/whop_sdk/types/shared/checkout_configuration.py index a30b9e9b..0812fa47 100644 --- a/src/whop_sdk/types/shared/checkout_configuration.py +++ b/src/whop_sdk/types/shared/checkout_configuration.py @@ -45,22 +45,22 @@ class Plan(BaseModel): class CheckoutConfiguration(BaseModel): id: str - """The ID of the checkout session""" + """The ID of the checkout configuration""" - affiliate_code: str - """The affiliate code to use for the checkout session""" + affiliate_code: Optional[str] = None + """The affiliate code to use for the checkout configuration""" company_id: str - """The ID of the company to use for the checkout session""" + """The ID of the company to use for the checkout configuration""" metadata: Dict[str, object] - """The metadata to use for the checkout session""" + """The metadata to use for the checkout configuration""" plan: Plan - """The plan to use for the checkout session""" + """The plan to use for the checkout configuration""" purchase_url: str - """The URL to redirect the user to after the checkout session is created""" + """The URL to redirect the user to after the checkout configuration is created""" - redirect_url: str - """The URL to redirect the user to after the checkout session is created""" + redirect_url: Optional[str] = None + """The URL to redirect the user to after the checkout configuration is created""" diff --git a/src/whop_sdk/types/shared/company.py b/src/whop_sdk/types/shared/company.py index cafd1cef..620cffde 100644 --- a/src/whop_sdk/types/shared/company.py +++ b/src/whop_sdk/types/shared/company.py @@ -8,7 +8,15 @@ from .business_types import BusinessTypes from .industry_types import IndustryTypes -__all__ = ["Company", "OwnerUser", "SocialLink"] +__all__ = ["Company", "Logo", "OwnerUser", "SocialLink"] + + +class Logo(BaseModel): + url: Optional[str] = None + """This is the URL you use to render optimized attachments on the client. + + This should be used for apps. + """ class OwnerUser(BaseModel): @@ -43,9 +51,15 @@ class Company(BaseModel): created_at: datetime """When the company was created (signed up)""" + description: Optional[str] = None + """The creator pitch for the company.""" + industry_type: Optional[IndustryTypes] = None """The different industry types a company can be in.""" + logo: Optional[Logo] = None + """The company's logo.""" + member_count: int """The number of members in the company.""" diff --git a/src/whop_sdk/types/shared/course_lesson_interaction.py b/src/whop_sdk/types/shared/course_lesson_interaction.py index 223acc52..f8c617b7 100644 --- a/src/whop_sdk/types/shared/course_lesson_interaction.py +++ b/src/whop_sdk/types/shared/course_lesson_interaction.py @@ -5,7 +5,23 @@ from ..._models import BaseModel -__all__ = ["CourseLessonInteraction", "Lesson", "User"] +__all__ = ["CourseLessonInteraction", "Course", "CourseExperience", "Lesson", "User"] + + +class CourseExperience(BaseModel): + id: str + """The unique ID representing this experience""" + + +class Course(BaseModel): + id: str + """The ID of the course. Looks like cors_XXX""" + + experience: CourseExperience + """The experience that the course belongs to""" + + title: Optional[str] = None + """The title of the course""" class Lesson(BaseModel): @@ -34,6 +50,9 @@ class CourseLessonInteraction(BaseModel): completed: bool """Whether the lesson has been completed by the user""" + course: Course + """The course for this lesson interaction""" + created_at: datetime """When the interaction was created""" diff --git a/src/whop_sdk/types/shared/email_notification_preferences.py b/src/whop_sdk/types/shared/email_notification_preferences.py new file mode 100644 index 00000000..2ab81c77 --- /dev/null +++ b/src/whop_sdk/types/shared/email_notification_preferences.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__ = ["EmailNotificationPreferences"] + +EmailNotificationPreferences: TypeAlias = Literal["all_admin_posts", "only_weekly_summary", "none"] diff --git a/src/whop_sdk/types/shared/experience.py b/src/whop_sdk/types/shared/experience.py index 4cc54c9b..7c39c5b2 100644 --- a/src/whop_sdk/types/shared/experience.py +++ b/src/whop_sdk/types/shared/experience.py @@ -5,13 +5,28 @@ from ..._models import BaseModel -__all__ = ["Experience", "App", "Company", "Product"] +__all__ = ["Experience", "App", "AppIcon", "Company", "Image", "Product"] + + +class AppIcon(BaseModel): + url: Optional[str] = None + """This is the URL you use to render optimized attachments on the client. + + This should be used for apps. + """ class App(BaseModel): id: str """The ID of the app""" + icon: Optional[AppIcon] = None + """The icon for the app. + + This icon is shown on discovery, on the product page, on checkout, and as a + default icon for the experiences. + """ + name: str """The name of the app""" @@ -27,6 +42,14 @@ class Company(BaseModel): """The title of the company.""" +class Image(BaseModel): + url: Optional[str] = None + """This is the URL you use to render optimized attachments on the client. + + This should be used for apps. + """ + + class Product(BaseModel): id: str """The internal ID of the public product.""" @@ -51,6 +74,9 @@ class Experience(BaseModel): created_at: datetime """The timestamp of when this experience was created.""" + image: Optional[Image] = None + """The logo for the experience.""" + name: str """The written name of the description.""" diff --git a/src/whop_sdk/types/shared/forum.py b/src/whop_sdk/types/shared/forum.py new file mode 100644 index 00000000..0f9202f4 --- /dev/null +++ b/src/whop_sdk/types/shared/forum.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ..._models import BaseModel +from .who_can_post_types import WhoCanPostTypes +from .who_can_comment_types import WhoCanCommentTypes +from .email_notification_preferences import EmailNotificationPreferences + +__all__ = ["Forum", "Experience"] + + +class Experience(BaseModel): + id: str + """The unique ID representing this experience""" + + name: str + """The written name of the description.""" + + +class Forum(BaseModel): + id: str + """The unique identifier for the entity""" + + email_notification_preference: EmailNotificationPreferences + """The email notification preference for this forum""" + + experience: Experience + """The experience for this forum""" + + who_can_comment: WhoCanCommentTypes + """Who can comment on this forum""" + + who_can_post: WhoCanPostTypes + """Who can post on this forum""" diff --git a/src/whop_sdk/types/shared/member_most_recent_actions.py b/src/whop_sdk/types/shared/member_most_recent_actions.py new file mode 100644 index 00000000..4c102e4f --- /dev/null +++ b/src/whop_sdk/types/shared/member_most_recent_actions.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal, TypeAlias + +__all__ = ["MemberMostRecentActions"] + +MemberMostRecentActions: TypeAlias = Literal[ + "canceling", + "churned", + "finished_split_pay", + "paused", + "paid_subscriber", + "paid_once", + "expiring", + "joined", + "drafted", + "left", + "trialing", + "pending_entry", + "renewing", + "past_due", +] diff --git a/src/whop_sdk/types/shared/member_statuses.py b/src/whop_sdk/types/shared/member_statuses.py new file mode 100644 index 00000000..a3616845 --- /dev/null +++ b/src/whop_sdk/types/shared/member_statuses.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__ = ["MemberStatuses"] + +MemberStatuses: TypeAlias = Literal["drafted", "joined", "left"] diff --git a/src/whop_sdk/types/shared/who_can_comment_types.py b/src/whop_sdk/types/shared/who_can_comment_types.py new file mode 100644 index 00000000..6512c5f5 --- /dev/null +++ b/src/whop_sdk/types/shared/who_can_comment_types.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__ = ["WhoCanCommentTypes"] + +WhoCanCommentTypes: TypeAlias = Literal["everyone", "admins"] diff --git a/src/whop_sdk/types/shared/who_can_post_types.py b/src/whop_sdk/types/shared/who_can_post_types.py new file mode 100644 index 00000000..ac315cb6 --- /dev/null +++ b/src/whop_sdk/types/shared/who_can_post_types.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__ = ["WhoCanPostTypes"] + +WhoCanPostTypes: TypeAlias = Literal["everyone", "admins"] diff --git a/src/whop_sdk/types/shared_params/__init__.py b/src/whop_sdk/types/shared_params/__init__.py index aeba1edc..c6e79558 100644 --- a/src/whop_sdk/types/shared_params/__init__.py +++ b/src/whop_sdk/types/shared_params/__init__.py @@ -6,6 +6,7 @@ from .plan_type import PlanType as PlanType from .custom_cta import CustomCta as CustomCta from .visibility import Visibility as Visibility +from .access_level import AccessLevel as AccessLevel from .app_statuses import AppStatuses as AppStatuses from .entry_status import EntryStatus as EntryStatus from .who_can_post import WhoCanPost as WhoCanPost @@ -16,12 +17,17 @@ from .invoice_status import InvoiceStatus as InvoiceStatus from .receipt_status import ReceiptStatus as ReceiptStatus from .release_method import ReleaseMethod as ReleaseMethod +from .member_statuses import MemberStatuses as MemberStatuses from .access_pass_type import AccessPassType as AccessPassType from .collection_method import CollectionMethod as CollectionMethod from .membership_status import MembershipStatus as MembershipStatus from .visibility_filter import VisibilityFilter as VisibilityFilter from .app_build_statuses import AppBuildStatuses as AppBuildStatuses +from .who_can_post_types import WhoCanPostTypes as WhoCanPostTypes from .app_build_platforms import AppBuildPlatforms as AppBuildPlatforms from .authorized_user_roles import AuthorizedUserRoles as AuthorizedUserRoles +from .who_can_comment_types import WhoCanCommentTypes as WhoCanCommentTypes from .friendly_receipt_status import FriendlyReceiptStatus as FriendlyReceiptStatus from .global_affiliate_status import GlobalAffiliateStatus as GlobalAffiliateStatus +from .member_most_recent_actions import MemberMostRecentActions as MemberMostRecentActions +from .email_notification_preferences import EmailNotificationPreferences as EmailNotificationPreferences diff --git a/src/whop_sdk/types/shared_params/access_level.py b/src/whop_sdk/types/shared_params/access_level.py new file mode 100644 index 00000000..79610b07 --- /dev/null +++ b/src/whop_sdk/types/shared_params/access_level.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__ = ["AccessLevel"] + +AccessLevel: TypeAlias = Literal["no_access", "admin", "customer"] diff --git a/src/whop_sdk/types/shared_params/email_notification_preferences.py b/src/whop_sdk/types/shared_params/email_notification_preferences.py new file mode 100644 index 00000000..a745925b --- /dev/null +++ b/src/whop_sdk/types/shared_params/email_notification_preferences.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__ = ["EmailNotificationPreferences"] + +EmailNotificationPreferences: TypeAlias = Literal["all_admin_posts", "only_weekly_summary", "none"] diff --git a/src/whop_sdk/types/shared_params/member_most_recent_actions.py b/src/whop_sdk/types/shared_params/member_most_recent_actions.py new file mode 100644 index 00000000..5f666c8c --- /dev/null +++ b/src/whop_sdk/types/shared_params/member_most_recent_actions.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypeAlias + +__all__ = ["MemberMostRecentActions"] + +MemberMostRecentActions: TypeAlias = Literal[ + "canceling", + "churned", + "finished_split_pay", + "paused", + "paid_subscriber", + "paid_once", + "expiring", + "joined", + "drafted", + "left", + "trialing", + "pending_entry", + "renewing", + "past_due", +] diff --git a/src/whop_sdk/types/shared_params/member_statuses.py b/src/whop_sdk/types/shared_params/member_statuses.py new file mode 100644 index 00000000..cb6d01f9 --- /dev/null +++ b/src/whop_sdk/types/shared_params/member_statuses.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__ = ["MemberStatuses"] + +MemberStatuses: TypeAlias = Literal["drafted", "joined", "left"] diff --git a/src/whop_sdk/types/shared_params/who_can_comment_types.py b/src/whop_sdk/types/shared_params/who_can_comment_types.py new file mode 100644 index 00000000..c9cd36fe --- /dev/null +++ b/src/whop_sdk/types/shared_params/who_can_comment_types.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__ = ["WhoCanCommentTypes"] + +WhoCanCommentTypes: TypeAlias = Literal["everyone", "admins"] diff --git a/src/whop_sdk/types/shared_params/who_can_post_types.py b/src/whop_sdk/types/shared_params/who_can_post_types.py new file mode 100644 index 00000000..bba45e1a --- /dev/null +++ b/src/whop_sdk/types/shared_params/who_can_post_types.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__ = ["WhoCanPostTypes"] + +WhoCanPostTypes: TypeAlias = Literal["everyone", "admins"] diff --git a/src/whop_sdk/types/unwrap_webhook_event.py b/src/whop_sdk/types/unwrap_webhook_event.py index 19638b00..aa869c77 100644 --- a/src/whop_sdk/types/unwrap_webhook_event.py +++ b/src/whop_sdk/types/unwrap_webhook_event.py @@ -3,13 +3,36 @@ from typing import Union from typing_extensions import TypeAlias +from .entry_denied_webhook_event import EntryDeniedWebhookEvent from .invoice_paid_webhook_event import InvoicePaidWebhookEvent +from .entry_created_webhook_event import EntryCreatedWebhookEvent +from .entry_deleted_webhook_event import EntryDeletedWebhookEvent +from .entry_approved_webhook_event import EntryApprovedWebhookEvent from .invoice_voided_webhook_event import InvoiceVoidedWebhookEvent +from .payment_failed_webhook_event import PaymentFailedWebhookEvent from .invoice_created_webhook_event import InvoiceCreatedWebhookEvent +from .payment_pending_webhook_event import PaymentPendingWebhookEvent from .invoice_past_due_webhook_event import InvoicePastDueWebhookEvent +from .payment_succeeded_webhook_event import PaymentSucceededWebhookEvent +from .membership_activated_webhook_event import MembershipActivatedWebhookEvent +from .membership_deactivated_webhook_event import MembershipDeactivatedWebhookEvent +from .course_lesson_interaction_completed_webhook_event import CourseLessonInteractionCompletedWebhookEvent __all__ = ["UnwrapWebhookEvent"] UnwrapWebhookEvent: TypeAlias = Union[ - InvoiceCreatedWebhookEvent, InvoicePaidWebhookEvent, InvoicePastDueWebhookEvent, InvoiceVoidedWebhookEvent + InvoiceCreatedWebhookEvent, + InvoicePaidWebhookEvent, + InvoicePastDueWebhookEvent, + InvoiceVoidedWebhookEvent, + MembershipActivatedWebhookEvent, + MembershipDeactivatedWebhookEvent, + EntryCreatedWebhookEvent, + EntryApprovedWebhookEvent, + EntryDeniedWebhookEvent, + EntryDeletedWebhookEvent, + CourseLessonInteractionCompletedWebhookEvent, + PaymentSucceededWebhookEvent, + PaymentFailedWebhookEvent, + PaymentPendingWebhookEvent, ] diff --git a/src/whop_sdk/types/user_check_access_response.py b/src/whop_sdk/types/user_check_access_response.py index bf382cc0..2f56acf0 100644 --- a/src/whop_sdk/types/user_check_access_response.py +++ b/src/whop_sdk/types/user_check_access_response.py @@ -1,14 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing_extensions import Literal - from .._models import BaseModel +from .shared.access_level import AccessLevel __all__ = ["UserCheckAccessResponse"] class UserCheckAccessResponse(BaseModel): - access_level: Literal["no_access", "admin", "customer"] + access_level: AccessLevel """The permission level of the user""" has_access: bool diff --git a/src/whop_sdk/types/user_retrieve_response.py b/src/whop_sdk/types/user_retrieve_response.py index 26969eb7..24016e3d 100644 --- a/src/whop_sdk/types/user_retrieve_response.py +++ b/src/whop_sdk/types/user_retrieve_response.py @@ -5,7 +5,15 @@ from .._models import BaseModel -__all__ = ["UserRetrieveResponse"] +__all__ = ["UserRetrieveResponse", "ProfilePicture"] + + +class ProfilePicture(BaseModel): + url: Optional[str] = None + """This is the URL you use to render optimized attachments on the client. + + This should be used for apps. + """ class UserRetrieveResponse(BaseModel): @@ -21,5 +29,8 @@ class UserRetrieveResponse(BaseModel): name: Optional[str] = None """The name of the user from their Whop account.""" + profile_picture: Optional[ProfilePicture] = None + """The user's profile picture""" + username: str """The username of the user from their Whop account.""" diff --git a/tests/api_resources/test_forums.py b/tests/api_resources/test_forums.py new file mode 100644 index 00000000..83f4a8c5 --- /dev/null +++ b/tests/api_resources/test_forums.py @@ -0,0 +1,310 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from whop_sdk import Whop, AsyncWhop +from tests.utils import assert_matches_type +from whop_sdk.types import ForumListResponse +from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage +from whop_sdk.types.shared import Forum + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestForums: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_retrieve(self, client: Whop) -> None: + forum = client.forums.retrieve( + "id", + ) + assert_matches_type(Forum, forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: Whop) -> None: + response = client.forums.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + forum = response.parse() + assert_matches_type(Forum, forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: Whop) -> None: + with client.forums.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + forum = response.parse() + assert_matches_type(Forum, forum, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: Whop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.forums.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update(self, client: Whop) -> None: + forum = client.forums.update( + id="id", + ) + assert_matches_type(Forum, forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_update_with_all_params(self, client: Whop) -> None: + forum = client.forums.update( + id="id", + email_notification_preference="all_admin_posts", + who_can_comment="everyone", + who_can_post="everyone", + ) + assert_matches_type(Forum, forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_update(self, client: Whop) -> None: + response = client.forums.with_raw_response.update( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + forum = response.parse() + assert_matches_type(Forum, forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_update(self, client: Whop) -> None: + with client.forums.with_streaming_response.update( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + forum = response.parse() + assert_matches_type(Forum, forum, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_update(self, client: Whop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.forums.with_raw_response.update( + id="", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list(self, client: Whop) -> None: + forum = client.forums.list( + company_id="biz_xxxxxxxxxxxxxx", + ) + assert_matches_type(SyncCursorPage[ForumListResponse], forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Whop) -> None: + forum = client.forums.list( + company_id="biz_xxxxxxxxxxxxxx", + after="after", + before="before", + first=42, + last=42, + product_id="prod_xxxxxxxxxxxxx", + ) + assert_matches_type(SyncCursorPage[ForumListResponse], forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list(self, client: Whop) -> None: + response = client.forums.with_raw_response.list( + company_id="biz_xxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + forum = response.parse() + assert_matches_type(SyncCursorPage[ForumListResponse], forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Whop) -> None: + with client.forums.with_streaming_response.list( + company_id="biz_xxxxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + forum = response.parse() + assert_matches_type(SyncCursorPage[ForumListResponse], forum, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncForums: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncWhop) -> None: + forum = await async_client.forums.retrieve( + "id", + ) + assert_matches_type(Forum, forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None: + response = await async_client.forums.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + forum = await response.parse() + assert_matches_type(Forum, forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> None: + async with async_client.forums.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + forum = await response.parse() + assert_matches_type(Forum, forum, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncWhop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.forums.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update(self, async_client: AsyncWhop) -> None: + forum = await async_client.forums.update( + id="id", + ) + assert_matches_type(Forum, forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncWhop) -> None: + forum = await async_client.forums.update( + id="id", + email_notification_preference="all_admin_posts", + who_can_comment="everyone", + who_can_post="everyone", + ) + assert_matches_type(Forum, forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_update(self, async_client: AsyncWhop) -> None: + response = await async_client.forums.with_raw_response.update( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + forum = await response.parse() + assert_matches_type(Forum, forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_update(self, async_client: AsyncWhop) -> None: + async with async_client.forums.with_streaming_response.update( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + forum = await response.parse() + assert_matches_type(Forum, forum, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_update(self, async_client: AsyncWhop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.forums.with_raw_response.update( + id="", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncWhop) -> None: + forum = await async_client.forums.list( + company_id="biz_xxxxxxxxxxxxxx", + ) + assert_matches_type(AsyncCursorPage[ForumListResponse], forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> None: + forum = await async_client.forums.list( + company_id="biz_xxxxxxxxxxxxxx", + after="after", + before="before", + first=42, + last=42, + product_id="prod_xxxxxxxxxxxxx", + ) + assert_matches_type(AsyncCursorPage[ForumListResponse], forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncWhop) -> None: + response = await async_client.forums.with_raw_response.list( + company_id="biz_xxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + forum = await response.parse() + assert_matches_type(AsyncCursorPage[ForumListResponse], forum, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncWhop) -> None: + async with async_client.forums.with_streaming_response.list( + company_id="biz_xxxxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + forum = await response.parse() + assert_matches_type(AsyncCursorPage[ForumListResponse], forum, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_members.py b/tests/api_resources/test_members.py new file mode 100644 index 00000000..fc600750 --- /dev/null +++ b/tests/api_resources/test_members.py @@ -0,0 +1,224 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from whop_sdk import Whop, AsyncWhop +from tests.utils import assert_matches_type +from whop_sdk.types import MemberListResponse, MemberRetrieveResponse +from whop_sdk._utils import parse_datetime +from whop_sdk.pagination import SyncCursorPage, AsyncCursorPage + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestMembers: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_retrieve(self, client: Whop) -> None: + member = client.members.retrieve( + "id", + ) + assert_matches_type(MemberRetrieveResponse, member, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: Whop) -> None: + response = client.members.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + member = response.parse() + assert_matches_type(MemberRetrieveResponse, member, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: Whop) -> None: + with client.members.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + member = response.parse() + assert_matches_type(MemberRetrieveResponse, member, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: Whop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.members.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list(self, client: Whop) -> None: + member = client.members.list( + company_id="biz_xxxxxxxxxxxxxx", + ) + assert_matches_type(SyncCursorPage[MemberListResponse], member, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Whop) -> None: + member = client.members.list( + company_id="biz_xxxxxxxxxxxxxx", + access_level="no_access", + access_pass_ids=["string"], + after="after", + before="before", + created_after=parse_datetime("2023-12-01T05:00:00.401Z"), + created_before=parse_datetime("2023-12-01T05:00:00.401Z"), + direction="asc", + first=42, + last=42, + most_recent_actions=["canceling"], + order="id", + plan_ids=["string"], + promo_code_ids=["string"], + query="query", + statuses=["drafted"], + ) + assert_matches_type(SyncCursorPage[MemberListResponse], member, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_raw_response_list(self, client: Whop) -> None: + response = client.members.with_raw_response.list( + company_id="biz_xxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + member = response.parse() + assert_matches_type(SyncCursorPage[MemberListResponse], member, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Whop) -> None: + with client.members.with_streaming_response.list( + company_id="biz_xxxxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + member = response.parse() + assert_matches_type(SyncCursorPage[MemberListResponse], member, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncMembers: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncWhop) -> None: + member = await async_client.members.retrieve( + "id", + ) + assert_matches_type(MemberRetrieveResponse, member, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncWhop) -> None: + response = await async_client.members.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + member = await response.parse() + assert_matches_type(MemberRetrieveResponse, member, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncWhop) -> None: + async with async_client.members.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + member = await response.parse() + assert_matches_type(MemberRetrieveResponse, member, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncWhop) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.members.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncWhop) -> None: + member = await async_client.members.list( + company_id="biz_xxxxxxxxxxxxxx", + ) + assert_matches_type(AsyncCursorPage[MemberListResponse], member, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncWhop) -> None: + member = await async_client.members.list( + company_id="biz_xxxxxxxxxxxxxx", + access_level="no_access", + access_pass_ids=["string"], + after="after", + before="before", + created_after=parse_datetime("2023-12-01T05:00:00.401Z"), + created_before=parse_datetime("2023-12-01T05:00:00.401Z"), + direction="asc", + first=42, + last=42, + most_recent_actions=["canceling"], + order="id", + plan_ids=["string"], + promo_code_ids=["string"], + query="query", + statuses=["drafted"], + ) + assert_matches_type(AsyncCursorPage[MemberListResponse], member, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncWhop) -> None: + response = await async_client.members.with_raw_response.list( + company_id="biz_xxxxxxxxxxxxxx", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + member = await response.parse() + assert_matches_type(AsyncCursorPage[MemberListResponse], member, path=["response"]) + + @pytest.mark.skip(reason="Prism tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncWhop) -> None: + async with async_client.members.with_streaming_response.list( + company_id="biz_xxxxxxxxxxxxxx", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + member = await response.parse() + assert_matches_type(AsyncCursorPage[MemberListResponse], member, path=["response"]) + + assert cast(Any, response.is_closed) is True