-
Notifications
You must be signed in to change notification settings - Fork 1
V3 #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
V3 #18
Changes from 22 commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
7ff18bc
Start v3
lemonyte d4ae1b9
Remove x-api-key header
lemonyte 9f928ee
Create base product class
lemonyte 3bc627a
Add IM impl
lemonyte e0b5563
Simplify error and debug messages
lemonyte 2b2cd0e
Properly handle API response format
lemonyte 035c3c8
Use logger instead of print
lemonyte fd84c1e
Fix filename typo
lemonyte b97ac59
Add domains impl
lemonyte dd54232
re-use api error handling
lemonyte af40d81
update email overloads
lemonyte 0af2417
Forgot these changes
lemonyte 7312269
Add lease impl
lemonyte 3b27446
Add leases and domains to contiguity class
lemonyte 9041278
fix lint
lemonyte 9465bc2
Update base examples and tests for msgspec
lemonyte 62e606e
Update dev deps
lemonyte 5b7241f
Bump phonenumbers to v9
lemonyte 9458053
add imessage read and history endpoints
e91b586
Bump minimum python version to 3.10
8bdd445
Remove usage of future annotations
cb4fedb
Add from and attachments params to text.send
efd9a04
fix status code check
lemonyte dc45307
handle unexpected objects in response data
lemonyte 34d280e
fix overload typing
lemonyte 47dafda
Remove pydantic mentions
lemonyte d6b5078
Fix test discovery
lemonyte fe95248
Fix item typing in Base
lemonyte 665efef
Refactor: Use response_type in decode_response
cursoragent 93483e4
Revert "AI nonsense"
lemonyte 06a4719
pre-commit autoupdate
lemonyte 67da89f
Bump python version in workflows
lemonyte cb26916
Indicate identity is not implemented
lemonyte 36a5d89
Rename email.email to email.send
lemonyte 4baa451
Make token param optional
lemonyte 6cb9102
Ignore assert lint in tests
lemonyte 0350b6a
Clean up tests
lemonyte d985620
Add preliminary sdk tests
lemonyte File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 3 additions & 4 deletions
7
examples/base/pydantic_usage.py → examples/base/msgspec_usage.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,66 +1,51 @@ | ||
| from ._client import ApiClient | ||
| from .analytics import EmailAnalytics | ||
| from .base import AsyncBase, Base, BaseItem, InvalidKeyError, ItemConflictError, ItemNotFoundError, QueryResponse | ||
| from .domains import Domains | ||
| from .email import Email | ||
| from .imessage import IMessage | ||
| from .leases import Leases | ||
| from .otp import OTP | ||
| from .quota import Quota | ||
| from .send import Send | ||
| from .template import Template | ||
| from .verify import Verify | ||
| from .text import Text | ||
| from .whatsapp import WhatsApp | ||
|
|
||
|
|
||
| class Contiguity: | ||
| """ | ||
| Create a new instance of the Contiguity class. | ||
|
|
||
| Args: | ||
| token (str): The authentication token. | ||
| debug (bool, optional): A flag indicating whether to enable debug mode. Default is False. | ||
| """ | ||
|
|
||
| def __init__( | ||
| self, | ||
| *, | ||
| token: str, | ||
| base_url: str = "https://api.contiguity.co", | ||
| orwell_base_url: str = "https://orwell.contiguity.co", | ||
| debug: bool = False, | ||
| base_url: str = "https://api.contiguity.com", | ||
| ) -> None: | ||
| if not token: | ||
| msg = "Contiguity requires a token/API key to be provided via contiguity.login('token')" | ||
| msg = "token cannot be empty" | ||
| raise ValueError(msg) | ||
| self.token = token | ||
| self.base_url = base_url | ||
| self.orwell_base_url = orwell_base_url | ||
| self.debug = debug | ||
| self.client = ApiClient(base_url=self.base_url, api_key=token.strip()) | ||
| self.orwell_client = ApiClient(base_url=self.orwell_base_url, api_key=token.strip()) | ||
|
|
||
| self.send = Send(client=self.client, debug=self.debug) | ||
| self.verify = Verify() | ||
| self.email_analytics = EmailAnalytics(client=self.orwell_client, debug=self.debug) | ||
| self.quota = Quota(client=self.client, debug=self.debug) | ||
| self.otp = OTP(client=self.client, debug=self.debug) | ||
| self.template = Template() | ||
|
|
||
|
|
||
| def login(token: str, /, *, debug: bool = False) -> Contiguity: | ||
| return Contiguity(token=token, debug=debug) | ||
| self.text = Text(client=self.client) | ||
| self.email = Email(client=self.client) | ||
| self.otp = OTP(client=self.client) | ||
| self.imessage = IMessage(client=self.client) | ||
| self.whatsapp = WhatsApp(client=self.client) | ||
| self.leases = Leases(client=self.client) | ||
| self.domains = Domains(client=self.client) | ||
|
|
||
|
|
||
| __all__ = ( | ||
| "AsyncBase", | ||
| "Contiguity", | ||
| "Send", | ||
| "Verify", | ||
| "EmailAnalytics", | ||
| "Quota", | ||
| "OTP", | ||
| "Template", | ||
| "Base", | ||
| "BaseItem", | ||
| "InvalidKeyError", | ||
| "ItemConflictError", | ||
| "ItemNotFoundError", | ||
| "QueryResponse", | ||
| "login", | ||
| "Contiguity", | ||
| "Domains", | ||
| "Email", | ||
| "IMessage", | ||
| "Leases", | ||
| "Text", | ||
| "WhatsApp", | ||
| ) | ||
| __version__ = "2.0.0" | ||
| __version__ = "3.0.0" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,3 @@ | ||
| from __future__ import annotations | ||
|
|
||
| import os | ||
|
|
||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| import logging | ||
| from abc import ABC, abstractmethod | ||
| from collections.abc import Sequence | ||
| from typing import Generic, Literal, TypeVar | ||
|
|
||
| from ._product import BaseProduct | ||
| from ._response import BaseResponse, decode_response | ||
|
|
||
| FallbackCauseT = TypeVar("FallbackCauseT", bound=str) | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| class IMSendResponse(BaseResponse): | ||
| message_id: str | ||
|
|
||
|
|
||
| class IMTypingResponse(BaseResponse): | ||
| status: str | ||
|
|
||
|
|
||
| class IMReactionResponse(IMTypingResponse): | ||
| message: str | ||
|
|
||
|
|
||
| class InstantMessagingClient(ABC, BaseProduct, Generic[FallbackCauseT]): | ||
| @property | ||
| @abstractmethod | ||
| def _api_path(self) -> str: ... | ||
|
|
||
| def send( # noqa: PLR0913 | ||
| self, | ||
| *, | ||
| to: str, | ||
| message: str, | ||
| from_: str | None = None, | ||
| attachments: Sequence[str] | None = None, | ||
| fallback_when: Sequence[FallbackCauseT] | None = None, | ||
| fallback_number: str | None = None, | ||
| ) -> IMSendResponse: | ||
| payload = { | ||
| "to": to, | ||
| "message": message, | ||
| "from": from_, | ||
| "attachments": attachments, | ||
| "fallback_when": fallback_when, | ||
| "fallback_number": fallback_number, | ||
| } | ||
|
|
||
| response = self._client.post( | ||
| self._api_path, | ||
| json={k: v for k, v in payload.items() if v is not None}, | ||
| ) | ||
|
|
||
| self._client.handle_error(response, fail_message="failed to send instant message") | ||
| data = decode_response(response.content, type=IMSendResponse) | ||
| logger.debug("successfully sent %s message to %r", self._api_path[1:], to) | ||
| return data | ||
|
|
||
| def _typing(self, *, to: str, action: Literal["start", "stop"], from_: str | None = None) -> IMTypingResponse: | ||
| payload = { | ||
| "to": to, | ||
| "action": action, | ||
| "from": from_, | ||
| } | ||
|
|
||
| response = self._client.post( | ||
| f"{self._api_path}/typing", | ||
| json={k: v for k, v in payload.items() if v is not None}, | ||
| ) | ||
|
|
||
| self._client.handle_error(response, fail_message=f"failed to {action} {self._api_path[1:]} typing indicator") | ||
| data = decode_response(response.content, type=IMTypingResponse) | ||
| logger.debug("successfully %s %s typing indicator for %r", action, self._api_path[1:], to) | ||
| return data | ||
|
|
||
| def start_typing(self, *, to: str, from_: str | None = None) -> IMTypingResponse: | ||
| return self._typing(to=to, action="start", from_=from_) | ||
|
|
||
| def stop_typing(self, *, to: str, from_: str | None = None) -> IMTypingResponse: | ||
| return self._typing(to=to, action="stop", from_=from_) | ||
|
|
||
| def _reactions( | ||
| self, | ||
| *, | ||
| to: str, | ||
| action: Literal["add", "remove"], | ||
| reaction: str, | ||
| message: str, | ||
| ) -> IMReactionResponse: | ||
| payload = { | ||
| "to": to, | ||
| "action": action, | ||
| "reaction": reaction, | ||
| "message": message, | ||
| } | ||
|
|
||
| response = self._client.post( | ||
| f"{self._api_path}/reactions", | ||
| json={k: v for k, v in payload.items() if v is not None}, | ||
| ) | ||
|
|
||
| self._client.handle_error(response, fail_message=f"failed to {action} {self._api_path[1:]} reaction") | ||
| data = decode_response(response.content, type=IMReactionResponse) | ||
| logger.debug("successfully %s %s reaction for %r", action, self._api_path[1:], to) | ||
| return data | ||
|
|
||
| def add_reaction(self, *, to: str, reaction: str, message: str) -> IMReactionResponse: | ||
| return self._reactions(to=to, action="add", reaction=reaction, message=message) | ||
|
|
||
| def remove_reaction(self, *, to: str, reaction: str, message: str) -> IMReactionResponse: | ||
| return self._reactions(to=to, action="remove", reaction=reaction, message=message) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| from ._client import ApiClient | ||
|
|
||
|
|
||
| class BaseProduct: | ||
| def __init__(self, *, client: ApiClient) -> None: | ||
| self._client = client |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.