From d44c15f1a1bba6bbe8a5f7c77f1f42f26d68d9c6 Mon Sep 17 00:00:00 2001 From: speakeasybot Date: Wed, 7 Aug 2024 00:14:29 +0000 Subject: [PATCH] ci: regenerated with OpenAPI Doc 1.0.0, Speakeasy CLI 1.355.0 --- message/.gitattributes | 2 + message/.gitignore | 8 + message/.speakeasy/gen.lock | 187 +++ message/.vscode/settings.json | 6 + message/CONTRIBUTING.md | 26 + message/README.md | 748 ++++++++- message/RELEASES.md | 10 +- message/USAGE.md | 139 +- message/docs/models/address.md | 12 + message/docs/models/assignthreadrequest.md | 9 + message/docs/models/assignusersrequest.md | 9 + message/docs/models/assignusersrequestbody.md | 10 + message/docs/models/attachmentsrelation.md | 10 + .../docs/models/createdraftresponsebody.md | 33 + message/docs/models/createdraftsendstatus.md | 13 + message/docs/models/createdrafttype.md | 11 + message/docs/models/deletemessagerequest.md | 8 + message/docs/models/deletethreadrequest.md | 8 + message/docs/models/emailtype.md | 13 + message/docs/models/file.md | 13 + .../models/generatesuggestedreplyrequest.md | 9 + .../generatesuggestedreplyresponsebody.md | 14 + .../models/generatesuggestedreplystatus.md | 13 + .../docs/models/generatesuggestedreplytype.md | 11 + .../docs/models/getgenaifeedbackrequest.md | 9 + .../models/getgenaifeedbackresponsebody.md | 11 + .../docs/models/getgenaifeedbackresults.md | 16 + message/docs/models/getgenaifeedbacktype.md | 11 + message/docs/models/getinfogenaipayload.md | 18 + .../docs/models/getinfogenairesponsebody.md | 14 + message/docs/models/getinfogenaistatus.md | 13 + message/docs/models/getinfogenaitype.md | 11 + message/docs/models/getinfopayload.md | 18 + message/docs/models/getinforequest.md | 9 + message/docs/models/getinforesponse.md | 17 + message/docs/models/getinforesponsebody.md | 14 + message/docs/models/getinfostatus.md | 13 + message/docs/models/getinfotype.md | 11 + message/docs/models/getmessagerequest.md | 8 + message/docs/models/getmessageresponse.md | 9 + message/docs/models/getmessageresponsebody.md | 33 + message/docs/models/getmessagesendstatus.md | 13 + message/docs/models/getmessagetype.md | 11 + message/docs/models/getmessagev2request.md | 8 + message/docs/models/markreadmessagerequest.md | 8 + message/docs/models/markreadthreadrequest.md | 8 + .../docs/models/markunreadmessagerequest.md | 8 + .../docs/models/markunreadthreadrequest.md | 8 + message/docs/models/message.md | 24 + message/docs/models/messagerequestparams.md | 19 + message/docs/models/messagesendstatus.md | 13 + message/docs/models/messagev2.md | 33 + message/docs/models/messagev2sendstatus.md | 13 + message/docs/models/messagev2type.md | 11 + .../docs/models/patchinfogenairesponsebody.md | 10 + message/docs/models/patchinfopayload.md | 18 + message/docs/models/patchinforequest.md | 10 + message/docs/models/patchinforequestbody.md | 20 + message/docs/models/patchinforesponsebody.md | 14 + message/docs/models/patchinfostatus.md | 13 + message/docs/models/patchinfotype.md | 11 + message/docs/models/payload.md | 15 + message/docs/models/requestbody.md | 10 + message/docs/models/results.md | 22 + message/docs/models/searchparams.md | 10 + .../docs/models/searchthreadsresponsebody.md | 11 + message/docs/models/security.md | 9 + message/docs/models/senddraftresponsebody.md | 33 + message/docs/models/senddraftsendstatus.md | 13 + message/docs/models/senddrafttype.md | 11 + message/docs/models/senderror.md | 10 + message/docs/models/sendmessagerequest.md | 9 + message/docs/models/sendstatus.md | 16 + message/docs/models/status.md | 13 + message/docs/models/thread.md | 12 + message/docs/models/trashmessagerequest.md | 8 + message/docs/models/trashthreadrequest.md | 8 + message/docs/models/type.md | 11 + message/docs/models/untrashmessagerequest.md | 8 + message/docs/models/untrashthreadrequest.md | 8 + .../docs/models/updatemessageresponsebody.md | 33 + .../docs/models/updatemessagesendstatus.md | 13 + message/docs/models/updatemessagetype.md | 11 + .../docs/models/updatethreadresponsebody.md | 22 + message/docs/models/utils/retryconfig.md | 24 + message/docs/sdks/drafts/README.md | 137 ++ message/docs/sdks/epilot/README.md | 10 + message/docs/sdks/genai/README.md | 204 +++ message/docs/sdks/internal/README.md | 49 + message/docs/sdks/messages/README.md | 419 +++++ message/docs/sdks/threads/README.md | 370 +++++ message/gen.yaml | 43 +- message/poetry.toml | 2 + message/py.typed | 1 + message/pylintrc | 68 +- message/pyproject.toml | 55 + message/scripts/compile.sh | 83 + message/scripts/publish.sh | 5 + message/setup.py | 39 - message/src/epilot/__init__.py | 3 - message/src/epilot/drafts.py | 78 - message/src/epilot/messages.py | 208 --- message/src/epilot/models/__init__.py | 2 - .../src/epilot/models/operations/__init__.py | 22 - .../epilot/models/operations/assignthread.py | 37 - .../epilot/models/operations/createdraft.py | 100 -- .../epilot/models/operations/deletemessage.py | 22 - .../epilot/models/operations/deletethread.py | 22 - .../epilot/models/operations/getmessage.py | 107 -- .../models/operations/markreadmessage.py | 22 - .../models/operations/markreadthread.py | 22 - .../models/operations/markunreadmessage.py | 22 - .../models/operations/markunreadthread.py | 22 - .../epilot/models/operations/searchthreads.py | 63 - .../src/epilot/models/operations/senddraft.py | 100 -- .../epilot/models/operations/sendmessage.py | 100 -- .../epilot/models/operations/trashmessage.py | 22 - .../epilot/models/operations/trashthread.py | 22 - .../models/operations/untrashmessage.py | 22 - .../epilot/models/operations/untrashthread.py | 22 - .../epilot/models/operations/updatemessage.py | 100 -- .../epilot/models/operations/updatethread.py | 52 - message/src/epilot/models/shared/__init__.py | 10 - message/src/epilot/models/shared/address.py | 41 - .../models/shared/attachmentsrelation.py | 18 - message/src/epilot/models/shared/file.py | 32 - message/src/epilot/models/shared/message.py | 71 - .../src/epilot/models/shared/searchparams.py | 18 - message/src/epilot/models/shared/security.py | 13 - message/src/epilot/sdk.py | 92 -- message/src/epilot/threads.py | 215 --- message/src/epilot/utils/__init__.py | 4 - message/src/epilot/utils/retries.py | 118 -- message/src/epilot/utils/utils.py | 735 --------- message/src/epilot_message/__init__.py | 5 + message/src/epilot_message/_hooks/__init__.py | 5 + .../src/epilot_message/_hooks/registration.py | 13 + message/src/epilot_message/_hooks/sdkhooks.py | 57 + message/src/epilot_message/_hooks/types.py | 76 + message/src/epilot_message/basesdk.py | 253 +++ message/src/epilot_message/drafts.py | 294 ++++ message/src/epilot_message/genai.py | 650 ++++++++ message/src/epilot_message/httpclient.py | 78 + message/src/epilot_message/internal.py | 164 ++ message/src/epilot_message/messages.py | 1360 +++++++++++++++++ message/src/epilot_message/models/__init__.py | 37 + message/src/epilot_message/models/address.py | 106 ++ .../epilot_message/models/assignthreadop.py | 38 + .../epilot_message/models/assignusersop.py | 34 + .../models/attachmentsrelation.py | 23 + .../epilot_message/models/createdraftop.py | 139 ++ .../epilot_message/models/deletemessageop.py | 18 + .../epilot_message/models/deletethreadop.py | 18 + message/src/epilot_message/models/file.py | 45 + .../models/generatesuggestedreplyop.py | 129 ++ .../models/getgenaifeedbackop.py | 113 ++ .../src/epilot_message/models/getinfoop.py | 263 ++++ .../src/epilot_message/models/getmessageop.py | 160 ++ .../epilot_message/models/getmessagev2op.py | 18 + .../models/markreadmessageop.py | 18 + .../epilot_message/models/markreadthreadop.py | 18 + .../models/markunreadmessageop.py | 18 + .../models/markunreadthreadop.py | 18 + message/src/epilot_message/models/message.py | 106 ++ .../models/messagerequestparams.py | 98 ++ .../src/epilot_message/models/messagev2.py | 143 ++ .../src/epilot_message/models/patchinfoop.py | 248 +++ message/src/epilot_message/models/sdkerror.py | 22 + .../src/epilot_message/models/searchparams.py | 22 + .../epilot_message/models/searchthreadsop.py | 86 ++ message/src/epilot_message/models/security.py | 18 + .../src/epilot_message/models/senddraftop.py | 139 ++ .../epilot_message/models/sendmessageop.py | 21 + .../epilot_message/models/trashmessageop.py | 18 + .../epilot_message/models/trashthreadop.py | 18 + .../epilot_message/models/untrashmessageop.py | 18 + .../epilot_message/models/untrashthreadop.py | 18 + .../epilot_message/models/updatemessageop.py | 139 ++ .../epilot_message/models/updatethreadop.py | 68 + message/src/epilot_message/py.typed | 1 + message/src/epilot_message/sdk.py | 103 ++ .../src/epilot_message/sdkconfiguration.py | 48 + message/src/epilot_message/threads.py | 1360 +++++++++++++++++ message/src/epilot_message/types/__init__.py | 21 + message/src/epilot_message/types/basemodel.py | 39 + message/src/epilot_message/utils/__init__.py | 84 + .../src/epilot_message/utils/annotations.py | 19 + message/src/epilot_message/utils/enums.py | 34 + .../epilot_message/utils/eventstreaming.py | 178 +++ message/src/epilot_message/utils/forms.py | 207 +++ message/src/epilot_message/utils/headers.py | 136 ++ message/src/epilot_message/utils/logger.py | 16 + message/src/epilot_message/utils/metadata.py | 118 ++ .../src/epilot_message/utils/queryparams.py | 203 +++ .../src/epilot_message/utils/requestbodies.py | 66 + message/src/epilot_message/utils/retries.py | 216 +++ message/src/epilot_message/utils/security.py | 168 ++ .../src/epilot_message/utils/serializers.py | 181 +++ message/src/epilot_message/utils/url.py | 150 ++ message/src/epilot_message/utils/values.py | 128 ++ 200 files changed, 12358 insertions(+), 2682 deletions(-) create mode 100644 message/.gitattributes create mode 100644 message/.gitignore create mode 100644 message/.speakeasy/gen.lock create mode 100644 message/.vscode/settings.json create mode 100644 message/CONTRIBUTING.md mode change 100755 => 100644 message/USAGE.md create mode 100644 message/docs/models/address.md create mode 100644 message/docs/models/assignthreadrequest.md create mode 100644 message/docs/models/assignusersrequest.md create mode 100644 message/docs/models/assignusersrequestbody.md create mode 100644 message/docs/models/attachmentsrelation.md create mode 100644 message/docs/models/createdraftresponsebody.md create mode 100644 message/docs/models/createdraftsendstatus.md create mode 100644 message/docs/models/createdrafttype.md create mode 100644 message/docs/models/deletemessagerequest.md create mode 100644 message/docs/models/deletethreadrequest.md create mode 100644 message/docs/models/emailtype.md create mode 100644 message/docs/models/file.md create mode 100644 message/docs/models/generatesuggestedreplyrequest.md create mode 100644 message/docs/models/generatesuggestedreplyresponsebody.md create mode 100644 message/docs/models/generatesuggestedreplystatus.md create mode 100644 message/docs/models/generatesuggestedreplytype.md create mode 100644 message/docs/models/getgenaifeedbackrequest.md create mode 100644 message/docs/models/getgenaifeedbackresponsebody.md create mode 100644 message/docs/models/getgenaifeedbackresults.md create mode 100644 message/docs/models/getgenaifeedbacktype.md create mode 100644 message/docs/models/getinfogenaipayload.md create mode 100644 message/docs/models/getinfogenairesponsebody.md create mode 100644 message/docs/models/getinfogenaistatus.md create mode 100644 message/docs/models/getinfogenaitype.md create mode 100644 message/docs/models/getinfopayload.md create mode 100644 message/docs/models/getinforequest.md create mode 100644 message/docs/models/getinforesponse.md create mode 100644 message/docs/models/getinforesponsebody.md create mode 100644 message/docs/models/getinfostatus.md create mode 100644 message/docs/models/getinfotype.md create mode 100644 message/docs/models/getmessagerequest.md create mode 100644 message/docs/models/getmessageresponse.md create mode 100644 message/docs/models/getmessageresponsebody.md create mode 100644 message/docs/models/getmessagesendstatus.md create mode 100644 message/docs/models/getmessagetype.md create mode 100644 message/docs/models/getmessagev2request.md create mode 100644 message/docs/models/markreadmessagerequest.md create mode 100644 message/docs/models/markreadthreadrequest.md create mode 100644 message/docs/models/markunreadmessagerequest.md create mode 100644 message/docs/models/markunreadthreadrequest.md create mode 100644 message/docs/models/message.md create mode 100644 message/docs/models/messagerequestparams.md create mode 100644 message/docs/models/messagesendstatus.md create mode 100644 message/docs/models/messagev2.md create mode 100644 message/docs/models/messagev2sendstatus.md create mode 100644 message/docs/models/messagev2type.md create mode 100644 message/docs/models/patchinfogenairesponsebody.md create mode 100644 message/docs/models/patchinfopayload.md create mode 100644 message/docs/models/patchinforequest.md create mode 100644 message/docs/models/patchinforequestbody.md create mode 100644 message/docs/models/patchinforesponsebody.md create mode 100644 message/docs/models/patchinfostatus.md create mode 100644 message/docs/models/patchinfotype.md create mode 100644 message/docs/models/payload.md create mode 100644 message/docs/models/requestbody.md create mode 100644 message/docs/models/results.md create mode 100644 message/docs/models/searchparams.md create mode 100644 message/docs/models/searchthreadsresponsebody.md create mode 100644 message/docs/models/security.md create mode 100644 message/docs/models/senddraftresponsebody.md create mode 100644 message/docs/models/senddraftsendstatus.md create mode 100644 message/docs/models/senddrafttype.md create mode 100644 message/docs/models/senderror.md create mode 100644 message/docs/models/sendmessagerequest.md create mode 100644 message/docs/models/sendstatus.md create mode 100644 message/docs/models/status.md create mode 100644 message/docs/models/thread.md create mode 100644 message/docs/models/trashmessagerequest.md create mode 100644 message/docs/models/trashthreadrequest.md create mode 100644 message/docs/models/type.md create mode 100644 message/docs/models/untrashmessagerequest.md create mode 100644 message/docs/models/untrashthreadrequest.md create mode 100644 message/docs/models/updatemessageresponsebody.md create mode 100644 message/docs/models/updatemessagesendstatus.md create mode 100644 message/docs/models/updatemessagetype.md create mode 100644 message/docs/models/updatethreadresponsebody.md create mode 100644 message/docs/models/utils/retryconfig.md create mode 100644 message/docs/sdks/drafts/README.md create mode 100644 message/docs/sdks/epilot/README.md create mode 100644 message/docs/sdks/genai/README.md create mode 100644 message/docs/sdks/internal/README.md create mode 100644 message/docs/sdks/messages/README.md create mode 100644 message/docs/sdks/threads/README.md create mode 100644 message/poetry.toml create mode 100644 message/py.typed mode change 100755 => 100644 message/pylintrc create mode 100644 message/pyproject.toml create mode 100755 message/scripts/compile.sh create mode 100755 message/scripts/publish.sh delete mode 100755 message/setup.py delete mode 100755 message/src/epilot/__init__.py delete mode 100755 message/src/epilot/drafts.py delete mode 100755 message/src/epilot/messages.py delete mode 100755 message/src/epilot/models/__init__.py delete mode 100755 message/src/epilot/models/operations/__init__.py delete mode 100755 message/src/epilot/models/operations/assignthread.py delete mode 100755 message/src/epilot/models/operations/createdraft.py delete mode 100755 message/src/epilot/models/operations/deletemessage.py delete mode 100755 message/src/epilot/models/operations/deletethread.py delete mode 100755 message/src/epilot/models/operations/getmessage.py delete mode 100755 message/src/epilot/models/operations/markreadmessage.py delete mode 100755 message/src/epilot/models/operations/markreadthread.py delete mode 100755 message/src/epilot/models/operations/markunreadmessage.py delete mode 100755 message/src/epilot/models/operations/markunreadthread.py delete mode 100755 message/src/epilot/models/operations/searchthreads.py delete mode 100755 message/src/epilot/models/operations/senddraft.py delete mode 100755 message/src/epilot/models/operations/sendmessage.py delete mode 100755 message/src/epilot/models/operations/trashmessage.py delete mode 100755 message/src/epilot/models/operations/trashthread.py delete mode 100755 message/src/epilot/models/operations/untrashmessage.py delete mode 100755 message/src/epilot/models/operations/untrashthread.py delete mode 100755 message/src/epilot/models/operations/updatemessage.py delete mode 100755 message/src/epilot/models/operations/updatethread.py delete mode 100755 message/src/epilot/models/shared/__init__.py delete mode 100755 message/src/epilot/models/shared/address.py delete mode 100755 message/src/epilot/models/shared/attachmentsrelation.py delete mode 100755 message/src/epilot/models/shared/file.py delete mode 100755 message/src/epilot/models/shared/message.py delete mode 100755 message/src/epilot/models/shared/searchparams.py delete mode 100755 message/src/epilot/models/shared/security.py delete mode 100755 message/src/epilot/sdk.py delete mode 100755 message/src/epilot/threads.py delete mode 100755 message/src/epilot/utils/__init__.py delete mode 100755 message/src/epilot/utils/retries.py delete mode 100755 message/src/epilot/utils/utils.py create mode 100644 message/src/epilot_message/__init__.py create mode 100644 message/src/epilot_message/_hooks/__init__.py create mode 100644 message/src/epilot_message/_hooks/registration.py create mode 100644 message/src/epilot_message/_hooks/sdkhooks.py create mode 100644 message/src/epilot_message/_hooks/types.py create mode 100644 message/src/epilot_message/basesdk.py create mode 100644 message/src/epilot_message/drafts.py create mode 100644 message/src/epilot_message/genai.py create mode 100644 message/src/epilot_message/httpclient.py create mode 100644 message/src/epilot_message/internal.py create mode 100644 message/src/epilot_message/messages.py create mode 100644 message/src/epilot_message/models/__init__.py create mode 100644 message/src/epilot_message/models/address.py create mode 100644 message/src/epilot_message/models/assignthreadop.py create mode 100644 message/src/epilot_message/models/assignusersop.py create mode 100644 message/src/epilot_message/models/attachmentsrelation.py create mode 100644 message/src/epilot_message/models/createdraftop.py create mode 100644 message/src/epilot_message/models/deletemessageop.py create mode 100644 message/src/epilot_message/models/deletethreadop.py create mode 100644 message/src/epilot_message/models/file.py create mode 100644 message/src/epilot_message/models/generatesuggestedreplyop.py create mode 100644 message/src/epilot_message/models/getgenaifeedbackop.py create mode 100644 message/src/epilot_message/models/getinfoop.py create mode 100644 message/src/epilot_message/models/getmessageop.py create mode 100644 message/src/epilot_message/models/getmessagev2op.py create mode 100644 message/src/epilot_message/models/markreadmessageop.py create mode 100644 message/src/epilot_message/models/markreadthreadop.py create mode 100644 message/src/epilot_message/models/markunreadmessageop.py create mode 100644 message/src/epilot_message/models/markunreadthreadop.py create mode 100644 message/src/epilot_message/models/message.py create mode 100644 message/src/epilot_message/models/messagerequestparams.py create mode 100644 message/src/epilot_message/models/messagev2.py create mode 100644 message/src/epilot_message/models/patchinfoop.py create mode 100644 message/src/epilot_message/models/sdkerror.py create mode 100644 message/src/epilot_message/models/searchparams.py create mode 100644 message/src/epilot_message/models/searchthreadsop.py create mode 100644 message/src/epilot_message/models/security.py create mode 100644 message/src/epilot_message/models/senddraftop.py create mode 100644 message/src/epilot_message/models/sendmessageop.py create mode 100644 message/src/epilot_message/models/trashmessageop.py create mode 100644 message/src/epilot_message/models/trashthreadop.py create mode 100644 message/src/epilot_message/models/untrashmessageop.py create mode 100644 message/src/epilot_message/models/untrashthreadop.py create mode 100644 message/src/epilot_message/models/updatemessageop.py create mode 100644 message/src/epilot_message/models/updatethreadop.py create mode 100644 message/src/epilot_message/py.typed create mode 100644 message/src/epilot_message/sdk.py create mode 100644 message/src/epilot_message/sdkconfiguration.py create mode 100644 message/src/epilot_message/threads.py create mode 100644 message/src/epilot_message/types/__init__.py create mode 100644 message/src/epilot_message/types/basemodel.py create mode 100644 message/src/epilot_message/utils/__init__.py create mode 100644 message/src/epilot_message/utils/annotations.py create mode 100644 message/src/epilot_message/utils/enums.py create mode 100644 message/src/epilot_message/utils/eventstreaming.py create mode 100644 message/src/epilot_message/utils/forms.py create mode 100644 message/src/epilot_message/utils/headers.py create mode 100644 message/src/epilot_message/utils/logger.py create mode 100644 message/src/epilot_message/utils/metadata.py create mode 100644 message/src/epilot_message/utils/queryparams.py create mode 100644 message/src/epilot_message/utils/requestbodies.py create mode 100644 message/src/epilot_message/utils/retries.py create mode 100644 message/src/epilot_message/utils/security.py create mode 100644 message/src/epilot_message/utils/serializers.py create mode 100644 message/src/epilot_message/utils/url.py create mode 100644 message/src/epilot_message/utils/values.py diff --git a/message/.gitattributes b/message/.gitattributes new file mode 100644 index 000000000..4d75d5900 --- /dev/null +++ b/message/.gitattributes @@ -0,0 +1,2 @@ +# This allows generated code to be indexed correctly +*.py linguist-generated=false \ No newline at end of file diff --git a/message/.gitignore b/message/.gitignore new file mode 100644 index 000000000..477b77290 --- /dev/null +++ b/message/.gitignore @@ -0,0 +1,8 @@ +.venv/ +venv/ +src/*.egg-info/ +__pycache__/ +.pytest_cache/ +.python-version +.DS_Store +pyrightconfig.json diff --git a/message/.speakeasy/gen.lock b/message/.speakeasy/gen.lock new file mode 100644 index 000000000..26d5954fc --- /dev/null +++ b/message/.speakeasy/gen.lock @@ -0,0 +1,187 @@ +lockVersion: 2.0.0 +id: 184b5f97-43a4-4cfc-89c9-dc67c21e9f7c +management: + docChecksum: 289c6b72cc52eb9ed38250723a07c98b + docVersion: 1.0.0 + speakeasyVersion: 1.355.0 + generationVersion: 2.387.0 + releaseVersion: 1.3.0 + configChecksum: 500980f5fa54514eff279ef1ce001ccb + repoURL: https://github.com/epilot-dev/sdk-python.git + repoSubDirectory: message + installationURL: https://github.com/epilot-dev/sdk-python.git#subdirectory=message +features: + python: + additionalDependencies: 1.0.0 + additionalProperties: 1.0.0 + constsAndDefaults: 1.0.2 + core: 5.3.4 + defaultEnabledRetries: 0.2.0 + envVarSecurityUsage: 0.3.1 + flattening: 3.0.0 + globalSecurity: 3.0.1 + globalSecurityCallbacks: 1.0.0 + globalServerURLs: 3.0.0 + nullables: 1.0.0 + responseFormat: 1.0.0 + retries: 3.0.0 + sdkHooks: 1.0.0 +generatedFiles: + - src/epilot_message/sdkconfiguration.py + - src/epilot_message/drafts.py + - src/epilot_message/messages.py + - src/epilot_message/genai.py + - src/epilot_message/threads.py + - src/epilot_message/internal.py + - src/epilot_message/sdk.py + - .vscode/settings.json + - poetry.toml + - py.typed + - pylintrc + - pyproject.toml + - scripts/compile.sh + - scripts/publish.sh + - src/epilot_message/__init__.py + - src/epilot_message/basesdk.py + - src/epilot_message/httpclient.py + - src/epilot_message/py.typed + - src/epilot_message/types/__init__.py + - src/epilot_message/types/basemodel.py + - src/epilot_message/utils/__init__.py + - src/epilot_message/utils/annotations.py + - src/epilot_message/utils/enums.py + - src/epilot_message/utils/eventstreaming.py + - src/epilot_message/utils/forms.py + - src/epilot_message/utils/headers.py + - src/epilot_message/utils/logger.py + - src/epilot_message/utils/metadata.py + - src/epilot_message/utils/queryparams.py + - src/epilot_message/utils/requestbodies.py + - src/epilot_message/utils/retries.py + - src/epilot_message/utils/security.py + - src/epilot_message/utils/serializers.py + - src/epilot_message/utils/url.py + - src/epilot_message/utils/values.py + - src/epilot_message/models/sdkerror.py + - src/epilot_message/models/createdraftop.py + - src/epilot_message/models/address.py + - src/epilot_message/models/attachmentsrelation.py + - src/epilot_message/models/file.py + - src/epilot_message/models/messagerequestparams.py + - src/epilot_message/models/senddraftop.py + - src/epilot_message/models/deletemessageop.py + - src/epilot_message/models/getmessageop.py + - src/epilot_message/models/messagev2.py + - src/epilot_message/models/getmessagev2op.py + - src/epilot_message/models/markreadmessageop.py + - src/epilot_message/models/markunreadmessageop.py + - src/epilot_message/models/sendmessageop.py + - src/epilot_message/models/trashmessageop.py + - src/epilot_message/models/untrashmessageop.py + - src/epilot_message/models/updatemessageop.py + - src/epilot_message/models/generatesuggestedreplyop.py + - src/epilot_message/models/getgenaifeedbackop.py + - src/epilot_message/models/getinfoop.py + - src/epilot_message/models/patchinfoop.py + - src/epilot_message/models/assignthreadop.py + - src/epilot_message/models/assignusersop.py + - src/epilot_message/models/deletethreadop.py + - src/epilot_message/models/markreadthreadop.py + - src/epilot_message/models/markunreadthreadop.py + - src/epilot_message/models/searchthreadsop.py + - src/epilot_message/models/message.py + - src/epilot_message/models/searchparams.py + - src/epilot_message/models/trashthreadop.py + - src/epilot_message/models/untrashthreadop.py + - src/epilot_message/models/updatethreadop.py + - src/epilot_message/models/security.py + - src/epilot_message/models/__init__.py + - docs/models/createdraftsendstatus.md + - docs/models/createdrafttype.md + - docs/models/createdraftresponsebody.md + - docs/models/emailtype.md + - docs/models/senderror.md + - docs/models/sendstatus.md + - docs/models/address.md + - docs/models/attachmentsrelation.md + - docs/models/file.md + - docs/models/thread.md + - docs/models/messagerequestparams.md + - docs/models/senddraftsendstatus.md + - docs/models/senddrafttype.md + - docs/models/senddraftresponsebody.md + - docs/models/deletemessagerequest.md + - docs/models/getmessagerequest.md + - docs/models/getmessagesendstatus.md + - docs/models/getmessagetype.md + - docs/models/getmessageresponsebody.md + - docs/models/getmessageresponse.md + - docs/models/messagev2sendstatus.md + - docs/models/messagev2type.md + - docs/models/messagev2.md + - docs/models/getmessagev2request.md + - docs/models/markreadmessagerequest.md + - docs/models/markunreadmessagerequest.md + - docs/models/sendmessagerequest.md + - docs/models/trashmessagerequest.md + - docs/models/untrashmessagerequest.md + - docs/models/updatemessagesendstatus.md + - docs/models/updatemessagetype.md + - docs/models/updatemessageresponsebody.md + - docs/models/generatesuggestedreplyrequest.md + - docs/models/generatesuggestedreplystatus.md + - docs/models/payload.md + - docs/models/generatesuggestedreplytype.md + - docs/models/generatesuggestedreplyresponsebody.md + - docs/models/getgenaifeedbackrequest.md + - docs/models/getgenaifeedbacktype.md + - docs/models/getgenaifeedbackresults.md + - docs/models/getgenaifeedbackresponsebody.md + - docs/models/getinforequest.md + - docs/models/getinfogenaistatus.md + - docs/models/getinfogenaipayload.md + - docs/models/getinfogenaitype.md + - docs/models/getinfogenairesponsebody.md + - docs/models/getinfostatus.md + - docs/models/getinfopayload.md + - docs/models/getinfotype.md + - docs/models/getinforesponsebody.md + - docs/models/getinforesponse.md + - docs/models/status.md + - docs/models/patchinforequestbody.md + - docs/models/patchinforequest.md + - docs/models/patchinfogenairesponsebody.md + - docs/models/patchinfostatus.md + - docs/models/patchinfopayload.md + - docs/models/patchinfotype.md + - docs/models/patchinforesponsebody.md + - docs/models/requestbody.md + - docs/models/assignthreadrequest.md + - docs/models/assignusersrequestbody.md + - docs/models/assignusersrequest.md + - docs/models/deletethreadrequest.md + - docs/models/markreadthreadrequest.md + - docs/models/markunreadthreadrequest.md + - docs/models/results.md + - docs/models/searchthreadsresponsebody.md + - docs/models/messagesendstatus.md + - docs/models/type.md + - docs/models/message.md + - docs/models/searchparams.md + - docs/models/trashthreadrequest.md + - docs/models/untrashthreadrequest.md + - docs/models/updatethreadresponsebody.md + - docs/models/security.md + - docs/sdks/epilot/README.md + - docs/models/utils/retryconfig.md + - docs/sdks/drafts/README.md + - docs/sdks/messages/README.md + - docs/sdks/genai/README.md + - docs/sdks/threads/README.md + - docs/sdks/internal/README.md + - USAGE.md + - .gitattributes + - src/epilot_message/_hooks/sdkhooks.py + - src/epilot_message/_hooks/types.py + - src/epilot_message/_hooks/__init__.py + - CONTRIBUTING.md diff --git a/message/.vscode/settings.json b/message/.vscode/settings.json new file mode 100644 index 000000000..8d79f0abb --- /dev/null +++ b/message/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "python.testing.pytestArgs": ["tests", "-vv"], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true, + "pylint.args": ["--rcfile=pylintrc"] +} diff --git a/message/CONTRIBUTING.md b/message/CONTRIBUTING.md new file mode 100644 index 000000000..d585717fc --- /dev/null +++ b/message/CONTRIBUTING.md @@ -0,0 +1,26 @@ +# Contributing to This Repository + +Thank you for your interest in contributing to this repository. Please note that this repository contains generated code. As such, we do not accept direct changes or pull requests. Instead, we encourage you to follow the guidelines below to report issues and suggest improvements. + +## How to Report Issues + +If you encounter any bugs or have suggestions for improvements, please open an issue on GitHub. When reporting an issue, please provide as much detail as possible to help us reproduce the problem. This includes: + +- A clear and descriptive title +- Steps to reproduce the issue +- Expected and actual behavior +- Any relevant logs, screenshots, or error messages +- Information about your environment (e.g., operating system, software versions) + - For example can be collected using the `npx envinfo` command from your terminal if you have Node.js installed + +## Issue Triage and Upstream Fixes + +We will review and triage issues as quickly as possible. Our goal is to address bugs and incorporate improvements in the upstream source code. Fixes will be included in the next generation of the generated code. + +## Contact + +If you have any questions or need further assistance, please feel free to reach out by opening an issue. + +Thank you for your understanding and cooperation! + +The Maintainers diff --git a/message/README.md b/message/README.md index 98f91d936..8f359ffc4 100755 --- a/message/README.md +++ b/message/README.md @@ -1,65 +1,739 @@ # epilot-message - + ## SDK Installation +PIP ```bash pip install git+https://github.com/epilot-dev/sdk-python.git#subdirectory=message ``` - +Poetry +```bash +poetry add git+https://github.com/epilot-dev/sdk-python.git#subdirectory=message +``` + + + ## SDK Example Usage - + +### Example + ```python -import epilot -from epilot.models import operations, shared +# Synchronous Example +import epilot_message +from epilot_message import Epilot -s = epilot.Epilot( - security=shared.Security( - epilot_auth="Bearer YOUR_BEARER_TOKEN_HERE", +s = Epilot( + security=epilot_message.Security( + epilot_auth="", ), ) -req = "unde" - -res = s.drafts.create_draft(req) +res = s.drafts.create_draft(request=epilot_message.MessageRequestParams( + from_={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + subject="Request for solar panel price", + bcc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + cc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + file={ + "dollar_relation": [ + { + "entity_id": "f820ce3b-07b0-45ae-bcc6-babb2f53f79f", + "cid": "fb222496-a1a5-4639-94f2-07b5e35e4068", + "filename": "Produktinformationen_epilot360_Double_Opt_in.pdf", + }, + ], + }, + html="
We at ABC GmbH would like to request a price quote for the solar panel.
", + parent_id="44d7a3eb-0cce-4bd3-a7cd-0b3e652de0c2", + reply_to={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + text="We at ABC GmbH would like to request a price quote for the solar panel.", + thread={ + "topic": "CUSTOMER_MESSAGE", + "assigned_to": [ + "206801", + "200109", + ], + }, + to=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], +)) -if res.create_draft_201_application_json_object is not None: +if res is not None: # handle response + pass +``` + +
+ +The same SDK client can also be used to make asychronous requests by importing asyncio. +```python +# Asynchronous Example +import asyncio +import epilot_message +from epilot_message import Epilot + +async def main(): + s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), + ) + res = await s.drafts.create_draft_async(request=epilot_message.MessageRequestParams( + from_={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + subject="Request for solar panel price", + bcc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + cc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + file={ + "dollar_relation": [ + { + "entity_id": "f820ce3b-07b0-45ae-bcc6-babb2f53f79f", + "cid": "fb222496-a1a5-4639-94f2-07b5e35e4068", + "filename": "Produktinformationen_epilot360_Double_Opt_in.pdf", + }, + ], + }, + html="
We at ABC GmbH would like to request a price quote for the solar panel.
", + parent_id="44d7a3eb-0cce-4bd3-a7cd-0b3e652de0c2", + reply_to={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + text="We at ABC GmbH would like to request a price quote for the solar panel.", + thread={ + "topic": "CUSTOMER_MESSAGE", + "assigned_to": [ + "206801", + "200109", + ], + }, + to=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + )) + if res is not None: + # handle response + pass + +asyncio.run(main()) +``` + + + +## Available Resources and Operations + +### [drafts](docs/sdks/drafts/README.md) + +* [create_draft](docs/sdks/drafts/README.md#create_draft) - createDraft +* [send_draft](docs/sdks/drafts/README.md#send_draft) - sendDraft + +### [messages](docs/sdks/messages/README.md) + +* [delete_message](docs/sdks/messages/README.md#delete_message) - deleteMessage +* [get_message](docs/sdks/messages/README.md#get_message) - getMessage +* [get_message_v2](docs/sdks/messages/README.md#get_message_v2) - getMessageV2 +* [mark_read_message](docs/sdks/messages/README.md#mark_read_message) - markReadMessage +* [mark_unread_message](docs/sdks/messages/README.md#mark_unread_message) - markUnreadMessage +* [send_message](docs/sdks/messages/README.md#send_message) - sendMessage +* [trash_message](docs/sdks/messages/README.md#trash_message) - trashMessage +* [untrash_message](docs/sdks/messages/README.md#untrash_message) - untrashMessage +* [update_message](docs/sdks/messages/README.md#update_message) - updateMessage + +### [gen_ai](docs/sdks/genai/README.md) + +* [generate_suggested_reply](docs/sdks/genai/README.md#generate_suggested_reply) - generateSuggestedReply +* [get_gen_ai_feedback](docs/sdks/genai/README.md#get_gen_ai_feedback) - getGenAIFeedback +* [get_info](docs/sdks/genai/README.md#get_info) - getInfo +* [patch_info](docs/sdks/genai/README.md#patch_info) - patchInfo + +### [threads](docs/sdks/threads/README.md) + +* [assign_thread](docs/sdks/threads/README.md#assign_thread) - assignThread +* [assign_users](docs/sdks/threads/README.md#assign_users) - assignUsers +* [delete_thread](docs/sdks/threads/README.md#delete_thread) - deleteThread +* [mark_read_thread](docs/sdks/threads/README.md#mark_read_thread) - markReadThread +* [mark_unread_thread](docs/sdks/threads/README.md#mark_unread_thread) - markUnreadThread +* [search_threads](docs/sdks/threads/README.md#search_threads) - searchThreads +* [trash_thread](docs/sdks/threads/README.md#trash_thread) - trashThread +* [untrash_thread](docs/sdks/threads/README.md#untrash_thread) - untrashThread +* [update_thread](docs/sdks/threads/README.md#update_thread) - updateThread + +### [internal](docs/sdks/internal/README.md) + +* [get_gen_ai_feedback](docs/sdks/internal/README.md#get_gen_ai_feedback) - getGenAIFeedback + + + +## Retries + +Some of the endpoints in this SDK support retries. If you use the SDK without any configuration, it will fall back to the default retry strategy provided by the API. However, the default retry strategy can be overridden on a per-operation basis, or across the entire SDK. + +To change the default retry strategy for a single API call, simply provide a `RetryConfig` object to the call: +```python +from epilot.utils import BackoffStrategy, RetryConfig +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.drafts.create_draft(request=epilot_message.MessageRequestParams( + from_={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + subject="Request for solar panel price", + bcc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + cc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + file={ + "dollar_relation": [ + { + "entity_id": "f820ce3b-07b0-45ae-bcc6-babb2f53f79f", + "cid": "fb222496-a1a5-4639-94f2-07b5e35e4068", + "filename": "Produktinformationen_epilot360_Double_Opt_in.pdf", + }, + ], + }, + html="
We at ABC GmbH would like to request a price quote for the solar panel.
", + parent_id="44d7a3eb-0cce-4bd3-a7cd-0b3e652de0c2", + reply_to={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + text="We at ABC GmbH would like to request a price quote for the solar panel.", + thread={ + "topic": "CUSTOMER_MESSAGE", + "assigned_to": [ + "206801", + "200109", + ], + }, + to=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], +), + RetryConfig("backoff", BackoffStrategy(1, 50, 1.1, 100), False)) + +if res is not None: + # handle response + pass + +``` + +If you'd like to override the default retry strategy for all operations that support retries, you can use the `retry_config` optional parameter when initializing the SDK: +```python +from epilot.utils import BackoffStrategy, RetryConfig +import epilot_message +from epilot_message import Epilot + +s = Epilot( + retry_config=RetryConfig("backoff", BackoffStrategy(1, 50, 1.1, 100), False), + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.drafts.create_draft(request=epilot_message.MessageRequestParams( + from_={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + subject="Request for solar panel price", + bcc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + cc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + file={ + "dollar_relation": [ + { + "entity_id": "f820ce3b-07b0-45ae-bcc6-babb2f53f79f", + "cid": "fb222496-a1a5-4639-94f2-07b5e35e4068", + "filename": "Produktinformationen_epilot360_Double_Opt_in.pdf", + }, + ], + }, + html="
We at ABC GmbH would like to request a price quote for the solar panel.
", + parent_id="44d7a3eb-0cce-4bd3-a7cd-0b3e652de0c2", + reply_to={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + text="We at ABC GmbH would like to request a price quote for the solar panel.", + thread={ + "topic": "CUSTOMER_MESSAGE", + "assigned_to": [ + "206801", + "200109", + ], + }, + to=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], +)) + +if res is not None: + # handle response + pass + +``` + + + +## Error Handling + +Handling errors in this SDK should largely match your expectations. All operations return a response object or raise an error. If Error objects are specified in your OpenAPI Spec, the SDK will raise the appropriate Error type. + +| Error Object | Status Code | Content Type | +| --------------------------------- | --------------------------------- | --------------------------------- | +| models.PatchInfoGenAIResponseBody | 500 | application/json | +| models.SDKError | 4xx-5xx | */* | + +### Example + +```python +import epilot_message +from epilot_message import Epilot, models + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + +res = None +try: + res = s.gen_ai.patch_info(message_id="", thread_id="", request_body={ + "created_at": 1612900000000, + "error": "Failed to generate summary", + "feedback": "Good summary", + "next_steps": [ + "The agent should approve the refund", + ], + "progress": 100, + "rating": "positive", + "status": epilot_message.Status.COMPLETED, + "summary": [ + "Customer is interested in solar panels", + ], + "tags": [ + "solar", + "quote", + ], + "topics": [ + "Product enquiry", + ], + "updated_at": 1612900000000, +}) + +except models.PatchInfoGenAIResponseBody as e: + # handle exception + raise(e) +except models.SDKError as e: + # handle exception + raise(e) + +if res is not None: + # handle response + pass + ``` - + - -## SDK Available Operations + +## Server Selection +### Select Server by Index -### drafts +You can override the default server globally by passing a server index to the `server_idx: int` optional parameter when initializing the SDK client instance. The selected server will then be used as the default on the operations that use it. This table lists the indexes associated with the available servers: -* `create_draft` - createDraft -* `send_draft` - sendDraft +| # | Server | Variables | +| - | ------ | --------- | +| 0 | `https://message.sls.epilot.io` | None | -### messages +#### Example + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + server_idx=0, + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.drafts.create_draft(request=epilot_message.MessageRequestParams( + from_={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + subject="Request for solar panel price", + bcc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + cc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + file={ + "dollar_relation": [ + { + "entity_id": "f820ce3b-07b0-45ae-bcc6-babb2f53f79f", + "cid": "fb222496-a1a5-4639-94f2-07b5e35e4068", + "filename": "Produktinformationen_epilot360_Double_Opt_in.pdf", + }, + ], + }, + html="
We at ABC GmbH would like to request a price quote for the solar panel.
", + parent_id="44d7a3eb-0cce-4bd3-a7cd-0b3e652de0c2", + reply_to={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + text="We at ABC GmbH would like to request a price quote for the solar panel.", + thread={ + "topic": "CUSTOMER_MESSAGE", + "assigned_to": [ + "206801", + "200109", + ], + }, + to=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], +)) + +if res is not None: + # handle response + pass + +``` + + +### Override Server URL Per-Client + +The default server can also be overridden globally by passing a URL to the `server_url: str` optional parameter when initializing the SDK client instance. For example: +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + server_url="https://message.sls.epilot.io", + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.drafts.create_draft(request=epilot_message.MessageRequestParams( + from_={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + subject="Request for solar panel price", + bcc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + cc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + file={ + "dollar_relation": [ + { + "entity_id": "f820ce3b-07b0-45ae-bcc6-babb2f53f79f", + "cid": "fb222496-a1a5-4639-94f2-07b5e35e4068", + "filename": "Produktinformationen_epilot360_Double_Opt_in.pdf", + }, + ], + }, + html="
We at ABC GmbH would like to request a price quote for the solar panel.
", + parent_id="44d7a3eb-0cce-4bd3-a7cd-0b3e652de0c2", + reply_to={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + text="We at ABC GmbH would like to request a price quote for the solar panel.", + thread={ + "topic": "CUSTOMER_MESSAGE", + "assigned_to": [ + "206801", + "200109", + ], + }, + to=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], +)) + +if res is not None: + # handle response + pass + +``` + + + +## Custom HTTP Client + +The Python SDK makes API calls using the [httpx](https://www.python-httpx.org/) HTTP library. In order to provide a convenient way to configure timeouts, cookies, proxies, custom headers, and other low-level configuration, you can initialize the SDK client with your own HTTP client instance. +Depending on whether you are using the sync or async version of the SDK, you can pass an instance of `HttpClient` or `AsyncHttpClient` respectively, which are Protocol's ensuring that the client has the necessary methods to make API calls. +This allows you to wrap the client with your own custom logic, such as adding custom headers, logging, or error handling, or you can just pass an instance of `httpx.Client` or `httpx.AsyncClient` directly. + +For example, you could specify a header for every request that this sdk makes as follows: +```python +from epilot_message import Epilot +import httpx + +http_client = httpx.Client(headers={"x-custom-header": "someValue"}) +s = Epilot(client=http_client) +``` + +or you could wrap the client with your own custom logic: +```python +from epilot_message import Epilot +from epilot_message.httpclient import AsyncHttpClient +import httpx + +class CustomClient(AsyncHttpClient): + client: AsyncHttpClient + + def __init__(self, client: AsyncHttpClient): + self.client = client + + async def send( + self, + request: httpx.Request, + *, + stream: bool = False, + auth: Union[ + httpx._types.AuthTypes, httpx._client.UseClientDefault, None + ] = httpx.USE_CLIENT_DEFAULT, + follow_redirects: Union[ + bool, httpx._client.UseClientDefault + ] = httpx.USE_CLIENT_DEFAULT, + ) -> httpx.Response: + request.headers["Client-Level-Header"] = "added by client" + + return await self.client.send( + request, stream=stream, auth=auth, follow_redirects=follow_redirects + ) + + def build_request( + self, + method: str, + url: httpx._types.URLTypes, + *, + content: Optional[httpx._types.RequestContent] = None, + data: Optional[httpx._types.RequestData] = None, + files: Optional[httpx._types.RequestFiles] = None, + json: Optional[Any] = None, + params: Optional[httpx._types.QueryParamTypes] = None, + headers: Optional[httpx._types.HeaderTypes] = None, + cookies: Optional[httpx._types.CookieTypes] = None, + timeout: Union[ + httpx._types.TimeoutTypes, httpx._client.UseClientDefault + ] = httpx.USE_CLIENT_DEFAULT, + extensions: Optional[httpx._types.RequestExtensions] = None, + ) -> httpx.Request: + return self.client.build_request( + method, + url, + content=content, + data=data, + files=files, + json=json, + params=params, + headers=headers, + cookies=cookies, + timeout=timeout, + extensions=extensions, + ) + +s = Epilot(async_client=CustomClient(httpx.AsyncClient())) +``` + + + +## Authentication + +### Per-Client Security Schemes + +This SDK supports the following security schemes globally: + +| Name | Type | Scheme | +| ------------- | ------------- | ------------- | +| `epilot_auth` | http | HTTP Bearer | +| `epilot_org` | apiKey | API key | + +You can set the security parameters through the `security` optional parameter when initializing the SDK client instance. The selected scheme will be used by default to authenticate with the API for all operations that support it. For example: +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.drafts.create_draft(request=epilot_message.MessageRequestParams( + from_={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + subject="Request for solar panel price", + bcc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + cc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + file={ + "dollar_relation": [ + { + "entity_id": "f820ce3b-07b0-45ae-bcc6-babb2f53f79f", + "cid": "fb222496-a1a5-4639-94f2-07b5e35e4068", + "filename": "Produktinformationen_epilot360_Double_Opt_in.pdf", + }, + ], + }, + html="
We at ABC GmbH would like to request a price quote for the solar panel.
", + parent_id="44d7a3eb-0cce-4bd3-a7cd-0b3e652de0c2", + reply_to={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + text="We at ABC GmbH would like to request a price quote for the solar panel.", + thread={ + "topic": "CUSTOMER_MESSAGE", + "assigned_to": [ + "206801", + "200109", + ], + }, + to=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], +)) + +if res is not None: + # handle response + pass + +``` + + + +## Debugging + +To emit debug logs for SDK requests and responses you can pass a logger object directly into your SDK object. + +```python +from epilot_message import Epilot +import logging + +logging.basicConfig(level=logging.DEBUG) +s = Epilot(debug_logger=logging.getLogger("epilot_message")) +``` + -* `delete_message` - deleteMessage -* `get_message` - getMessage -* `mark_read_message` - markReadMessage -* `mark_unread_message` - markUnreadMessage -* `send_message` - sendMessage -* `trash_message` - trashMessage -* `untrash_message` - untrashMessage -* `update_message` - updateMessage + -### threads -* `assign_thread` - assignThread -* `delete_thread` - deleteThread -* `mark_read_thread` - markReadThread -* `mark_unread_thread` - markUnreadThread -* `search_threads` - searchThreads -* `trash_thread` - trashThread -* `untrash_thread` - untrashThread -* `update_thread` - updateThread - ### SDK Generated by [Speakeasy](https://docs.speakeasyapi.dev/docs/using-speakeasy/client-sdks) diff --git a/message/RELEASES.md b/message/RELEASES.md index cb372def0..6696329c8 100644 --- a/message/RELEASES.md +++ b/message/RELEASES.md @@ -34,4 +34,12 @@ Based on: ### Changes Based on: - OpenAPI Doc 1.0.0 https://docs.api.epilot.io/message.yaml -- Speakeasy CLI 1.19.2 (2.16.5) https://github.com/speakeasy-api/speakeasy \ No newline at end of file +- Speakeasy CLI 1.19.2 (2.16.5) https://github.com/speakeasy-api/speakeasy + +## 2024-08-07 00:14:18 +### Changes +Based on: +- OpenAPI Doc 1.0.0 https://docs.api.epilot.io/message.yaml +- Speakeasy CLI 1.355.0 (2.387.0) https://github.com/speakeasy-api/speakeasy +### Generated +- [python v1.3.0] message \ No newline at end of file diff --git a/message/USAGE.md b/message/USAGE.md old mode 100755 new mode 100644 index 3e30ad7fb..7135eb627 --- a/message/USAGE.md +++ b/message/USAGE.md @@ -1,20 +1,137 @@ - + ```python -import epilot -from epilot.models import operations, shared +# Synchronous Example +import epilot_message +from epilot_message import Epilot -s = epilot.Epilot( - security=shared.Security( - epilot_auth="Bearer YOUR_BEARER_TOKEN_HERE", +s = Epilot( + security=epilot_message.Security( + epilot_auth="", ), ) -req = "unde" - -res = s.drafts.create_draft(req) +res = s.drafts.create_draft(request=epilot_message.MessageRequestParams( + from_={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + subject="Request for solar panel price", + bcc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + cc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + file={ + "dollar_relation": [ + { + "entity_id": "f820ce3b-07b0-45ae-bcc6-babb2f53f79f", + "cid": "fb222496-a1a5-4639-94f2-07b5e35e4068", + "filename": "Produktinformationen_epilot360_Double_Opt_in.pdf", + }, + ], + }, + html="
We at ABC GmbH would like to request a price quote for the solar panel.
", + parent_id="44d7a3eb-0cce-4bd3-a7cd-0b3e652de0c2", + reply_to={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + text="We at ABC GmbH would like to request a price quote for the solar panel.", + thread={ + "topic": "CUSTOMER_MESSAGE", + "assigned_to": [ + "206801", + "200109", + ], + }, + to=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], +)) -if res.create_draft_201_application_json_object is not None: +if res is not None: # handle response + pass ``` - \ No newline at end of file + +
+ +The same SDK client can also be used to make asychronous requests by importing asyncio. +```python +# Asynchronous Example +import asyncio +import epilot_message +from epilot_message import Epilot + +async def main(): + s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), + ) + res = await s.drafts.create_draft_async(request=epilot_message.MessageRequestParams( + from_={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + subject="Request for solar panel price", + bcc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + cc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + file={ + "dollar_relation": [ + { + "entity_id": "f820ce3b-07b0-45ae-bcc6-babb2f53f79f", + "cid": "fb222496-a1a5-4639-94f2-07b5e35e4068", + "filename": "Produktinformationen_epilot360_Double_Opt_in.pdf", + }, + ], + }, + html="
We at ABC GmbH would like to request a price quote for the solar panel.
", + parent_id="44d7a3eb-0cce-4bd3-a7cd-0b3e652de0c2", + reply_to={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + text="We at ABC GmbH would like to request a price quote for the solar panel.", + thread={ + "topic": "CUSTOMER_MESSAGE", + "assigned_to": [ + "206801", + "200109", + ], + }, + to=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + )) + if res is not None: + # handle response + pass + +asyncio.run(main()) +``` + \ No newline at end of file diff --git a/message/docs/models/address.md b/message/docs/models/address.md new file mode 100644 index 000000000..8cdae006b --- /dev/null +++ b/message/docs/models/address.md @@ -0,0 +1,12 @@ +# Address + + +## Fields + +| Field | Type | Required | Description | Example | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `address` | *str* | :heavy_check_mark: | Email address | messaging@epilot.cloud | +| `email_type` | [OptionalNullable[models.EmailType]](../models/emailtype.md) | :heavy_minus_sign: | Type of the email, Internal (360 Agents), Partners, External users(Customers)
| | +| `name` | *Optional[str]* | :heavy_minus_sign: | Email address alias | epilot | +| `send_error` | [Optional[models.SendError]](../models/senderror.md) | :heavy_minus_sign: | Information about reject, complaint or bounce event. Only available if `send_status` is REJECT, COMPLAINT, BOUNCE or ERROR. JSON object is defined by AWS SES. Reference at
| | +| `send_status` | [Optional[models.SendStatus]](../models/sendstatus.md) | :heavy_minus_sign: | Sent message status regarding to this recipient. Reference at
| | \ No newline at end of file diff --git a/message/docs/models/assignthreadrequest.md b/message/docs/models/assignthreadrequest.md new file mode 100644 index 000000000..4fe17c659 --- /dev/null +++ b/message/docs/models/assignthreadrequest.md @@ -0,0 +1,9 @@ +# AssignThreadRequest + + +## Fields + +| Field | Type | Required | Description | +| ---------------------------------------------------- | ---------------------------------------------------- | ---------------------------------------------------- | ---------------------------------------------------- | +| `request_body` | List[[models.RequestBody](../models/requestbody.md)] | :heavy_check_mark: | N/A | +| `id` | *str* | :heavy_check_mark: | Thread ID | \ No newline at end of file diff --git a/message/docs/models/assignusersrequest.md b/message/docs/models/assignusersrequest.md new file mode 100644 index 000000000..c1199be06 --- /dev/null +++ b/message/docs/models/assignusersrequest.md @@ -0,0 +1,9 @@ +# AssignUsersRequest + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------- | +| `request_body` | [models.AssignUsersRequestBody](../models/assignusersrequestbody.md) | :heavy_check_mark: | N/A | +| `id` | *str* | :heavy_check_mark: | Thread ID | \ No newline at end of file diff --git a/message/docs/models/assignusersrequestbody.md b/message/docs/models/assignusersrequestbody.md new file mode 100644 index 000000000..56b8d027e --- /dev/null +++ b/message/docs/models/assignusersrequestbody.md @@ -0,0 +1,10 @@ +# AssignUsersRequestBody + +User IDs of users assigned to thread + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------- | ------------------------------- | ------------------------------- | ------------------------------- | +| `assigned_to` | List[*str*] | :heavy_minus_sign: | IDs of users assigned to thread | \ No newline at end of file diff --git a/message/docs/models/attachmentsrelation.md b/message/docs/models/attachmentsrelation.md new file mode 100644 index 000000000..c64205b61 --- /dev/null +++ b/message/docs/models/attachmentsrelation.md @@ -0,0 +1,10 @@ +# AttachmentsRelation + +Message attachments + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| `dollar_relation` | List[[models.File](../models/file.md)] | :heavy_minus_sign: | It's normal entity relation with some additional properties for sending message attachment. | \ No newline at end of file diff --git a/message/docs/models/createdraftresponsebody.md b/message/docs/models/createdraftresponsebody.md new file mode 100644 index 000000000..6b1a6d282 --- /dev/null +++ b/message/docs/models/createdraftresponsebody.md @@ -0,0 +1,33 @@ +# CreateDraftResponseBody + +Success + + +## Fields + +| Field | Type | Required | Description | Example | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `created_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Created date | 2021-02-09 12:41:43.662 +0000 UTC | +| `id` | *str* | :heavy_check_mark: | Entity ID | 3fa85f64-5717-4562-b3fc-2c963f66afa6 | +| `org` | *str* | :heavy_check_mark: | Ivy Organization ID the entity belongs to | 206801 | +| `schema_` | *str* | :heavy_check_mark: | URL-friendly identifier for the entity schema | message | +| `title` | *str* | :heavy_check_mark: | Entity title | | +| `updated_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Updated date | 2021-02-10 09:14:31.99 +0000 UTC | +| `from_` | [models.Address](../models/address.md) | :heavy_check_mark: | N/A | | +| `subject` | *str* | :heavy_check_mark: | Subject | Request for solar panel price | +| `tags` | List[*str*] | :heavy_minus_sign: | Entity tags | [
"pricing",
"INBOX"
] | +| `bcc` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | Bcc email addresses | | +| `cc` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | Cc email addresses | | +| `file` | [Optional[models.AttachmentsRelation]](../models/attachmentsrelation.md) | :heavy_minus_sign: | Message attachments | | +| `html` | *Optional[str]* | :heavy_minus_sign: | HTML body |
We at ABC GmbH would like to request a price quote for the solar panel.
| +| `in_reply_to` | *Optional[str]* | :heavy_minus_sign: | In-Reply-To header. Value is the `message_id` of parent message.
| | +| `message_id` | *Optional[str]* | :heavy_minus_sign: | Message ID which is from email provider. If you provide `message-id`, API overrides by its own value. | <0102017b97a502f8-a67f01c2-68cc-4928-b91b-45853f34e259-000000@eu-west-1.amazonses.com> | +| `org_read_message` | List[*str*] | :heavy_minus_sign: | Ivy Organization ID of organization read the message. | | +| `references` | *Optional[str]* | :heavy_minus_sign: | References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying.
| <0102017b97a502f8-a67f01c2-68cc-4928-b91b-45853f34e259-000000@eu-west-1.amazonses.com> | +| `reply_to` | [Optional[models.Address]](../models/address.md) | :heavy_minus_sign: | N/A | | +| `send_status` | List[[models.CreateDraftSendStatus](../models/createdraftsendstatus.md)] | :heavy_minus_sign: | Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at
| | +| `sender` | *Optional[str]* | :heavy_minus_sign: | Ivy User ID of user sends the message. | 206801 | +| `text` | *Optional[str]* | :heavy_minus_sign: | Text body | We at ABC GmbH would like to request a price quote for the solar panel. | +| `to` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | To email addresses | | +| `type` | [Optional[models.CreateDraftType]](../models/createdrafttype.md) | :heavy_minus_sign: | Message type | | +| `user_read_message` | List[*str*] | :heavy_minus_sign: | Ivy User ID of user read the message. | | \ No newline at end of file diff --git a/message/docs/models/createdraftsendstatus.md b/message/docs/models/createdraftsendstatus.md new file mode 100644 index 000000000..e66ba6e4e --- /dev/null +++ b/message/docs/models/createdraftsendstatus.md @@ -0,0 +1,13 @@ +# CreateDraftSendStatus + + +## Values + +| Name | Value | +| ----------- | ----------- | +| `SEND` | SEND | +| `DELIVERY` | DELIVERY | +| `REJECT` | REJECT | +| `COMPLAINT` | COMPLAINT | +| `BOUNCE` | BOUNCE | +| `ERROR` | ERROR | \ No newline at end of file diff --git a/message/docs/models/createdrafttype.md b/message/docs/models/createdrafttype.md new file mode 100644 index 000000000..b38c2b753 --- /dev/null +++ b/message/docs/models/createdrafttype.md @@ -0,0 +1,11 @@ +# CreateDraftType + +Message type + + +## Values + +| Name | Value | +| ---------- | ---------- | +| `SENT` | SENT | +| `RECEIVED` | RECEIVED | \ No newline at end of file diff --git a/message/docs/models/deletemessagerequest.md b/message/docs/models/deletemessagerequest.md new file mode 100644 index 000000000..cb6e818bc --- /dev/null +++ b/message/docs/models/deletemessagerequest.md @@ -0,0 +1,8 @@ +# DeleteMessageRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `id` | *str* | :heavy_check_mark: | Message ID | \ No newline at end of file diff --git a/message/docs/models/deletethreadrequest.md b/message/docs/models/deletethreadrequest.md new file mode 100644 index 000000000..b81b61eea --- /dev/null +++ b/message/docs/models/deletethreadrequest.md @@ -0,0 +1,8 @@ +# DeleteThreadRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `id` | *str* | :heavy_check_mark: | Thread ID | \ No newline at end of file diff --git a/message/docs/models/emailtype.md b/message/docs/models/emailtype.md new file mode 100644 index 000000000..b134d77b7 --- /dev/null +++ b/message/docs/models/emailtype.md @@ -0,0 +1,13 @@ +# EmailType + +Type of the email, Internal (360 Agents), Partners, External users(Customers) + + + +## Values + +| Name | Value | +| ---------- | ---------- | +| `INTERNAL` | INTERNAL | +| `EXTERNAL` | EXTERNAL | +| `PARTNER` | PARTNER | \ No newline at end of file diff --git a/message/docs/models/file.md b/message/docs/models/file.md new file mode 100644 index 000000000..22b3e1947 --- /dev/null +++ b/message/docs/models/file.md @@ -0,0 +1,13 @@ +# File + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `entity_id` | *str* | :heavy_check_mark: | File entity ID | f820ce3b-07b0-45ae-bcc6-babb2f53f79f | +| `cid` | *Optional[str]* | :heavy_minus_sign: | Content ID (for inline) | fb222496-a1a5-4639-94f2-07b5e35e4068 | +| `filename` | *Optional[str]* | :heavy_minus_sign: | File name | Produktinformationen_epilot360_Double_Opt_in.pdf | +| `inline` | *Optional[bool]* | :heavy_minus_sign: | If true then this attachment should not be offered for download (at least not in the main attachments list). The usecase is CID embedded image (aka inline image).
| | +| `is_message_attachment` | *Optional[bool]* | :heavy_minus_sign: | To indicate this file relation is message attachment. If false then this file will not be sent and simply kept as a file relation. | | +| `send_as_link` | *Optional[bool]* | :heavy_minus_sign: | If true then this attachment is sent via link. The link have to be inserted to email body by API caller. In this case, service doesn't process this attachment.
| | \ No newline at end of file diff --git a/message/docs/models/generatesuggestedreplyrequest.md b/message/docs/models/generatesuggestedreplyrequest.md new file mode 100644 index 000000000..9c4fceb6d --- /dev/null +++ b/message/docs/models/generatesuggestedreplyrequest.md @@ -0,0 +1,9 @@ +# GenerateSuggestedReplyRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `message_id` | *str* | :heavy_check_mark: | Message ID | +| `thread_id` | *str* | :heavy_check_mark: | Thread ID | \ No newline at end of file diff --git a/message/docs/models/generatesuggestedreplyresponsebody.md b/message/docs/models/generatesuggestedreplyresponsebody.md new file mode 100644 index 000000000..1df2e4c31 --- /dev/null +++ b/message/docs/models/generatesuggestedreplyresponsebody.md @@ -0,0 +1,14 @@ +# GenerateSuggestedReplyResponseBody + +Success + + +## Fields + +| Field | Type | Required | Description | Example | +| -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| `message_id` | *Optional[str]* | :heavy_minus_sign: | Message ID | c03eb411-9f75-4ff0-9404-5a61c5b8798d | +| `org_id` | *Optional[str]* | :heavy_minus_sign: | Organization ID | 739224 | +| `payload` | [Optional[models.Payload]](../models/payload.md) | :heavy_minus_sign: | N/A | | +| `thread_id` | *Optional[str]* | :heavy_minus_sign: | Thread ID | 07b8b522-a993-4021-8fae-fd19f330ee60 | +| `type` | [Optional[models.GenerateSuggestedReplyType]](../models/generatesuggestedreplytype.md) | :heavy_minus_sign: | Job type | | \ No newline at end of file diff --git a/message/docs/models/generatesuggestedreplystatus.md b/message/docs/models/generatesuggestedreplystatus.md new file mode 100644 index 000000000..f195858bd --- /dev/null +++ b/message/docs/models/generatesuggestedreplystatus.md @@ -0,0 +1,13 @@ +# GenerateSuggestedReplyStatus + +Status of the GenAI job + + +## Values + +| Name | Value | +| ------------- | ------------- | +| `INITIATED` | INITIATED | +| `IN_PROGRESS` | IN_PROGRESS | +| `COMPLETED` | COMPLETED | +| `FAILED` | FAILED | \ No newline at end of file diff --git a/message/docs/models/generatesuggestedreplytype.md b/message/docs/models/generatesuggestedreplytype.md new file mode 100644 index 000000000..8803b4c3b --- /dev/null +++ b/message/docs/models/generatesuggestedreplytype.md @@ -0,0 +1,11 @@ +# GenerateSuggestedReplyType + +Job type + + +## Values + +| Name | Value | +| ------- | ------- | +| `INFO` | INFO | +| `REPLY` | REPLY | \ No newline at end of file diff --git a/message/docs/models/getgenaifeedbackrequest.md b/message/docs/models/getgenaifeedbackrequest.md new file mode 100644 index 000000000..9c600c726 --- /dev/null +++ b/message/docs/models/getgenaifeedbackrequest.md @@ -0,0 +1,9 @@ +# GetGenAIFeedbackRequest + + +## Fields + +| Field | Type | Required | Description | Example | +| ---------------------------- | ---------------------------- | ---------------------------- | ---------------------------- | ---------------------------- | +| `from_` | *Optional[float]* | :heavy_minus_sign: | N/A | 0 | +| `size` | *Optional[float]* | :heavy_minus_sign: | Number of feedback to return | 10 | \ No newline at end of file diff --git a/message/docs/models/getgenaifeedbackresponsebody.md b/message/docs/models/getgenaifeedbackresponsebody.md new file mode 100644 index 000000000..07d4d6e14 --- /dev/null +++ b/message/docs/models/getgenaifeedbackresponsebody.md @@ -0,0 +1,11 @@ +# GetGenAIFeedbackResponseBody + +Success + + +## Fields + +| Field | Type | Required | Description | Example | +| ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | +| `hits` | *Optional[float]* | :heavy_minus_sign: | Total hits | 10 | +| `results` | List[[models.GetGenAIFeedbackResults](../models/getgenaifeedbackresults.md)] | :heavy_minus_sign: | N/A | | \ No newline at end of file diff --git a/message/docs/models/getgenaifeedbackresults.md b/message/docs/models/getgenaifeedbackresults.md new file mode 100644 index 000000000..558f358c2 --- /dev/null +++ b/message/docs/models/getgenaifeedbackresults.md @@ -0,0 +1,16 @@ +# GetGenAIFeedbackResults + + +## Fields + +| Field | Type | Required | Description | Example | +| -------------------------------------------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- | +| `created_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_minus_sign: | Created date | 2021-01-10 09:14:31.99 +0000 UTC | +| `feedback` | *OptionalNullable[str]* | :heavy_minus_sign: | Feedback of the suggested reply | Good summary | +| `last_updated_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_minus_sign: | Updated date | 2021-02-10 09:14:31.99 +0000 UTC | +| `message_id` | *Optional[str]* | :heavy_minus_sign: | Message ID | c03eb411-9f75-4ff0-9404-5a61c5b8798d | +| `org_id` | *Optional[str]* | :heavy_minus_sign: | Organization ID | 739224 | +| `org_name` | *Optional[str]* | :heavy_minus_sign: | Name of the org | Raven GmbH | +| `rating` | *OptionalNullable[str]* | :heavy_minus_sign: | Rating of the suggested reply | positive | +| `thread_id` | *Optional[str]* | :heavy_minus_sign: | Thread ID | 07b8b522-a993-4021-8fae-fd19f330ee60 | +| `type` | [Optional[models.GetGenAIFeedbackType]](../models/getgenaifeedbacktype.md) | :heavy_minus_sign: | Job type | | \ No newline at end of file diff --git a/message/docs/models/getgenaifeedbacktype.md b/message/docs/models/getgenaifeedbacktype.md new file mode 100644 index 000000000..d57b18a66 --- /dev/null +++ b/message/docs/models/getgenaifeedbacktype.md @@ -0,0 +1,11 @@ +# GetGenAIFeedbackType + +Job type + + +## Values + +| Name | Value | +| ------- | ------- | +| `INFO` | INFO | +| `REPLY` | REPLY | \ No newline at end of file diff --git a/message/docs/models/getinfogenaipayload.md b/message/docs/models/getinfogenaipayload.md new file mode 100644 index 000000000..8b53535ba --- /dev/null +++ b/message/docs/models/getinfogenaipayload.md @@ -0,0 +1,18 @@ +# GetInfoGenAIPayload + + +## Fields + +| Field | Type | Required | Description | Example | +| ---------------------------------------------------------------------- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------- | +| `created_at` | *Optional[float]* | :heavy_minus_sign: | Job created date | 1612900000000 | +| `error` | *OptionalNullable[str]* | :heavy_minus_sign: | Error message if the job failed | Failed to generate summary | +| `feedback` | *OptionalNullable[str]* | :heavy_minus_sign: | Feedback of the suggested reply | Good summary | +| `next_steps` | List[*str*] | :heavy_minus_sign: | Recommended next steps | [
"The agent should approve the refund"
] | +| `progress` | *Optional[float]* | :heavy_minus_sign: | Progress of the GenAI job in percentage | 100 | +| `rating` | *OptionalNullable[str]* | :heavy_minus_sign: | Rating of the suggested reply | positive | +| `status` | [Optional[models.GetInfoGenAIStatus]](../models/getinfogenaistatus.md) | :heavy_minus_sign: | Status of the GenAI job | COMPLETED | +| `summary` | List[*str*] | :heavy_minus_sign: | Generated summary | [
"Customer is interested in solar panels"
] | +| `tags` | List[*str*] | :heavy_minus_sign: | Tags | [
"solar",
"quote"
] | +| `topics` | List[*str*] | :heavy_minus_sign: | Topics of the email thread | [
"Product enquiry"
] | +| `updated_at` | *Optional[float]* | :heavy_minus_sign: | Job last updated date | 1612900000000 | \ No newline at end of file diff --git a/message/docs/models/getinfogenairesponsebody.md b/message/docs/models/getinfogenairesponsebody.md new file mode 100644 index 000000000..1abfdba5a --- /dev/null +++ b/message/docs/models/getinfogenairesponsebody.md @@ -0,0 +1,14 @@ +# GetInfoGenAIResponseBody + +Accepted + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | +| `message_id` | *Optional[str]* | :heavy_minus_sign: | Message ID | c03eb411-9f75-4ff0-9404-5a61c5b8798d | +| `org_id` | *Optional[str]* | :heavy_minus_sign: | Organization ID | 739224 | +| `payload` | [Optional[models.GetInfoGenAIPayload]](../models/getinfogenaipayload.md) | :heavy_minus_sign: | N/A | | +| `thread_id` | *Optional[str]* | :heavy_minus_sign: | Thread ID | 07b8b522-a993-4021-8fae-fd19f330ee60 | +| `type` | [Optional[models.GetInfoGenAIType]](../models/getinfogenaitype.md) | :heavy_minus_sign: | Job type | | \ No newline at end of file diff --git a/message/docs/models/getinfogenaistatus.md b/message/docs/models/getinfogenaistatus.md new file mode 100644 index 000000000..44714d3a6 --- /dev/null +++ b/message/docs/models/getinfogenaistatus.md @@ -0,0 +1,13 @@ +# GetInfoGenAIStatus + +Status of the GenAI job + + +## Values + +| Name | Value | +| ------------- | ------------- | +| `INITIATED` | INITIATED | +| `IN_PROGRESS` | IN_PROGRESS | +| `COMPLETED` | COMPLETED | +| `FAILED` | FAILED | \ No newline at end of file diff --git a/message/docs/models/getinfogenaitype.md b/message/docs/models/getinfogenaitype.md new file mode 100644 index 000000000..6182238f4 --- /dev/null +++ b/message/docs/models/getinfogenaitype.md @@ -0,0 +1,11 @@ +# GetInfoGenAIType + +Job type + + +## Values + +| Name | Value | +| ------- | ------- | +| `INFO` | INFO | +| `REPLY` | REPLY | \ No newline at end of file diff --git a/message/docs/models/getinfopayload.md b/message/docs/models/getinfopayload.md new file mode 100644 index 000000000..c38ad64e3 --- /dev/null +++ b/message/docs/models/getinfopayload.md @@ -0,0 +1,18 @@ +# GetInfoPayload + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | +| `created_at` | *Optional[float]* | :heavy_minus_sign: | Job created date | 1612900000000 | +| `error` | *OptionalNullable[str]* | :heavy_minus_sign: | Error message if the job failed | Failed to generate summary | +| `feedback` | *OptionalNullable[str]* | :heavy_minus_sign: | Feedback of the suggested reply | Good summary | +| `next_steps` | List[*str*] | :heavy_minus_sign: | Recommended next steps | [
"The agent should approve the refund"
] | +| `progress` | *Optional[float]* | :heavy_minus_sign: | Progress of the GenAI job in percentage | 100 | +| `rating` | *OptionalNullable[str]* | :heavy_minus_sign: | Rating of the suggested reply | positive | +| `status` | [Optional[models.GetInfoStatus]](../models/getinfostatus.md) | :heavy_minus_sign: | Status of the GenAI job | COMPLETED | +| `summary` | List[*str*] | :heavy_minus_sign: | Generated summary | [
"Customer is interested in solar panels"
] | +| `tags` | List[*str*] | :heavy_minus_sign: | Tags | [
"solar",
"quote"
] | +| `topics` | List[*str*] | :heavy_minus_sign: | Topics of the email thread | [
"Product enquiry"
] | +| `updated_at` | *Optional[float]* | :heavy_minus_sign: | Job last updated date | 1612900000000 | \ No newline at end of file diff --git a/message/docs/models/getinforequest.md b/message/docs/models/getinforequest.md new file mode 100644 index 000000000..e85f1ba11 --- /dev/null +++ b/message/docs/models/getinforequest.md @@ -0,0 +1,9 @@ +# GetInfoRequest + + +## Fields + +| Field | Type | Required | Description | +| --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | +| `thread_id` | *str* | :heavy_check_mark: | Thread ID | +| `message_id` | *Optional[str]* | :heavy_minus_sign: | Message ID, If not passed defaults to latest message ID in the thread | \ No newline at end of file diff --git a/message/docs/models/getinforesponse.md b/message/docs/models/getinforesponse.md new file mode 100644 index 000000000..20ec0d466 --- /dev/null +++ b/message/docs/models/getinforesponse.md @@ -0,0 +1,17 @@ +# GetInfoResponse + + +## Supported Types + +### `models.GetInfoResponseBody` + +```python +value: models.GetInfoResponseBody = /* values here */ +``` + +### `models.GetInfoGenAIResponseBody` + +```python +value: models.GetInfoGenAIResponseBody = /* values here */ +``` + diff --git a/message/docs/models/getinforesponsebody.md b/message/docs/models/getinforesponsebody.md new file mode 100644 index 000000000..478d7322d --- /dev/null +++ b/message/docs/models/getinforesponsebody.md @@ -0,0 +1,14 @@ +# GetInfoResponseBody + +Success + + +## Fields + +| Field | Type | Required | Description | Example | +| -------------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------- | +| `message_id` | *Optional[str]* | :heavy_minus_sign: | Message ID | c03eb411-9f75-4ff0-9404-5a61c5b8798d | +| `org_id` | *Optional[str]* | :heavy_minus_sign: | Organization ID | 739224 | +| `payload` | [Optional[models.GetInfoPayload]](../models/getinfopayload.md) | :heavy_minus_sign: | N/A | | +| `thread_id` | *Optional[str]* | :heavy_minus_sign: | Thread ID | 07b8b522-a993-4021-8fae-fd19f330ee60 | +| `type` | [Optional[models.GetInfoType]](../models/getinfotype.md) | :heavy_minus_sign: | Job type | | \ No newline at end of file diff --git a/message/docs/models/getinfostatus.md b/message/docs/models/getinfostatus.md new file mode 100644 index 000000000..5e257d1c5 --- /dev/null +++ b/message/docs/models/getinfostatus.md @@ -0,0 +1,13 @@ +# GetInfoStatus + +Status of the GenAI job + + +## Values + +| Name | Value | +| ------------- | ------------- | +| `INITIATED` | INITIATED | +| `IN_PROGRESS` | IN_PROGRESS | +| `COMPLETED` | COMPLETED | +| `FAILED` | FAILED | \ No newline at end of file diff --git a/message/docs/models/getinfotype.md b/message/docs/models/getinfotype.md new file mode 100644 index 000000000..73cf6483b --- /dev/null +++ b/message/docs/models/getinfotype.md @@ -0,0 +1,11 @@ +# GetInfoType + +Job type + + +## Values + +| Name | Value | +| ------- | ------- | +| `INFO` | INFO | +| `REPLY` | REPLY | \ No newline at end of file diff --git a/message/docs/models/getmessagerequest.md b/message/docs/models/getmessagerequest.md new file mode 100644 index 000000000..bd2257bbe --- /dev/null +++ b/message/docs/models/getmessagerequest.md @@ -0,0 +1,8 @@ +# GetMessageRequest + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | +| `id` | *str* | :heavy_check_mark: | Message ID | 4d74976d-fb64-47fd-85e2-65eea140f5eb | \ No newline at end of file diff --git a/message/docs/models/getmessageresponse.md b/message/docs/models/getmessageresponse.md new file mode 100644 index 000000000..47958dc7c --- /dev/null +++ b/message/docs/models/getmessageresponse.md @@ -0,0 +1,9 @@ +# GetMessageResponse + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------- | +| `headers` | Dict[str, List[*str*]] | :heavy_check_mark: | N/A | +| `result` | [models.GetMessageResponseBody](../models/getmessageresponsebody.md) | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/message/docs/models/getmessageresponsebody.md b/message/docs/models/getmessageresponsebody.md new file mode 100644 index 000000000..8651e5dc2 --- /dev/null +++ b/message/docs/models/getmessageresponsebody.md @@ -0,0 +1,33 @@ +# GetMessageResponseBody + +Success + + +## Fields + +| Field | Type | Required | Description | Example | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `created_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Created date | 2021-02-09 12:41:43.662 +0000 UTC | +| `id` | *str* | :heavy_check_mark: | Entity ID | 3fa85f64-5717-4562-b3fc-2c963f66afa6 | +| `org` | *str* | :heavy_check_mark: | Ivy Organization ID the entity belongs to | 206801 | +| `schema_` | *str* | :heavy_check_mark: | URL-friendly identifier for the entity schema | message | +| `title` | *str* | :heavy_check_mark: | Entity title | | +| `updated_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Updated date | 2021-02-10 09:14:31.99 +0000 UTC | +| `from_` | [models.Address](../models/address.md) | :heavy_check_mark: | N/A | | +| `subject` | *str* | :heavy_check_mark: | Subject | Request for solar panel price | +| `tags` | List[*str*] | :heavy_minus_sign: | Entity tags | [
"pricing",
"INBOX"
] | +| `bcc` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | Bcc email addresses | | +| `cc` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | Cc email addresses | | +| `file` | [Optional[models.AttachmentsRelation]](../models/attachmentsrelation.md) | :heavy_minus_sign: | Message attachments | | +| `html` | *Optional[str]* | :heavy_minus_sign: | HTML body |
We at ABC GmbH would like to request a price quote for the solar panel.
| +| `in_reply_to` | *Optional[str]* | :heavy_minus_sign: | In-Reply-To header. Value is the `message_id` of parent message.
| | +| `message_id` | *Optional[str]* | :heavy_minus_sign: | Message ID which is from email provider. If you provide `message-id`, API overrides by its own value. | <0102017b97a502f8-a67f01c2-68cc-4928-b91b-45853f34e259-000000@eu-west-1.amazonses.com> | +| `org_read_message` | List[*str*] | :heavy_minus_sign: | Ivy Organization ID of organization read the message. | | +| `references` | *Optional[str]* | :heavy_minus_sign: | References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying.
| <0102017b97a502f8-a67f01c2-68cc-4928-b91b-45853f34e259-000000@eu-west-1.amazonses.com> | +| `reply_to` | [Optional[models.Address]](../models/address.md) | :heavy_minus_sign: | N/A | | +| `send_status` | List[[models.GetMessageSendStatus](../models/getmessagesendstatus.md)] | :heavy_minus_sign: | Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at
| | +| `sender` | *Optional[str]* | :heavy_minus_sign: | Ivy User ID of user sends the message. | 206801 | +| `text` | *Optional[str]* | :heavy_minus_sign: | Text body | We at ABC GmbH would like to request a price quote for the solar panel. | +| `to` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | To email addresses | | +| `type` | [Optional[models.GetMessageType]](../models/getmessagetype.md) | :heavy_minus_sign: | Message type | | +| `user_read_message` | List[*str*] | :heavy_minus_sign: | Ivy User ID of user read the message. | | \ No newline at end of file diff --git a/message/docs/models/getmessagesendstatus.md b/message/docs/models/getmessagesendstatus.md new file mode 100644 index 000000000..8683933c3 --- /dev/null +++ b/message/docs/models/getmessagesendstatus.md @@ -0,0 +1,13 @@ +# GetMessageSendStatus + + +## Values + +| Name | Value | +| ----------- | ----------- | +| `SEND` | SEND | +| `DELIVERY` | DELIVERY | +| `REJECT` | REJECT | +| `COMPLAINT` | COMPLAINT | +| `BOUNCE` | BOUNCE | +| `ERROR` | ERROR | \ No newline at end of file diff --git a/message/docs/models/getmessagetype.md b/message/docs/models/getmessagetype.md new file mode 100644 index 000000000..cec66d0a8 --- /dev/null +++ b/message/docs/models/getmessagetype.md @@ -0,0 +1,11 @@ +# GetMessageType + +Message type + + +## Values + +| Name | Value | +| ---------- | ---------- | +| `SENT` | SENT | +| `RECEIVED` | RECEIVED | \ No newline at end of file diff --git a/message/docs/models/getmessagev2request.md b/message/docs/models/getmessagev2request.md new file mode 100644 index 000000000..4b9c54eb5 --- /dev/null +++ b/message/docs/models/getmessagev2request.md @@ -0,0 +1,8 @@ +# GetMessageV2Request + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | +| `id` | *str* | :heavy_check_mark: | Message ID | 4d74976d-fb64-47fd-85e2-65eea140f5eb | \ No newline at end of file diff --git a/message/docs/models/markreadmessagerequest.md b/message/docs/models/markreadmessagerequest.md new file mode 100644 index 000000000..590ee37ed --- /dev/null +++ b/message/docs/models/markreadmessagerequest.md @@ -0,0 +1,8 @@ +# MarkReadMessageRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `id` | *str* | :heavy_check_mark: | Message ID | \ No newline at end of file diff --git a/message/docs/models/markreadthreadrequest.md b/message/docs/models/markreadthreadrequest.md new file mode 100644 index 000000000..2c5fb5a8b --- /dev/null +++ b/message/docs/models/markreadthreadrequest.md @@ -0,0 +1,8 @@ +# MarkReadThreadRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `id` | *str* | :heavy_check_mark: | Thread ID | \ No newline at end of file diff --git a/message/docs/models/markunreadmessagerequest.md b/message/docs/models/markunreadmessagerequest.md new file mode 100644 index 000000000..a3c9cc306 --- /dev/null +++ b/message/docs/models/markunreadmessagerequest.md @@ -0,0 +1,8 @@ +# MarkUnreadMessageRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `id` | *str* | :heavy_check_mark: | Message ID | \ No newline at end of file diff --git a/message/docs/models/markunreadthreadrequest.md b/message/docs/models/markunreadthreadrequest.md new file mode 100644 index 000000000..8055e7a0d --- /dev/null +++ b/message/docs/models/markunreadthreadrequest.md @@ -0,0 +1,8 @@ +# MarkUnreadThreadRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `id` | *str* | :heavy_check_mark: | Thread ID | \ No newline at end of file diff --git a/message/docs/models/message.md b/message/docs/models/message.md new file mode 100644 index 000000000..6473d266c --- /dev/null +++ b/message/docs/models/message.md @@ -0,0 +1,24 @@ +# Message + + +## Fields + +| Field | Type | Required | Description | Example | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `from_` | [models.Address](../models/address.md) | :heavy_check_mark: | N/A | | +| `subject` | *str* | :heavy_check_mark: | Subject | Request for solar panel price | +| `bcc` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | Bcc email addresses | | +| `cc` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | Cc email addresses | | +| `file` | [Optional[models.AttachmentsRelation]](../models/attachmentsrelation.md) | :heavy_minus_sign: | Message attachments | | +| `html` | *Optional[str]* | :heavy_minus_sign: | HTML body |
We at ABC GmbH would like to request a price quote for the solar panel.
| +| `in_reply_to` | *Optional[str]* | :heavy_minus_sign: | In-Reply-To header. Value is the `message_id` of parent message.
| | +| `message_id` | *Optional[str]* | :heavy_minus_sign: | Message ID which is from email provider. If you provide `message-id`, API overrides by its own value. | <0102017b97a502f8-a67f01c2-68cc-4928-b91b-45853f34e259-000000@eu-west-1.amazonses.com> | +| `org_read_message` | List[*str*] | :heavy_minus_sign: | Ivy Organization ID of organization read the message. | | +| `references` | *Optional[str]* | :heavy_minus_sign: | References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying.
| <0102017b97a502f8-a67f01c2-68cc-4928-b91b-45853f34e259-000000@eu-west-1.amazonses.com> | +| `reply_to` | [Optional[models.Address]](../models/address.md) | :heavy_minus_sign: | N/A | | +| `send_status` | List[[models.MessageSendStatus](../models/messagesendstatus.md)] | :heavy_minus_sign: | Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at
| | +| `sender` | *Optional[str]* | :heavy_minus_sign: | Ivy User ID of user sends the message. | 206801 | +| `text` | *Optional[str]* | :heavy_minus_sign: | Text body | We at ABC GmbH would like to request a price quote for the solar panel. | +| `to` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | To email addresses | | +| `type` | [Optional[models.Type]](../models/type.md) | :heavy_minus_sign: | Message type | | +| `user_read_message` | List[*str*] | :heavy_minus_sign: | Ivy User ID of user read the message. | | \ No newline at end of file diff --git a/message/docs/models/messagerequestparams.md b/message/docs/models/messagerequestparams.md new file mode 100644 index 000000000..d1e973851 --- /dev/null +++ b/message/docs/models/messagerequestparams.md @@ -0,0 +1,19 @@ +# MessageRequestParams + + +## Fields + +| Field | Type | Required | Description | Example | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `from_` | [models.Address](../models/address.md) | :heavy_check_mark: | N/A | | +| `subject` | *str* | :heavy_check_mark: | Subject | Request for solar panel price | +| `__pydantic_extra__` | Dict[str, *Any*] | :heavy_minus_sign: | N/A | | +| `bcc` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | Bcc email addresses | | +| `cc` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | Cc email addresses | | +| `file` | [Optional[models.AttachmentsRelation]](../models/attachmentsrelation.md) | :heavy_minus_sign: | Message attachments | | +| `html` | *Optional[str]* | :heavy_minus_sign: | HTML body |
We at ABC GmbH would like to request a price quote for the solar panel.
| +| `parent_id` | *Optional[str]* | :heavy_minus_sign: | Entity ID of parent message which this message replies to or forwards from. If both `parent_id` and `thread` are provided, `thread` is discarded.
| 44d7a3eb-0cce-4bd3-a7cd-0b3e652de0c2 | +| `reply_to` | [Optional[models.Address]](../models/address.md) | :heavy_minus_sign: | N/A | | +| `text` | *Optional[str]* | :heavy_minus_sign: | Text body. If not provided, text body is converted from HTML body using [html-to-text](https://www.npmjs.com/package/html-to-text) | We at ABC GmbH would like to request a price quote for the solar panel. | +| `thread` | [Optional[models.Thread]](../models/thread.md) | :heavy_minus_sign: | Open new thread when sending the very first message in conversation. Thread should contains context related to all messages in it (eg. topic, brand_id, opportunity_id, assigned_to,...). Thread properties depend on API caller as it's not pre-defined. We do recommend having at least `topic` property for categorizing. `thread` or `parent_id` must be provided either.
| {
"topic": "CUSTOMER_MESSAGE",
"assigned_to": [
"206801",
"200109"
],
"opportunity_id": 829072
} | +| `to` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | To email addresses | | \ No newline at end of file diff --git a/message/docs/models/messagesendstatus.md b/message/docs/models/messagesendstatus.md new file mode 100644 index 000000000..086fcf8d4 --- /dev/null +++ b/message/docs/models/messagesendstatus.md @@ -0,0 +1,13 @@ +# MessageSendStatus + + +## Values + +| Name | Value | +| ----------- | ----------- | +| `SEND` | SEND | +| `DELIVERY` | DELIVERY | +| `REJECT` | REJECT | +| `COMPLAINT` | COMPLAINT | +| `BOUNCE` | BOUNCE | +| `ERROR` | ERROR | \ No newline at end of file diff --git a/message/docs/models/messagev2.md b/message/docs/models/messagev2.md new file mode 100644 index 000000000..7a7cc1d5a --- /dev/null +++ b/message/docs/models/messagev2.md @@ -0,0 +1,33 @@ +# MessageV2 + + +## Fields + +| Field | Type | Required | Description | Example | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `created_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Created date | 2021-02-09 12:41:43.662 +0000 UTC | +| `id` | *str* | :heavy_check_mark: | Entity ID | 3fa85f64-5717-4562-b3fc-2c963f66afa6 | +| `org` | *str* | :heavy_check_mark: | Ivy Organization ID the entity belongs to | 206801 | +| `schema_` | *str* | :heavy_check_mark: | URL-friendly identifier for the entity schema | message | +| `title` | *str* | :heavy_check_mark: | Entity title | | +| `updated_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Updated date | 2021-02-10 09:14:31.99 +0000 UTC | +| `from_` | [models.Address](../models/address.md) | :heavy_check_mark: | N/A | | +| `subject` | *str* | :heavy_check_mark: | Subject | Request for solar panel price | +| `tags` | List[*str*] | :heavy_minus_sign: | Entity tags | [
"pricing",
"INBOX"
] | +| `bcc` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | Bcc email addresses | | +| `cc` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | Cc email addresses | | +| `file` | [Optional[models.AttachmentsRelation]](../models/attachmentsrelation.md) | :heavy_minus_sign: | Message attachments | | +| `html` | *Optional[str]* | :heavy_minus_sign: | HTML body |
We at ABC GmbH would like to request a price quote for the solar panel.
| +| `html_download_url` | *Optional[str]* | :heavy_minus_sign: | HTML body download URL | https://s3.eu-central-1.amazonaws.com/epilot-attachments/3f34ce73-089c-4d45-a5ee-c161234e41c3/3f34ce73-089c-4d45-a5ee-c161234e41c3.html | +| `html_omitted` | *Optional[bool]* | :heavy_minus_sign: | If true then html is not provided and must be downloaded using the html_download_url | | +| `in_reply_to` | *Optional[str]* | :heavy_minus_sign: | In-Reply-To header. Value is the `message_id` of parent message.
| | +| `message_id` | *Optional[str]* | :heavy_minus_sign: | Message ID which is from email provider. If you provide `message-id`, API overrides by its own value. | <0102017b97a502f8-a67f01c2-68cc-4928-b91b-45853f34e259-000000@eu-west-1.amazonses.com> | +| `org_read_message` | List[*str*] | :heavy_minus_sign: | Ivy Organization ID of organization read the message. | | +| `references` | *Optional[str]* | :heavy_minus_sign: | References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying.
| <0102017b97a502f8-a67f01c2-68cc-4928-b91b-45853f34e259-000000@eu-west-1.amazonses.com> | +| `reply_to` | [Optional[models.Address]](../models/address.md) | :heavy_minus_sign: | N/A | | +| `send_status` | List[[models.MessageV2SendStatus](../models/messagev2sendstatus.md)] | :heavy_minus_sign: | Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at
| | +| `sender` | *Optional[str]* | :heavy_minus_sign: | Ivy User ID of user sends the message. | 206801 | +| `text` | *Optional[str]* | :heavy_minus_sign: | Text body | We at ABC GmbH would like to request a price quote for the solar panel. | +| `to` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | To email addresses | | +| `type` | [Optional[models.MessageV2Type]](../models/messagev2type.md) | :heavy_minus_sign: | Message type | | +| `user_read_message` | List[*str*] | :heavy_minus_sign: | Ivy User ID of user read the message. | | \ No newline at end of file diff --git a/message/docs/models/messagev2sendstatus.md b/message/docs/models/messagev2sendstatus.md new file mode 100644 index 000000000..0a58facb9 --- /dev/null +++ b/message/docs/models/messagev2sendstatus.md @@ -0,0 +1,13 @@ +# MessageV2SendStatus + + +## Values + +| Name | Value | +| ----------- | ----------- | +| `SEND` | SEND | +| `DELIVERY` | DELIVERY | +| `REJECT` | REJECT | +| `COMPLAINT` | COMPLAINT | +| `BOUNCE` | BOUNCE | +| `ERROR` | ERROR | \ No newline at end of file diff --git a/message/docs/models/messagev2type.md b/message/docs/models/messagev2type.md new file mode 100644 index 000000000..9446818ab --- /dev/null +++ b/message/docs/models/messagev2type.md @@ -0,0 +1,11 @@ +# MessageV2Type + +Message type + + +## Values + +| Name | Value | +| ---------- | ---------- | +| `SENT` | SENT | +| `RECEIVED` | RECEIVED | \ No newline at end of file diff --git a/message/docs/models/patchinfogenairesponsebody.md b/message/docs/models/patchinfogenairesponsebody.md new file mode 100644 index 000000000..7b685d8f3 --- /dev/null +++ b/message/docs/models/patchinfogenairesponsebody.md @@ -0,0 +1,10 @@ +# PatchInfoGenAIResponseBody + +Internal server error + + +## Fields + +| Field | Type | Required | Description | Example | +| --------------------- | --------------------- | --------------------- | --------------------- | --------------------- | +| `error` | *Optional[str]* | :heavy_minus_sign: | N/A | Internal server error | \ No newline at end of file diff --git a/message/docs/models/patchinfopayload.md b/message/docs/models/patchinfopayload.md new file mode 100644 index 000000000..f1f78fe66 --- /dev/null +++ b/message/docs/models/patchinfopayload.md @@ -0,0 +1,18 @@ +# PatchInfoPayload + + +## Fields + +| Field | Type | Required | Description | Example | +| ---------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------- | +| `created_at` | *Optional[float]* | :heavy_minus_sign: | Job created date | 1612900000000 | +| `error` | *OptionalNullable[str]* | :heavy_minus_sign: | Error message if the job failed | Failed to generate summary | +| `feedback` | *OptionalNullable[str]* | :heavy_minus_sign: | Feedback of the suggested reply | Good summary | +| `next_steps` | List[*str*] | :heavy_minus_sign: | Recommended next steps | [
"The agent should approve the refund"
] | +| `progress` | *Optional[float]* | :heavy_minus_sign: | Progress of the GenAI job in percentage | 100 | +| `rating` | *OptionalNullable[str]* | :heavy_minus_sign: | Rating of the suggested reply | positive | +| `status` | [Optional[models.PatchInfoStatus]](../models/patchinfostatus.md) | :heavy_minus_sign: | Status of the GenAI job | COMPLETED | +| `summary` | List[*str*] | :heavy_minus_sign: | Generated summary | [
"Customer is interested in solar panels"
] | +| `tags` | List[*str*] | :heavy_minus_sign: | Tags | [
"solar",
"quote"
] | +| `topics` | List[*str*] | :heavy_minus_sign: | Topics of the email thread | [
"Product enquiry"
] | +| `updated_at` | *Optional[float]* | :heavy_minus_sign: | Job last updated date | 1612900000000 | \ No newline at end of file diff --git a/message/docs/models/patchinforequest.md b/message/docs/models/patchinforequest.md new file mode 100644 index 000000000..f280dc757 --- /dev/null +++ b/message/docs/models/patchinforequest.md @@ -0,0 +1,10 @@ +# PatchInfoRequest + + +## Fields + +| Field | Type | Required | Description | +| ---------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------- | +| `request_body` | [models.PatchInfoRequestBody](../models/patchinforequestbody.md) | :heavy_check_mark: | Request body for genai info update | +| `message_id` | *str* | :heavy_check_mark: | Message ID | +| `thread_id` | *str* | :heavy_check_mark: | Thread ID | \ No newline at end of file diff --git a/message/docs/models/patchinforequestbody.md b/message/docs/models/patchinforequestbody.md new file mode 100644 index 000000000..e7723e0ef --- /dev/null +++ b/message/docs/models/patchinforequestbody.md @@ -0,0 +1,20 @@ +# PatchInfoRequestBody + +Request body for genai info update + + +## Fields + +| Field | Type | Required | Description | Example | +| ---------------------------------------------- | ---------------------------------------------- | ---------------------------------------------- | ---------------------------------------------- | ---------------------------------------------- | +| `created_at` | *Optional[float]* | :heavy_minus_sign: | Job created date | 1612900000000 | +| `error` | *OptionalNullable[str]* | :heavy_minus_sign: | Error message if the job failed | Failed to generate summary | +| `feedback` | *OptionalNullable[str]* | :heavy_minus_sign: | Feedback of the suggested reply | Good summary | +| `next_steps` | List[*str*] | :heavy_minus_sign: | Recommended next steps | [
"The agent should approve the refund"
] | +| `progress` | *Optional[float]* | :heavy_minus_sign: | Progress of the GenAI job in percentage | 100 | +| `rating` | *OptionalNullable[str]* | :heavy_minus_sign: | Rating of the suggested reply | positive | +| `status` | [Optional[models.Status]](../models/status.md) | :heavy_minus_sign: | Status of the GenAI job | COMPLETED | +| `summary` | List[*str*] | :heavy_minus_sign: | Generated summary | [
"Customer is interested in solar panels"
] | +| `tags` | List[*str*] | :heavy_minus_sign: | Tags | [
"solar",
"quote"
] | +| `topics` | List[*str*] | :heavy_minus_sign: | Topics of the email thread | [
"Product enquiry"
] | +| `updated_at` | *Optional[float]* | :heavy_minus_sign: | Job last updated date | 1612900000000 | \ No newline at end of file diff --git a/message/docs/models/patchinforesponsebody.md b/message/docs/models/patchinforesponsebody.md new file mode 100644 index 000000000..f9dffbb87 --- /dev/null +++ b/message/docs/models/patchinforesponsebody.md @@ -0,0 +1,14 @@ +# PatchInfoResponseBody + +Successfully updated, returns the updated info + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------ | ------------------------------------------------------------------ | ------------------------------------------------------------------ | ------------------------------------------------------------------ | ------------------------------------------------------------------ | +| `message_id` | *Optional[str]* | :heavy_minus_sign: | Message ID | c03eb411-9f75-4ff0-9404-5a61c5b8798d | +| `org_id` | *Optional[str]* | :heavy_minus_sign: | Organization ID | 739224 | +| `payload` | [Optional[models.PatchInfoPayload]](../models/patchinfopayload.md) | :heavy_minus_sign: | N/A | | +| `thread_id` | *Optional[str]* | :heavy_minus_sign: | Thread ID | 07b8b522-a993-4021-8fae-fd19f330ee60 | +| `type` | [Optional[models.PatchInfoType]](../models/patchinfotype.md) | :heavy_minus_sign: | Job type | | \ No newline at end of file diff --git a/message/docs/models/patchinfostatus.md b/message/docs/models/patchinfostatus.md new file mode 100644 index 000000000..392426563 --- /dev/null +++ b/message/docs/models/patchinfostatus.md @@ -0,0 +1,13 @@ +# PatchInfoStatus + +Status of the GenAI job + + +## Values + +| Name | Value | +| ------------- | ------------- | +| `INITIATED` | INITIATED | +| `IN_PROGRESS` | IN_PROGRESS | +| `COMPLETED` | COMPLETED | +| `FAILED` | FAILED | \ No newline at end of file diff --git a/message/docs/models/patchinfotype.md b/message/docs/models/patchinfotype.md new file mode 100644 index 000000000..35d5bb0fd --- /dev/null +++ b/message/docs/models/patchinfotype.md @@ -0,0 +1,11 @@ +# PatchInfoType + +Job type + + +## Values + +| Name | Value | +| ------- | ------- | +| `INFO` | INFO | +| `REPLY` | REPLY | \ No newline at end of file diff --git a/message/docs/models/payload.md b/message/docs/models/payload.md new file mode 100644 index 000000000..48b69406d --- /dev/null +++ b/message/docs/models/payload.md @@ -0,0 +1,15 @@ +# Payload + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | +| `created_at` | *Optional[float]* | :heavy_minus_sign: | Job created date | 1612900000000 | +| `error` | *OptionalNullable[str]* | :heavy_minus_sign: | Error message if the job failed | Failed to generate summary | +| `feedback` | *OptionalNullable[str]* | :heavy_minus_sign: | Feedback of the suggested reply | Good summary | +| `progress` | *Optional[float]* | :heavy_minus_sign: | Progress of the GenAI job in percentage | 100 | +| `rating` | *OptionalNullable[str]* | :heavy_minus_sign: | Rating of the suggested reply | positive | +| `status` | [Optional[models.GenerateSuggestedReplyStatus]](../models/generatesuggestedreplystatus.md) | :heavy_minus_sign: | Status of the GenAI job | COMPLETED | +| `suggested_reply` | *OptionalNullable[str]* | :heavy_minus_sign: | Suggested reply | Thank you for your inquiry. We will get back to you shortly. | +| `updated_at` | *Optional[float]* | :heavy_minus_sign: | Job last updated date | 1612900000000 | \ No newline at end of file diff --git a/message/docs/models/requestbody.md b/message/docs/models/requestbody.md new file mode 100644 index 000000000..9718ffabd --- /dev/null +++ b/message/docs/models/requestbody.md @@ -0,0 +1,10 @@ +# RequestBody + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | ------------------------------------ | +| `entity_id` | *Optional[str]* | :heavy_minus_sign: | Entity ID | 3f34ce73-089c-4d45-a5ee-c161234e41c3 | +| `is_main_entity` | *Optional[bool]* | :heavy_minus_sign: | To indicate this is main entity | true | +| `slug` | *Optional[str]* | :heavy_minus_sign: | Entity slug | contact | \ No newline at end of file diff --git a/message/docs/models/results.md b/message/docs/models/results.md new file mode 100644 index 000000000..5e9391014 --- /dev/null +++ b/message/docs/models/results.md @@ -0,0 +1,22 @@ +# Results + +Thread properties depend on API caller as it's not pre-defined. We do recommend having at least `topic` property for categorizing. + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | +| `created_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Created date | 2021-02-09 12:41:43.662 +0000 UTC | +| `id` | *str* | :heavy_check_mark: | Entity ID | 3fa85f64-5717-4562-b3fc-2c963f66afa6 | +| `org` | *str* | :heavy_check_mark: | Ivy Organization ID the entity belongs to | 206801 | +| `schema_` | *str* | :heavy_check_mark: | URL-friendly identifier for the entity schema | message | +| `title` | *str* | :heavy_check_mark: | Entity title | | +| `updated_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Updated date | 2021-02-10 09:14:31.99 +0000 UTC | +| `topic` | *str* | :heavy_check_mark: | Message topic (e.g. which service sends the message or message category) | CUSTOMER_MESSAGE | +| `tags` | List[*str*] | :heavy_minus_sign: | Entity tags | [
"pricing",
"INBOX"
] | +| `assigned_to` | List[*str*] | :heavy_minus_sign: | Ivy User ID of who the message is assigned to. Default is the user who sends message. | | +| `latest_message` | [Optional[models.Message]](../models/message.md) | :heavy_minus_sign: | N/A | | +| `latest_message_at` | *Optional[str]* | :heavy_minus_sign: | The date of the latest message time in the thread | 2024-02-10 09:14:31.99 +0000 UTC | +| `latest_trash_message` | [Optional[models.Message]](../models/message.md) | :heavy_minus_sign: | N/A | | +| `org_read_message` | List[*str*] | :heavy_minus_sign: | Ivy Organization ID of organization read the message. | | \ No newline at end of file diff --git a/message/docs/models/searchparams.md b/message/docs/models/searchparams.md new file mode 100644 index 000000000..ae5975f78 --- /dev/null +++ b/message/docs/models/searchparams.md @@ -0,0 +1,10 @@ +# SearchParams + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------- | +| `q` | *str* | :heavy_check_mark: | Lucene query syntax supported with ElasticSearch | subject:"Request for solar panel price" AND _tags:INBOX | +| `from_` | *Optional[int]* | :heavy_minus_sign: | N/A | | +| `size` | *Optional[int]* | :heavy_minus_sign: | N/A | | \ No newline at end of file diff --git a/message/docs/models/searchthreadsresponsebody.md b/message/docs/models/searchthreadsresponsebody.md new file mode 100644 index 000000000..c8879c7c2 --- /dev/null +++ b/message/docs/models/searchthreadsresponsebody.md @@ -0,0 +1,11 @@ +# SearchThreadsResponseBody + +Success + + +## Fields + +| Field | Type | Required | Description | Example | +| -------------------------------------------- | -------------------------------------------- | -------------------------------------------- | -------------------------------------------- | -------------------------------------------- | +| `hits` | *float* | :heavy_check_mark: | Total of matched threads | 14 | +| `results` | List[[models.Results](../models/results.md)] | :heavy_check_mark: | Matched threads | | \ No newline at end of file diff --git a/message/docs/models/security.md b/message/docs/models/security.md new file mode 100644 index 000000000..c59fe377f --- /dev/null +++ b/message/docs/models/security.md @@ -0,0 +1,9 @@ +# Security + + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `epilot_auth` | *Optional[str]* | :heavy_minus_sign: | N/A | +| `epilot_org` | *Optional[str]* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/message/docs/models/senddraftresponsebody.md b/message/docs/models/senddraftresponsebody.md new file mode 100644 index 000000000..f48ae7be8 --- /dev/null +++ b/message/docs/models/senddraftresponsebody.md @@ -0,0 +1,33 @@ +# SendDraftResponseBody + +Success + + +## Fields + +| Field | Type | Required | Description | Example | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `created_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Created date | 2021-02-09 12:41:43.662 +0000 UTC | +| `id` | *str* | :heavy_check_mark: | Entity ID | 3fa85f64-5717-4562-b3fc-2c963f66afa6 | +| `org` | *str* | :heavy_check_mark: | Ivy Organization ID the entity belongs to | 206801 | +| `schema_` | *str* | :heavy_check_mark: | URL-friendly identifier for the entity schema | message | +| `title` | *str* | :heavy_check_mark: | Entity title | | +| `updated_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Updated date | 2021-02-10 09:14:31.99 +0000 UTC | +| `from_` | [models.Address](../models/address.md) | :heavy_check_mark: | N/A | | +| `subject` | *str* | :heavy_check_mark: | Subject | Request for solar panel price | +| `tags` | List[*str*] | :heavy_minus_sign: | Entity tags | [
"pricing",
"INBOX"
] | +| `bcc` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | Bcc email addresses | | +| `cc` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | Cc email addresses | | +| `file` | [Optional[models.AttachmentsRelation]](../models/attachmentsrelation.md) | :heavy_minus_sign: | Message attachments | | +| `html` | *Optional[str]* | :heavy_minus_sign: | HTML body |
We at ABC GmbH would like to request a price quote for the solar panel.
| +| `in_reply_to` | *Optional[str]* | :heavy_minus_sign: | In-Reply-To header. Value is the `message_id` of parent message.
| | +| `message_id` | *Optional[str]* | :heavy_minus_sign: | Message ID which is from email provider. If you provide `message-id`, API overrides by its own value. | <0102017b97a502f8-a67f01c2-68cc-4928-b91b-45853f34e259-000000@eu-west-1.amazonses.com> | +| `org_read_message` | List[*str*] | :heavy_minus_sign: | Ivy Organization ID of organization read the message. | | +| `references` | *Optional[str]* | :heavy_minus_sign: | References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying.
| <0102017b97a502f8-a67f01c2-68cc-4928-b91b-45853f34e259-000000@eu-west-1.amazonses.com> | +| `reply_to` | [Optional[models.Address]](../models/address.md) | :heavy_minus_sign: | N/A | | +| `send_status` | List[[models.SendDraftSendStatus](../models/senddraftsendstatus.md)] | :heavy_minus_sign: | Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at
| | +| `sender` | *Optional[str]* | :heavy_minus_sign: | Ivy User ID of user sends the message. | 206801 | +| `text` | *Optional[str]* | :heavy_minus_sign: | Text body | We at ABC GmbH would like to request a price quote for the solar panel. | +| `to` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | To email addresses | | +| `type` | [Optional[models.SendDraftType]](../models/senddrafttype.md) | :heavy_minus_sign: | Message type | | +| `user_read_message` | List[*str*] | :heavy_minus_sign: | Ivy User ID of user read the message. | | \ No newline at end of file diff --git a/message/docs/models/senddraftsendstatus.md b/message/docs/models/senddraftsendstatus.md new file mode 100644 index 000000000..f3ab2f1c2 --- /dev/null +++ b/message/docs/models/senddraftsendstatus.md @@ -0,0 +1,13 @@ +# SendDraftSendStatus + + +## Values + +| Name | Value | +| ----------- | ----------- | +| `SEND` | SEND | +| `DELIVERY` | DELIVERY | +| `REJECT` | REJECT | +| `COMPLAINT` | COMPLAINT | +| `BOUNCE` | BOUNCE | +| `ERROR` | ERROR | \ No newline at end of file diff --git a/message/docs/models/senddrafttype.md b/message/docs/models/senddrafttype.md new file mode 100644 index 000000000..218420528 --- /dev/null +++ b/message/docs/models/senddrafttype.md @@ -0,0 +1,11 @@ +# SendDraftType + +Message type + + +## Values + +| Name | Value | +| ---------- | ---------- | +| `SENT` | SENT | +| `RECEIVED` | RECEIVED | \ No newline at end of file diff --git a/message/docs/models/senderror.md b/message/docs/models/senderror.md new file mode 100644 index 000000000..9fcb6cc19 --- /dev/null +++ b/message/docs/models/senderror.md @@ -0,0 +1,10 @@ +# SendError + +Information about reject, complaint or bounce event. Only available if `send_status` is REJECT, COMPLAINT, BOUNCE or ERROR. JSON object is defined by AWS SES. Reference at + + + +## Fields + +| Field | Type | Required | Description | +| ----------- | ----------- | ----------- | ----------- | \ No newline at end of file diff --git a/message/docs/models/sendmessagerequest.md b/message/docs/models/sendmessagerequest.md new file mode 100644 index 000000000..d0043a14a --- /dev/null +++ b/message/docs/models/sendmessagerequest.md @@ -0,0 +1,9 @@ +# SendMessageRequest + + +## Fields + +| Field | Type | Required | Description | +| ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| `message_request_params` | [Optional[models.MessageRequestParams]](../models/messagerequestparams.md) | :heavy_minus_sign: | N/A | +| `do_not_create_entities` | *Optional[bool]* | :heavy_minus_sign: | When true, this flag lets the caller to send only the message and by-pass creating the thread & message entities. | \ No newline at end of file diff --git a/message/docs/models/sendstatus.md b/message/docs/models/sendstatus.md new file mode 100644 index 000000000..295ecf9f0 --- /dev/null +++ b/message/docs/models/sendstatus.md @@ -0,0 +1,16 @@ +# SendStatus + +Sent message status regarding to this recipient. Reference at + + + +## Values + +| Name | Value | +| ----------- | ----------- | +| `SEND` | SEND | +| `DELIVERY` | DELIVERY | +| `REJECT` | REJECT | +| `COMPLAINT` | COMPLAINT | +| `BOUNCE` | BOUNCE | +| `ERROR` | ERROR | \ No newline at end of file diff --git a/message/docs/models/status.md b/message/docs/models/status.md new file mode 100644 index 000000000..25d2d4e4a --- /dev/null +++ b/message/docs/models/status.md @@ -0,0 +1,13 @@ +# Status + +Status of the GenAI job + + +## Values + +| Name | Value | +| ------------- | ------------- | +| `INITIATED` | INITIATED | +| `IN_PROGRESS` | IN_PROGRESS | +| `COMPLETED` | COMPLETED | +| `FAILED` | FAILED | \ No newline at end of file diff --git a/message/docs/models/thread.md b/message/docs/models/thread.md new file mode 100644 index 000000000..7793d260e --- /dev/null +++ b/message/docs/models/thread.md @@ -0,0 +1,12 @@ +# Thread + +Open new thread when sending the very first message in conversation. Thread should contains context related to all messages in it (eg. topic, brand_id, opportunity_id, assigned_to,...). Thread properties depend on API caller as it's not pre-defined. We do recommend having at least `topic` property for categorizing. `thread` or `parent_id` must be provided either. + + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | +| `topic` | *str* | :heavy_check_mark: | Message topic (e.g. which service sends the message or message category) | +| `assigned_to` | List[*str*] | :heavy_minus_sign: | Ivy User ID of who the message is assigned to. Default is the user who sends message. | \ No newline at end of file diff --git a/message/docs/models/trashmessagerequest.md b/message/docs/models/trashmessagerequest.md new file mode 100644 index 000000000..f31939931 --- /dev/null +++ b/message/docs/models/trashmessagerequest.md @@ -0,0 +1,8 @@ +# TrashMessageRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `id` | *str* | :heavy_check_mark: | Message ID | \ No newline at end of file diff --git a/message/docs/models/trashthreadrequest.md b/message/docs/models/trashthreadrequest.md new file mode 100644 index 000000000..1e25c549e --- /dev/null +++ b/message/docs/models/trashthreadrequest.md @@ -0,0 +1,8 @@ +# TrashThreadRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `id` | *str* | :heavy_check_mark: | Thread ID | \ No newline at end of file diff --git a/message/docs/models/type.md b/message/docs/models/type.md new file mode 100644 index 000000000..a54f2f8e1 --- /dev/null +++ b/message/docs/models/type.md @@ -0,0 +1,11 @@ +# Type + +Message type + + +## Values + +| Name | Value | +| ---------- | ---------- | +| `SENT` | SENT | +| `RECEIVED` | RECEIVED | \ No newline at end of file diff --git a/message/docs/models/untrashmessagerequest.md b/message/docs/models/untrashmessagerequest.md new file mode 100644 index 000000000..f7876c59e --- /dev/null +++ b/message/docs/models/untrashmessagerequest.md @@ -0,0 +1,8 @@ +# UntrashMessageRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `id` | *str* | :heavy_check_mark: | Message ID | \ No newline at end of file diff --git a/message/docs/models/untrashthreadrequest.md b/message/docs/models/untrashthreadrequest.md new file mode 100644 index 000000000..fe60842f3 --- /dev/null +++ b/message/docs/models/untrashthreadrequest.md @@ -0,0 +1,8 @@ +# UntrashThreadRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `id` | *str* | :heavy_check_mark: | Thread ID | \ No newline at end of file diff --git a/message/docs/models/updatemessageresponsebody.md b/message/docs/models/updatemessageresponsebody.md new file mode 100644 index 000000000..26bc38dd3 --- /dev/null +++ b/message/docs/models/updatemessageresponsebody.md @@ -0,0 +1,33 @@ +# UpdateMessageResponseBody + +Success + + +## Fields + +| Field | Type | Required | Description | Example | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `created_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Created date | 2021-02-09 12:41:43.662 +0000 UTC | +| `id` | *str* | :heavy_check_mark: | Entity ID | 3fa85f64-5717-4562-b3fc-2c963f66afa6 | +| `org` | *str* | :heavy_check_mark: | Ivy Organization ID the entity belongs to | 206801 | +| `schema_` | *str* | :heavy_check_mark: | URL-friendly identifier for the entity schema | message | +| `title` | *str* | :heavy_check_mark: | Entity title | | +| `updated_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Updated date | 2021-02-10 09:14:31.99 +0000 UTC | +| `from_` | [models.Address](../models/address.md) | :heavy_check_mark: | N/A | | +| `subject` | *str* | :heavy_check_mark: | Subject | Request for solar panel price | +| `tags` | List[*str*] | :heavy_minus_sign: | Entity tags | [
"pricing",
"INBOX"
] | +| `bcc` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | Bcc email addresses | | +| `cc` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | Cc email addresses | | +| `file` | [Optional[models.AttachmentsRelation]](../models/attachmentsrelation.md) | :heavy_minus_sign: | Message attachments | | +| `html` | *Optional[str]* | :heavy_minus_sign: | HTML body |
We at ABC GmbH would like to request a price quote for the solar panel.
| +| `in_reply_to` | *Optional[str]* | :heavy_minus_sign: | In-Reply-To header. Value is the `message_id` of parent message.
| | +| `message_id` | *Optional[str]* | :heavy_minus_sign: | Message ID which is from email provider. If you provide `message-id`, API overrides by its own value. | <0102017b97a502f8-a67f01c2-68cc-4928-b91b-45853f34e259-000000@eu-west-1.amazonses.com> | +| `org_read_message` | List[*str*] | :heavy_minus_sign: | Ivy Organization ID of organization read the message. | | +| `references` | *Optional[str]* | :heavy_minus_sign: | References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying.
| <0102017b97a502f8-a67f01c2-68cc-4928-b91b-45853f34e259-000000@eu-west-1.amazonses.com> | +| `reply_to` | [Optional[models.Address]](../models/address.md) | :heavy_minus_sign: | N/A | | +| `send_status` | List[[models.UpdateMessageSendStatus](../models/updatemessagesendstatus.md)] | :heavy_minus_sign: | Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at
| | +| `sender` | *Optional[str]* | :heavy_minus_sign: | Ivy User ID of user sends the message. | 206801 | +| `text` | *Optional[str]* | :heavy_minus_sign: | Text body | We at ABC GmbH would like to request a price quote for the solar panel. | +| `to` | List[[models.Address](../models/address.md)] | :heavy_minus_sign: | To email addresses | | +| `type` | [Optional[models.UpdateMessageType]](../models/updatemessagetype.md) | :heavy_minus_sign: | Message type | | +| `user_read_message` | List[*str*] | :heavy_minus_sign: | Ivy User ID of user read the message. | | \ No newline at end of file diff --git a/message/docs/models/updatemessagesendstatus.md b/message/docs/models/updatemessagesendstatus.md new file mode 100644 index 000000000..b95759838 --- /dev/null +++ b/message/docs/models/updatemessagesendstatus.md @@ -0,0 +1,13 @@ +# UpdateMessageSendStatus + + +## Values + +| Name | Value | +| ----------- | ----------- | +| `SEND` | SEND | +| `DELIVERY` | DELIVERY | +| `REJECT` | REJECT | +| `COMPLAINT` | COMPLAINT | +| `BOUNCE` | BOUNCE | +| `ERROR` | ERROR | \ No newline at end of file diff --git a/message/docs/models/updatemessagetype.md b/message/docs/models/updatemessagetype.md new file mode 100644 index 000000000..365a77111 --- /dev/null +++ b/message/docs/models/updatemessagetype.md @@ -0,0 +1,11 @@ +# UpdateMessageType + +Message type + + +## Values + +| Name | Value | +| ---------- | ---------- | +| `SENT` | SENT | +| `RECEIVED` | RECEIVED | \ No newline at end of file diff --git a/message/docs/models/updatethreadresponsebody.md b/message/docs/models/updatethreadresponsebody.md new file mode 100644 index 000000000..ff206cef4 --- /dev/null +++ b/message/docs/models/updatethreadresponsebody.md @@ -0,0 +1,22 @@ +# UpdateThreadResponseBody + +Thread properties depend on API caller as it's not pre-defined. We do recommend having at least `topic` property for categorizing. + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | +| `created_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Created date | 2021-02-09 12:41:43.662 +0000 UTC | +| `id` | *str* | :heavy_check_mark: | Entity ID | 3fa85f64-5717-4562-b3fc-2c963f66afa6 | +| `org` | *str* | :heavy_check_mark: | Ivy Organization ID the entity belongs to | 206801 | +| `schema_` | *str* | :heavy_check_mark: | URL-friendly identifier for the entity schema | message | +| `title` | *str* | :heavy_check_mark: | Entity title | | +| `updated_at` | [date](https://docs.python.org/3/library/datetime.html#date-objects) | :heavy_check_mark: | Updated date | 2021-02-10 09:14:31.99 +0000 UTC | +| `topic` | *str* | :heavy_check_mark: | Message topic (e.g. which service sends the message or message category) | CUSTOMER_MESSAGE | +| `tags` | List[*str*] | :heavy_minus_sign: | Entity tags | [
"pricing",
"INBOX"
] | +| `assigned_to` | List[*str*] | :heavy_minus_sign: | Ivy User ID of who the message is assigned to. Default is the user who sends message. | | +| `latest_message` | [Optional[models.Message]](../models/message.md) | :heavy_minus_sign: | N/A | | +| `latest_message_at` | *Optional[str]* | :heavy_minus_sign: | The date of the latest message time in the thread | 2024-02-10 09:14:31.99 +0000 UTC | +| `latest_trash_message` | [Optional[models.Message]](../models/message.md) | :heavy_minus_sign: | N/A | | +| `org_read_message` | List[*str*] | :heavy_minus_sign: | Ivy Organization ID of organization read the message. | | \ No newline at end of file diff --git a/message/docs/models/utils/retryconfig.md b/message/docs/models/utils/retryconfig.md new file mode 100644 index 000000000..69dd549ec --- /dev/null +++ b/message/docs/models/utils/retryconfig.md @@ -0,0 +1,24 @@ +# RetryConfig + +Allows customizing the default retry configuration. Only usable with methods that mention they support retries. + +## Fields + +| Name | Type | Description | Example | +| ------------------------- | ----------------------------------- | --------------------------------------- | --------- | +| `strategy` | `*str*` | The retry strategy to use. | `backoff` | +| `backoff` | [BackoffStrategy](#backoffstrategy) | Configuration for the backoff strategy. | | +| `retry_connection_errors` | `*bool*` | Whether to retry on connection errors. | `true` | + +## BackoffStrategy + +The backoff strategy allows retrying a request with an exponential backoff between each retry. + +### Fields + +| Name | Type | Description | Example | +| ------------------ | --------- | ----------------------------------------- | -------- | +| `initial_interval` | `*int*` | The initial interval in milliseconds. | `500` | +| `max_interval` | `*int*` | The maximum interval in milliseconds. | `60000` | +| `exponent` | `*float*` | The exponent to use for the backoff. | `1.5` | +| `max_elapsed_time` | `*int*` | The maximum elapsed time in milliseconds. | `300000` | \ No newline at end of file diff --git a/message/docs/sdks/drafts/README.md b/message/docs/sdks/drafts/README.md new file mode 100644 index 000000000..6ff26f102 --- /dev/null +++ b/message/docs/sdks/drafts/README.md @@ -0,0 +1,137 @@ +# Drafts +(*drafts*) + +### Available Operations + +* [create_draft](#create_draft) - createDraft +* [send_draft](#send_draft) - sendDraft + +## create_draft + +Create a new draft + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.drafts.create_draft(request=epilot_message.MessageRequestParams( + from_={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + subject="Request for solar panel price", + bcc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + cc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + file={ + "dollar_relation": [ + { + "entity_id": "f820ce3b-07b0-45ae-bcc6-babb2f53f79f", + "cid": "fb222496-a1a5-4639-94f2-07b5e35e4068", + "filename": "Produktinformationen_epilot360_Double_Opt_in.pdf", + }, + ], + }, + html="
We at ABC GmbH would like to request a price quote for the solar panel.
", + parent_id="44d7a3eb-0cce-4bd3-a7cd-0b3e652de0c2", + reply_to={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + text="We at ABC GmbH would like to request a price quote for the solar panel.", + thread={ + "topic": "CUSTOMER_MESSAGE", + "assigned_to": [ + "206801", + "200109", + ], + }, + to=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], +)) + +if res is not None: + # handle response + pass + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `request` | [models.MessageRequestParams](../../models/messagerequestparams.md) | :heavy_check_mark: | The request object to use for the request. | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + + +### Response + +**[models.CreateDraftResponseBody](../../models/createdraftresponsebody.md)** +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## send_draft + +Send the existing draft to the recipients + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.drafts.send_draft() + +if res is not None: + # handle response + pass + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + + +### Response + +**[models.SendDraftResponseBody](../../models/senddraftresponsebody.md)** +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | diff --git a/message/docs/sdks/epilot/README.md b/message/docs/sdks/epilot/README.md new file mode 100644 index 000000000..d07ff5923 --- /dev/null +++ b/message/docs/sdks/epilot/README.md @@ -0,0 +1,10 @@ +# Epilot SDK + + +## Overview + +Message API: Send and receive email messages via your epilot organization + + +### Available Operations + diff --git a/message/docs/sdks/genai/README.md b/message/docs/sdks/genai/README.md new file mode 100644 index 000000000..540743957 --- /dev/null +++ b/message/docs/sdks/genai/README.md @@ -0,0 +1,204 @@ +# GenAI +(*gen_ai*) + +### Available Operations + +* [generate_suggested_reply](#generate_suggested_reply) - generateSuggestedReply +* [get_gen_ai_feedback](#get_gen_ai_feedback) - getGenAIFeedback +* [get_info](#get_info) - getInfo +* [patch_info](#patch_info) - patchInfo + +## generate_suggested_reply + +Generate suggested reply of the message in the thread + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.gen_ai.generate_suggested_reply(message_id="", thread_id="") + +if res is not None: + # handle response + pass + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `message_id` | *str* | :heavy_check_mark: | Message ID | +| `thread_id` | *str* | :heavy_check_mark: | Thread ID | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + + +### Response + +**[models.GenerateSuggestedReplyResponseBody](../../models/generatesuggestedreplyresponsebody.md)** +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## get_gen_ai_feedback + +Fetch the feedback list for genai + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.gen_ai.get_gen_ai_feedback(from_=0, size=10) + +if res is not None: + # handle response + pass + +``` + +### Parameters + +| Parameter | Type | Required | Description | Example | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `from_` | *Optional[float]* | :heavy_minus_sign: | N/A | 0 | +| `size` | *Optional[float]* | :heavy_minus_sign: | Number of feedback to return | 10 | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | | + + +### Response + +**[models.GetGenAIFeedbackResponseBody](../../models/getgenaifeedbackresponsebody.md)** +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## get_info + +Get generated information of the thread + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.gen_ai.get_info(thread_id="") + +if res is not None: + # handle response + pass + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | +| `thread_id` | *str* | :heavy_check_mark: | Thread ID | +| `message_id` | *Optional[str]* | :heavy_minus_sign: | Message ID, If not passed defaults to latest message ID in the thread | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + + +### Response + +**[models.GetInfoResponse](../../models/getinforesponse.md)** +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## patch_info + +patch generated information of the thread + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.gen_ai.patch_info(message_id="", thread_id="", request_body={ + "created_at": 1612900000000, + "error": "Failed to generate summary", + "feedback": "Good summary", + "next_steps": [ + "The agent should approve the refund", + ], + "progress": 100, + "rating": "positive", + "status": epilot_message.Status.COMPLETED, + "summary": [ + "Customer is interested in solar panels", + ], + "tags": [ + "solar", + "quote", + ], + "topics": [ + "Product enquiry", + ], + "updated_at": 1612900000000, +}) + +if res is not None: + # handle response + pass + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `message_id` | *str* | :heavy_check_mark: | Message ID | +| `thread_id` | *str* | :heavy_check_mark: | Thread ID | +| `request_body` | [models.PatchInfoRequestBody](../../models/patchinforequestbody.md) | :heavy_check_mark: | Request body for genai info update | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + + +### Response + +**[models.PatchInfoResponseBody](../../models/patchinforesponsebody.md)** +### Errors + +| Error Object | Status Code | Content Type | +| --------------------------------- | --------------------------------- | --------------------------------- | +| models.PatchInfoGenAIResponseBody | 500 | application/json | +| models.SDKError | 4xx-5xx | */* | diff --git a/message/docs/sdks/internal/README.md b/message/docs/sdks/internal/README.md new file mode 100644 index 000000000..956219ac9 --- /dev/null +++ b/message/docs/sdks/internal/README.md @@ -0,0 +1,49 @@ +# Internal +(*internal*) + +### Available Operations + +* [get_gen_ai_feedback](#get_gen_ai_feedback) - getGenAIFeedback + +## get_gen_ai_feedback + +Fetch the feedback list for genai + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.internal.get_gen_ai_feedback(from_=0, size=10) + +if res is not None: + # handle response + pass + +``` + +### Parameters + +| Parameter | Type | Required | Description | Example | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `from_` | *Optional[float]* | :heavy_minus_sign: | N/A | 0 | +| `size` | *Optional[float]* | :heavy_minus_sign: | Number of feedback to return | 10 | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | | + + +### Response + +**[models.GetGenAIFeedbackResponseBody](../../models/getgenaifeedbackresponsebody.md)** +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | diff --git a/message/docs/sdks/messages/README.md b/message/docs/sdks/messages/README.md new file mode 100644 index 000000000..5be03f3a7 --- /dev/null +++ b/message/docs/sdks/messages/README.md @@ -0,0 +1,419 @@ +# Messages +(*messages*) + +### Available Operations + +* [delete_message](#delete_message) - deleteMessage +* [get_message](#get_message) - getMessage +* [get_message_v2](#get_message_v2) - getMessageV2 +* [mark_read_message](#mark_read_message) - markReadMessage +* [mark_unread_message](#mark_unread_message) - markUnreadMessage +* [send_message](#send_message) - sendMessage +* [trash_message](#trash_message) - trashMessage +* [untrash_message](#untrash_message) - untrashMessage +* [update_message](#update_message) - updateMessage + +## delete_message + +Immediately and permanently delete a message. This operation cannot be undone. + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +s.messages.delete_message(id="") + +# Use the SDK ... + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Message ID | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## get_message + +Get an email message by id + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.messages.get_message(id="4d74976d-fb64-47fd-85e2-65eea140f5eb") + +if res is not None: + # handle response + pass + +``` + +### Parameters + +| Parameter | Type | Required | Description | Example | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Message ID | 4d74976d-fb64-47fd-85e2-65eea140f5eb | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | | + + +### Response + +**[models.GetMessageResponse](../../models/getmessageresponse.md)** +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## get_message_v2 + +- Fetches message by ID +- If the message html is omitted on the entity, then it keeps the content on the message as a signed url + { + ... + _id: "4d74976d-fb64-47fd-85e2-65eea140f5eb", + _schema: "message", + _org: "org-123", + html_omitted: true, + html_download_url: "https://s3.eu-central-1.amazonaws.com/epilot-attachments/3f34ce73-089c-4d45-a5ee-c161234e41c3/3f34ce73-089c-4d45-a5ee-c161234e41c3.html" + } + + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.messages.get_message_v2(id="4d74976d-fb64-47fd-85e2-65eea140f5eb") + +if res is not None: + # handle response + pass + +``` + +### Parameters + +| Parameter | Type | Required | Description | Example | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Message ID | 4d74976d-fb64-47fd-85e2-65eea140f5eb | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | | + + +### Response + +**[models.MessageV2](../../models/messagev2.md)** +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## mark_read_message + +Mark message as read + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +s.messages.mark_read_message(id="") + +# Use the SDK ... + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Message ID | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## mark_unread_message + +Mark message as unread + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +s.messages.mark_unread_message(id="") + +# Use the SDK ... + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Message ID | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## send_message + +Send an email message + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.messages.send_message(message_request_params=epilot_message.MessageRequestParams( + from_={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + subject="Request for solar panel price", + bcc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + cc=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], + file={ + "dollar_relation": [ + { + "entity_id": "f820ce3b-07b0-45ae-bcc6-babb2f53f79f", + "cid": "fb222496-a1a5-4639-94f2-07b5e35e4068", + "filename": "Produktinformationen_epilot360_Double_Opt_in.pdf", + }, + ], + }, + html="
We at ABC GmbH would like to request a price quote for the solar panel.
", + parent_id="44d7a3eb-0cce-4bd3-a7cd-0b3e652de0c2", + reply_to={ + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + text="We at ABC GmbH would like to request a price quote for the solar panel.", + thread={ + "topic": "CUSTOMER_MESSAGE", + "assigned_to": [ + "206801", + "200109", + ], + }, + to=[ + { + "address": "messaging@epilot.cloud", + "name": "epilot", + }, + ], +)) + +if res is not None: + # handle response + pass + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| `do_not_create_entities` | *Optional[bool]* | :heavy_minus_sign: | When true, this flag lets the caller to send only the message and by-pass creating the thread & message entities. | +| `message_request_params` | [Optional[models.MessageRequestParams]](../../models/messagerequestparams.md) | :heavy_minus_sign: | N/A | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + + +### Response + +**[models.MessageRequestParams](../../models/messagerequestparams.md)** +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## trash_message + +Move a message to the trash + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +s.messages.trash_message(id="") + +# Use the SDK ... + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Message ID | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## untrash_message + +Restore a trashed message + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +s.messages.untrash_message(id="") + +# Use the SDK ... + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Message ID | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## update_message + +Update message metadata + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.messages.update_message() + +if res is not None: + # handle response + pass + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + + +### Response + +**[models.UpdateMessageResponseBody](../../models/updatemessageresponsebody.md)** +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | diff --git a/message/docs/sdks/threads/README.md b/message/docs/sdks/threads/README.md new file mode 100644 index 000000000..4b092bd88 --- /dev/null +++ b/message/docs/sdks/threads/README.md @@ -0,0 +1,370 @@ +# Threads +(*threads*) + +### Available Operations + +* [assign_thread](#assign_thread) - assignThread +* [assign_users](#assign_users) - assignUsers +* [delete_thread](#delete_thread) - deleteThread +* [mark_read_thread](#mark_read_thread) - markReadThread +* [mark_unread_thread](#mark_unread_thread) - markUnreadThread +* [search_threads](#search_threads) - searchThreads +* [trash_thread](#trash_thread) - trashThread +* [untrash_thread](#untrash_thread) - untrashThread +* [update_thread](#update_thread) - updateThread + +## assign_thread + +Assign thread to entities + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +s.threads.assign_thread(id="", request_body=[ + { + "entity_id": "3f34ce73-089c-4d45-a5ee-c161234e41c3", + "is_main_entity": True, + "slug": "contact", + }, +]) + +# Use the SDK ... + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Thread ID | +| `request_body` | List[[models.RequestBody](../../models/requestbody.md)] | :heavy_check_mark: | N/A | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## assign_users + +Assign users to thread for receiving notifications. +The operation replaces all existing assigned users in thread. + + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +s.threads.assign_users(id="", request_body={ + "assigned_to": [ + "206801", + ], +}) + +# Use the SDK ... + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ----------------------------------------------------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Thread ID | +| `request_body` | [models.AssignUsersRequestBody](../../models/assignusersrequestbody.md) | :heavy_check_mark: | N/A | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## delete_thread + +Immediately and permanently delete a thread. This operation cannot be undone. + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +s.threads.delete_thread(id="") + +# Use the SDK ... + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Thread ID | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## mark_read_thread + +Mark thread as read + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +s.threads.mark_read_thread(id="") + +# Use the SDK ... + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Thread ID | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## mark_unread_thread + +Mark thread as unread + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +s.threads.mark_unread_thread(id="") + +# Use the SDK ... + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Thread ID | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## search_threads + +Search for threads of email messages. + +Messages with no replies yet are treated as threads with single message. + +Lucene syntax supported. + + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.threads.search_threads(request={ + "q": "subject:\"Request for solar panel price\" AND _tags:INBOX", +}) + +if res is not None: + # handle response + pass + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `request` | [models.SearchParams](../../models/searchparams.md) | :heavy_check_mark: | The request object to use for the request. | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + + +### Response + +**[models.SearchThreadsResponseBody](../../models/searchthreadsresponsebody.md)** +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## trash_thread + +Move a thread to trash + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +s.threads.trash_thread(id="") + +# Use the SDK ... + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Thread ID | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## untrash_thread + +Restore a trashed thread + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +s.threads.untrash_thread(id="") + +# Use the SDK ... + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Thread ID | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | + +## update_thread + +Modify thread metadata + +### Example Usage + +```python +import epilot_message +from epilot_message import Epilot + +s = Epilot( + security=epilot_message.Security( + epilot_auth="", + ), +) + + +res = s.threads.update_thread() + +if res is not None: + # handle response + pass + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + + +### Response + +**[models.UpdateThreadResponseBody](../../models/updatethreadresponsebody.md)** +### Errors + +| Error Object | Status Code | Content Type | +| --------------- | --------------- | --------------- | +| models.SDKError | 4xx-5xx | */* | diff --git a/message/gen.yaml b/message/gen.yaml index 5c31381b3..c50f0765d 100644 --- a/message/gen.yaml +++ b/message/gen.yaml @@ -1,16 +1,41 @@ -configVersion: 1.0.0 -management: - docChecksum: 007d70cb5b2af152bc8b6492cdc0171c - docVersion: 1.0.0 - speakeasyVersion: 1.19.2 - generationVersion: 2.16.5 +configVersion: 2.0.0 generation: - telemetryEnabled: false sdkClassName: epilot + usageSnippets: + optionalPropertyRendering: withExample + fixes: + nameResolutionDec2023: false + parameterOrderingFeb2024: false + requestResponseComponentNamesFeb2024: false + auth: + oAuth2ClientCredentialsEnabled: false sdkFlattening: true - singleTagPerOp: false + telemetryEnabled: false python: - version: 1.2.2 + version: 1.3.0 + additionalDependencies: + dev: {} + main: {} author: epilot + authors: + - Speakeasy + clientServerStatusCodesAsErrors: true description: Python Client SDK for Epilot + enumFormat: enum + flattenGlobalSecurity: true + flattenRequests: false + imports: + option: openapi + paths: + callbacks: "" + errors: "" + operations: "" + shared: "" + webhooks: "" + inputModelSuffix: input + maxMethodParams: 4 + methodArguments: infer-optional-args + outputModelSuffix: output packageName: epilot-message + responseFormat: flat + templateVersion: v2 diff --git a/message/poetry.toml b/message/poetry.toml new file mode 100644 index 000000000..ab1033bd3 --- /dev/null +++ b/message/poetry.toml @@ -0,0 +1,2 @@ +[virtualenvs] +in-project = true diff --git a/message/py.typed b/message/py.typed new file mode 100644 index 000000000..3e38f1a92 --- /dev/null +++ b/message/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561. The package enables type hints. diff --git a/message/pylintrc b/message/pylintrc old mode 100755 new mode 100644 index 8f07ddd14..705b048fc --- a/message/pylintrc +++ b/message/pylintrc @@ -59,10 +59,11 @@ ignore-paths= # Emacs file locks ignore-patterns=^\.# -# List of module names for which member attributes should not be checked -# (useful for modules/projects where namespaces are manipulated during runtime -# and thus existing member attributes cannot be deduced by static analysis). It -# supports qualified module names, as well as Unix pattern matching. +# List of module names for which member attributes should not be checked and +# will not be imported (useful for modules/projects where namespaces are +# manipulated during runtime and thus existing member attributes cannot be +# deduced by static analysis). It supports qualified module names, as well as +# Unix pattern matching. ignored-modules= # Python code to execute, usually for sys.path manipulation such as @@ -88,11 +89,17 @@ persistent=yes # Minimum Python version to use for version dependent checks. Will default to # the version used to run pylint. -py-version=3.9 +py-version=3.8 # Discover python modules and packages in the file system subtree. recursive=no +# Add paths to the list of the source roots. Supports globbing patterns. The +# source root is an absolute path or a path relative to the current working +# directory used to determine a package namespace for modules located under the +# source root. +source-roots=src + # When enabled, pylint would attempt to guess common misconfiguration and emit # user-friendly hints instead of false-positive error messages. suggestion-mode=yes @@ -116,20 +123,15 @@ argument-naming-style=snake_case #argument-rgx= # Naming style matching correct attribute names. -attr-naming-style=snake_case +#attr-naming-style=snake_case # Regular expression matching correct attribute names. Overrides attr-naming- # style. If left empty, attribute names will be checked with the set naming # style. -#attr-rgx= +attr-rgx=[^\W\d][^\W]*|__.*__$ # Bad variable names which should always be refused, separated by a comma. -bad-names=foo, - bar, - baz, - toto, - tutu, - tata +bad-names= # Bad variable names regexes, separated by a comma. If names match any regex, # they will always be refused @@ -185,6 +187,7 @@ good-names=i, ex, Run, _, + e, cc, to, id, @@ -232,6 +235,10 @@ no-docstring-rgx=^_ # These decorators are taken in consideration only for invalid-name. property-classes=abc.abstractproperty +# Regular expression matching correct type alias names. If left empty, type +# alias names will be checked with the set naming style. +typealias-rgx=.* + # Regular expression matching correct type variable names. If left empty, type # variable names will be checked with the set naming style. #typevar-rgx= @@ -254,15 +261,12 @@ check-protected-access-in-special-methods=no defining-attr-methods=__init__, __new__, setUp, + asyncSetUp, __post_init__ # List of member names, which should be excluded from the protected access # warning. -exclude-protected=_asdict, - _fields, - _replace, - _source, - _make +exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit # List of valid names for the first argument in a class method. valid-classmethod-first-arg=cls @@ -425,6 +429,8 @@ disable=raw-checker-failed, suppressed-message, useless-suppression, deprecated-pragma, + use-implicit-booleaness-not-comparison-to-string, + use-implicit-booleaness-not-comparison-to-zero, use-symbolic-message-instead, trailing-whitespace, line-too-long, @@ -437,18 +443,27 @@ disable=raw-checker-failed, broad-exception-raised, too-few-public-methods, too-many-branches, - chained-comparison, duplicate-code, trailing-newlines, too-many-public-methods, too-many-locals, - too-many-lines + too-many-lines, + using-constant-test, + too-many-statements, + cyclic-import, + too-many-nested-blocks, + too-many-boolean-expressions, + no-else-raise, + bare-except, + broad-exception-caught, + fixme, + relative-beyond-top-level # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option # multiple time (only on the command line, not in the configuration file where # it should appear only once). See also the "--disable" option for examples. -enable=c-extension-no-member +enable= [METHOD_ARGS] @@ -494,8 +509,9 @@ evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor # used to format the message information. See doc for all details. msg-template= -# Set the output format. Available formats are text, parseable, colorized, json -# and msvs (visual studio). You can also give a reporter class, e.g. +# Set the output format. Available formats are: text, parseable, colorized, +# json2 (improved json format), json (old json format) and msvs (visual +# studio). You can also give a reporter class, e.g. # mypackage.mymodule.MyReporterClass. #output-format= @@ -529,8 +545,8 @@ min-similarity-lines=4 # Limits count of emitted suggestions for spelling mistakes. max-spelling-suggestions=4 -# Spelling dictionary name. Available dictionaries: none. To make it work, -# install the 'python-enchant' package. +# Spelling dictionary name. No available dictionaries : You need to install +# both the python package and the system dependency for enchant to work. spelling-dict= # List of comma separated words that should be considered directives if they @@ -623,7 +639,7 @@ additional-builtins= allow-global-unused-variables=yes # List of names allowed to shadow builtins -allowed-redefined-builtins= +allowed-redefined-builtins=id,object # List of strings which can identify a callback function by name. A callback # name must start or end with one of those strings. diff --git a/message/pyproject.toml b/message/pyproject.toml new file mode 100644 index 000000000..57967acf7 --- /dev/null +++ b/message/pyproject.toml @@ -0,0 +1,55 @@ +[tool.poetry] +name = "epilot-message" +version = "1.3.0" +description = "Python Client SDK for Epilot" +authors = ["Speakeasy",] +readme = "README.md" +repository = "https://github.com/epilot-dev/sdk-python.git" +packages = [ + { include = "epilot_message", from = "src" } +] +include = ["py.typed", "src/epilot_message/py.typed"] + +[tool.setuptools.package-data] +"*" = ["py.typed", "src/epilot_message/py.typed"] + +[virtualenvs] +in-project = true + +[tool.poetry.dependencies] +python = "^3.8" +httpx = "^0.27.0" +jsonpath-python = "^1.0.6" +pydantic = "~2.8.2" +python-dateutil = "^2.9.0.post0" +typing-inspect = "^0.9.0" + +[tool.poetry.group.dev.dependencies] +mypy = "==1.10.1" +pylint = "==3.2.3" +pyright = "==1.1.374" +types-python-dateutil = "^2.9.0.20240316" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +[tool.pytest.ini_options] +pythonpath = ["src"] + +[tool.mypy] +disable_error_code = "misc" + +[[tool.mypy.overrides]] +module = "typing_inspect" +ignore_missing_imports = true + +[[tool.mypy.overrides]] +module = "jsonpath" +ignore_missing_imports = true + +[tool.pyright] +venvPath = "." +venv = ".venv" + + diff --git a/message/scripts/compile.sh b/message/scripts/compile.sh new file mode 100755 index 000000000..aa49772e2 --- /dev/null +++ b/message/scripts/compile.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash + +set -o pipefail # Ensure pipeline failures are propagated + +# Use temporary files to store outputs and exit statuses +declare -A output_files +declare -A status_files + +# Function to run a command with temporary output and status files +run_command() { + local cmd="$1" + local key="$2" + local output_file="$3" + local status_file="$4" + + # Run the command and store output and exit status + { + eval "$cmd" + echo $? > "$status_file" + } &> "$output_file" & +} + +# Create temporary files for outputs and statuses +for cmd in compileall pylint mypy pyright; do + output_files[$cmd]=$(mktemp) + status_files[$cmd]=$(mktemp) +done + +# Collect PIDs for background processes +declare -a pids + +# Run commands in parallel using temporary files +echo "Running python -m compileall" +run_command 'poetry run python -m compileall -q . && echo "Success"' 'compileall' "${output_files[compileall]}" "${status_files[compileall]}" +pids+=($!) + +echo "Running pylint" +run_command 'poetry run pylint src' 'pylint' "${output_files[pylint]}" "${status_files[pylint]}" +pids+=($!) + +echo "Running mypy" +run_command 'poetry run mypy src' 'mypy' "${output_files[mypy]}" "${status_files[mypy]}" +pids+=($!) + +echo "Running pyright (optional)" +run_command 'if command -v pyright > /dev/null 2>&1; then pyright src; else echo "pyright not found, skipping"; fi' 'pyright' "${output_files[pyright]}" "${status_files[pyright]}" +pids+=($!) + +# Wait for all processes to complete +echo "Waiting for processes to complete" +for pid in "${pids[@]}"; do + wait "$pid" +done + +# Print output sequentially and check for failures +failed=false +for key in "${!output_files[@]}"; do + echo "--- Output from Command: $key ---" + echo + cat "${output_files[$key]}" + echo # Empty line for separation + echo "--- End of Output from Command: $key ---" + echo + + exit_status=$(cat "${status_files[$key]}") + if [ "$exit_status" -ne 0 ]; then + echo "Command $key failed with exit status $exit_status" >&2 + failed=true + fi +done + +# Clean up temporary files +for tmp_file in "${output_files[@]}" "${status_files[@]}"; do + rm -f "$tmp_file" +done + +if $failed; then + echo "One or more commands failed." >&2 + exit 1 +else + echo "All commands completed successfully." + exit 0 +fi diff --git a/message/scripts/publish.sh b/message/scripts/publish.sh new file mode 100755 index 000000000..1ee7194cd --- /dev/null +++ b/message/scripts/publish.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +export POETRY_PYPI_TOKEN_PYPI=${PYPI_TOKEN} + +poetry publish --build --skip-existing diff --git a/message/setup.py b/message/setup.py deleted file mode 100755 index 4bdff85a9..000000000 --- a/message/setup.py +++ /dev/null @@ -1,39 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -import setuptools - -try: - with open("README.md", "r") as fh: - long_description = fh.read() -except FileNotFoundError: - long_description = "" - -setuptools.setup( - name="epilot-message", - version="1.2.2", - author="epilot", - description="Python Client SDK for Epilot", - long_description=long_description, - long_description_content_type="text/markdown", - packages=setuptools.find_packages(where="src"), - install_requires=[ - "certifi==2022.12.07", - "charset-normalizer==2.1.1", - "dataclasses-json-speakeasy==0.5.8", - "idna==3.3", - "marshmallow==3.17.1", - "marshmallow-enum==1.5.1", - "mypy-extensions==0.4.3", - "packaging==21.3", - "pyparsing==3.0.9", - "python-dateutil==2.8.2", - "requests==2.28.1", - "six==1.16.0", - "typing-inspect==0.8.0", - "typing_extensions==4.3.0", - "urllib3==1.26.12", - "pylint==2.16.2", - ], - package_dir={'': 'src'}, - python_requires='>=3.9' -) diff --git a/message/src/epilot/__init__.py b/message/src/epilot/__init__.py deleted file mode 100755 index b9e232018..000000000 --- a/message/src/epilot/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from .sdk import * diff --git a/message/src/epilot/drafts.py b/message/src/epilot/drafts.py deleted file mode 100755 index 4d0bdb57a..000000000 --- a/message/src/epilot/drafts.py +++ /dev/null @@ -1,78 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -import requests as requests_http -from . import utils -from epilot.models import operations -from typing import Any, Optional - -class Drafts: - _client: requests_http.Session - _security_client: requests_http.Session - _server_url: str - _language: str - _sdk_version: str - _gen_version: str - - def __init__(self, client: requests_http.Session, security_client: requests_http.Session, server_url: str, language: str, sdk_version: str, gen_version: str) -> None: - self._client = client - self._security_client = security_client - self._server_url = server_url - self._language = language - self._sdk_version = sdk_version - self._gen_version = gen_version - - def create_draft(self, request: Any) -> operations.CreateDraftResponse: - r"""createDraft - Create a new draft - """ - base_url = self._server_url - - url = base_url.removesuffix('/') + '/v1/message/drafts' - - headers = {} - req_content_type, data, form = utils.serialize_request_body(request, "request", 'json') - if req_content_type not in ('multipart/form-data', 'multipart/mixed'): - headers['content-type'] = req_content_type - - client = self._security_client - - http_res = client.request('POST', url, data=data, files=form, headers=headers) - content_type = http_res.headers.get('Content-Type') - - res = operations.CreateDraftResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code == 201: - if utils.match_content_type(content_type, 'application/json'): - out = utils.unmarshal_json(http_res.text, Optional[operations.CreateDraft201ApplicationJSON]) - res.create_draft_201_application_json_object = out - elif http_res.status_code == 403: - pass - - return res - - def send_draft(self) -> operations.SendDraftResponse: - r"""sendDraft - Send the existing draft to the recipients - """ - base_url = self._server_url - - url = base_url.removesuffix('/') + '/v1/message/drafts:send' - - - client = self._security_client - - http_res = client.request('POST', url) - content_type = http_res.headers.get('Content-Type') - - res = operations.SendDraftResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code == 201: - if utils.match_content_type(content_type, 'application/json'): - out = utils.unmarshal_json(http_res.text, Optional[operations.SendDraft201ApplicationJSON]) - res.send_draft_201_application_json_object = out - elif http_res.status_code == 403: - pass - - return res - - \ No newline at end of file diff --git a/message/src/epilot/messages.py b/message/src/epilot/messages.py deleted file mode 100755 index 79d8a2dd8..000000000 --- a/message/src/epilot/messages.py +++ /dev/null @@ -1,208 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -import requests as requests_http -from . import utils -from epilot.models import operations -from typing import Any, Optional - -class Messages: - _client: requests_http.Session - _security_client: requests_http.Session - _server_url: str - _language: str - _sdk_version: str - _gen_version: str - - def __init__(self, client: requests_http.Session, security_client: requests_http.Session, server_url: str, language: str, sdk_version: str, gen_version: str) -> None: - self._client = client - self._security_client = security_client - self._server_url = server_url - self._language = language - self._sdk_version = sdk_version - self._gen_version = gen_version - - def delete_message(self, request: operations.DeleteMessageRequest) -> operations.DeleteMessageResponse: - r"""deleteMessage - Immediately and permanently delete a message. This operation cannot be undone. - """ - base_url = self._server_url - - url = utils.generate_url(operations.DeleteMessageRequest, base_url, '/v1/message/messages/{id}', request) - - - client = self._security_client - - http_res = client.request('DELETE', url) - content_type = http_res.headers.get('Content-Type') - - res = operations.DeleteMessageResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code in [204, 403]: - pass - - return res - - def get_message(self, request: operations.GetMessageRequest) -> operations.GetMessageResponse: - r"""getMessage - Get an email message by id - """ - base_url = self._server_url - - url = utils.generate_url(operations.GetMessageRequest, base_url, '/v1/message/messages/{id}', request) - - - client = self._security_client - - http_res = client.request('GET', url) - content_type = http_res.headers.get('Content-Type') - - res = operations.GetMessageResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code == 201: - if utils.match_content_type(content_type, 'application/json'): - out = utils.unmarshal_json(http_res.text, Optional[operations.GetMessage201ApplicationJSON]) - res.get_message_201_application_json_object = out - elif http_res.status_code == 403: - pass - - return res - - def mark_read_message(self, request: operations.MarkReadMessageRequest) -> operations.MarkReadMessageResponse: - r"""markReadMessage - Mark message as read - """ - base_url = self._server_url - - url = utils.generate_url(operations.MarkReadMessageRequest, base_url, '/v1/message/messages/{id}/read', request) - - - client = self._security_client - - http_res = client.request('POST', url) - content_type = http_res.headers.get('Content-Type') - - res = operations.MarkReadMessageResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code in [204, 403]: - pass - - return res - - def mark_unread_message(self, request: operations.MarkUnreadMessageRequest) -> operations.MarkUnreadMessageResponse: - r"""markUnreadMessage - Mark message as unread - """ - base_url = self._server_url - - url = utils.generate_url(operations.MarkUnreadMessageRequest, base_url, '/v1/message/messages/{id}/unread', request) - - - client = self._security_client - - http_res = client.request('POST', url) - content_type = http_res.headers.get('Content-Type') - - res = operations.MarkUnreadMessageResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code in [204, 403]: - pass - - return res - - def send_message(self, request: Any) -> operations.SendMessageResponse: - r"""sendMessage - Send an email message - """ - base_url = self._server_url - - url = base_url.removesuffix('/') + '/v1/message/messages' - - headers = {} - req_content_type, data, form = utils.serialize_request_body(request, "request", 'json') - if req_content_type not in ('multipart/form-data', 'multipart/mixed'): - headers['content-type'] = req_content_type - - client = self._security_client - - http_res = client.request('POST', url, data=data, files=form, headers=headers) - content_type = http_res.headers.get('Content-Type') - - res = operations.SendMessageResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code == 201: - if utils.match_content_type(content_type, 'application/json'): - out = utils.unmarshal_json(http_res.text, Optional[operations.SendMessage201ApplicationJSON]) - res.send_message_201_application_json_object = out - elif http_res.status_code == 403: - pass - - return res - - def trash_message(self, request: operations.TrashMessageRequest) -> operations.TrashMessageResponse: - r"""trashMessage - Move a message to the trash - """ - base_url = self._server_url - - url = utils.generate_url(operations.TrashMessageRequest, base_url, '/v1/message/messages/{id}/trash', request) - - - client = self._security_client - - http_res = client.request('POST', url) - content_type = http_res.headers.get('Content-Type') - - res = operations.TrashMessageResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code in [204, 403]: - pass - - return res - - def untrash_message(self, request: operations.UntrashMessageRequest) -> operations.UntrashMessageResponse: - r"""untrashMessage - Restore a trashed message - """ - base_url = self._server_url - - url = utils.generate_url(operations.UntrashMessageRequest, base_url, '/v1/message/messages/{id}/untrash', request) - - - client = self._security_client - - http_res = client.request('POST', url) - content_type = http_res.headers.get('Content-Type') - - res = operations.UntrashMessageResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code in [204, 403]: - pass - - return res - - def update_message(self) -> operations.UpdateMessageResponse: - r"""updateMessage - Update message metadata - """ - base_url = self._server_url - - url = base_url.removesuffix('/') + '/v1/message/messages' - - - client = self._security_client - - http_res = client.request('PUT', url) - content_type = http_res.headers.get('Content-Type') - - res = operations.UpdateMessageResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code == 201: - if utils.match_content_type(content_type, 'application/json'): - out = utils.unmarshal_json(http_res.text, Optional[operations.UpdateMessage201ApplicationJSON]) - res.update_message_201_application_json_object = out - elif http_res.status_code == 403: - pass - - return res - - \ No newline at end of file diff --git a/message/src/epilot/models/__init__.py b/message/src/epilot/models/__init__.py deleted file mode 100755 index 889f8adcf..000000000 --- a/message/src/epilot/models/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - diff --git a/message/src/epilot/models/operations/__init__.py b/message/src/epilot/models/operations/__init__.py deleted file mode 100755 index 7f5afbc54..000000000 --- a/message/src/epilot/models/operations/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from .assignthread import * -from .createdraft import * -from .deletemessage import * -from .deletethread import * -from .getmessage import * -from .markreadmessage import * -from .markreadthread import * -from .markunreadmessage import * -from .markunreadthread import * -from .searchthreads import * -from .senddraft import * -from .sendmessage import * -from .trashmessage import * -from .trashthread import * -from .untrashmessage import * -from .untrashthread import * -from .updatemessage import * -from .updatethread import * - -__all__ = ["AssignThreadRequest","AssignThreadRequestBody","AssignThreadResponse","CreateDraft201ApplicationJSON","CreateDraft201ApplicationJSONSendStatusEnum","CreateDraft201ApplicationJSONTypeEnum","CreateDraftResponse","DeleteMessageRequest","DeleteMessageResponse","DeleteThreadRequest","DeleteThreadResponse","GetMessage201ApplicationJSON","GetMessage201ApplicationJSONSendStatusEnum","GetMessage201ApplicationJSONTypeEnum","GetMessageRequest","GetMessageResponse","MarkReadMessageRequest","MarkReadMessageResponse","MarkReadThreadRequest","MarkReadThreadResponse","MarkUnreadMessageRequest","MarkUnreadMessageResponse","MarkUnreadThreadRequest","MarkUnreadThreadResponse","SearchThreads200ApplicationJSON","SearchThreads200ApplicationJSONResults","SearchThreadsResponse","SendDraft201ApplicationJSON","SendDraft201ApplicationJSONSendStatusEnum","SendDraft201ApplicationJSONTypeEnum","SendDraftResponse","SendMessage201ApplicationJSON","SendMessage201ApplicationJSONSendStatusEnum","SendMessage201ApplicationJSONTypeEnum","SendMessageResponse","TrashMessageRequest","TrashMessageResponse","TrashThreadRequest","TrashThreadResponse","UntrashMessageRequest","UntrashMessageResponse","UntrashThreadRequest","UntrashThreadResponse","UpdateMessage201ApplicationJSON","UpdateMessage201ApplicationJSONSendStatusEnum","UpdateMessage201ApplicationJSONTypeEnum","UpdateMessageResponse","UpdateThread201ApplicationJSON","UpdateThreadResponse"] diff --git a/message/src/epilot/models/operations/assignthread.py b/message/src/epilot/models/operations/assignthread.py deleted file mode 100755 index 30ad5de3b..000000000 --- a/message/src/epilot/models/operations/assignthread.py +++ /dev/null @@ -1,37 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import requests as requests_http -from dataclasses_json import Undefined, dataclass_json -from epilot import utils -from typing import Optional - - -@dataclass_json(undefined=Undefined.EXCLUDE) -@dataclasses.dataclass -class AssignThreadRequestBody: - - entity_id: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('entity_id'), 'exclude': lambda f: f is None }}) - r"""Entity ID""" - is_main_entity: Optional[bool] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('is_main_entity'), 'exclude': lambda f: f is None }}) - r"""To indicate this is main entity""" - slug: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('slug'), 'exclude': lambda f: f is None }}) - r"""Entity slug""" - - -@dataclasses.dataclass -class AssignThreadRequest: - - id: str = dataclasses.field(metadata={'path_param': { 'field_name': 'id', 'style': 'simple', 'explode': False }}) - r"""Thread ID""" - request_body: list[AssignThreadRequestBody] = dataclasses.field(metadata={'request': { 'media_type': 'application/json' }}) - - -@dataclasses.dataclass -class AssignThreadResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - \ No newline at end of file diff --git a/message/src/epilot/models/operations/createdraft.py b/message/src/epilot/models/operations/createdraft.py deleted file mode 100755 index 31cfcf4f6..000000000 --- a/message/src/epilot/models/operations/createdraft.py +++ /dev/null @@ -1,100 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import dateutil.parser -import requests as requests_http -from ..shared import address as shared_address -from ..shared import attachmentsrelation as shared_attachmentsrelation -from dataclasses_json import Undefined, dataclass_json -from datetime import datetime -from enum import Enum -from epilot import utils -from marshmallow import fields -from typing import Optional - -class CreateDraft201ApplicationJSONSendStatusEnum(str, Enum): - SEND = "SEND" - DELIVERY = "DELIVERY" - REJECT = "REJECT" - COMPLAINT = "COMPLAINT" - BOUNCE = "BOUNCE" - ERROR = "ERROR" - -class CreateDraft201ApplicationJSONTypeEnum(str, Enum): - r"""Message type""" - SENT = "SENT" - RECEIVED = "RECEIVED" - - -@dataclass_json(undefined=Undefined.EXCLUDE) -@dataclasses.dataclass -class CreateDraft201ApplicationJSON: - r"""Success""" - - created_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_created_at'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) - r"""Created date""" - id: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_id') }}) - r"""Entity ID""" - org: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_org') }}) - r"""Ivy Organization ID the entity belongs to""" - schema: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_schema') }}) - r"""URL-friendly identifier for the entity schema""" - title: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_title') }}) - r"""Entity title""" - updated_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_updated_at'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) - r"""Updated date""" - from_: shared_address.Address = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('from') }}) - subject: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('subject') }}) - r"""Subject""" - tags: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_tags'), 'exclude': lambda f: f is None }}) - r"""Entity tags""" - bcc: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('bcc'), 'exclude': lambda f: f is None }}) - r"""Bcc email addresses""" - cc: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('cc'), 'exclude': lambda f: f is None }}) - r"""Cc email addresses""" - file: Optional[shared_attachmentsrelation.AttachmentsRelation] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('file'), 'exclude': lambda f: f is None }}) - r"""Message attachments""" - html: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('html'), 'exclude': lambda f: f is None }}) - r"""HTML body""" - in_reply_to: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('in_reply_to'), 'exclude': lambda f: f is None }}) - r"""In-Reply-To header. Value is the `message_id` of parent message. - - """ - message_id: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('message_id'), 'exclude': lambda f: f is None }}) - r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" - org_read_message: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('org_read_message'), 'exclude': lambda f: f is None }}) - r"""Ivy Organization ID of organization read the message.""" - references: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('references'), 'exclude': lambda f: f is None }}) - r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent.\ - The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread.\ - The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. - - """ - reply_to: Optional[shared_address.Address] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('reply_to'), 'exclude': lambda f: f is None }}) - send_status: Optional[list[CreateDraft201ApplicationJSONSendStatusEnum]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('send_status'), 'exclude': lambda f: f is None }}) - r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc`\ - Reference at - - """ - sender: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('sender'), 'exclude': lambda f: f is None }}) - r"""Ivy User ID of user sends the message.""" - text: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('text'), 'exclude': lambda f: f is None }}) - r"""Text body""" - to: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('to'), 'exclude': lambda f: f is None }}) - r"""To email addresses""" - type: Optional[CreateDraft201ApplicationJSONTypeEnum] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('type'), 'exclude': lambda f: f is None }}) - r"""Message type""" - user_read_message: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('user_read_message'), 'exclude': lambda f: f is None }}) - r"""Ivy User ID of user read the message.""" - - -@dataclasses.dataclass -class CreateDraftResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - create_draft_201_application_json_object: Optional[CreateDraft201ApplicationJSON] = dataclasses.field(default=None) - r"""Success""" - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - \ No newline at end of file diff --git a/message/src/epilot/models/operations/deletemessage.py b/message/src/epilot/models/operations/deletemessage.py deleted file mode 100755 index f48e52d41..000000000 --- a/message/src/epilot/models/operations/deletemessage.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import requests as requests_http -from typing import Optional - - -@dataclasses.dataclass -class DeleteMessageRequest: - - id: str = dataclasses.field(metadata={'path_param': { 'field_name': 'id', 'style': 'simple', 'explode': False }}) - r"""Message ID""" - - -@dataclasses.dataclass -class DeleteMessageResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - \ No newline at end of file diff --git a/message/src/epilot/models/operations/deletethread.py b/message/src/epilot/models/operations/deletethread.py deleted file mode 100755 index 293953919..000000000 --- a/message/src/epilot/models/operations/deletethread.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import requests as requests_http -from typing import Optional - - -@dataclasses.dataclass -class DeleteThreadRequest: - - id: str = dataclasses.field(metadata={'path_param': { 'field_name': 'id', 'style': 'simple', 'explode': False }}) - r"""Thread ID""" - - -@dataclasses.dataclass -class DeleteThreadResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - \ No newline at end of file diff --git a/message/src/epilot/models/operations/getmessage.py b/message/src/epilot/models/operations/getmessage.py deleted file mode 100755 index b3297fdd8..000000000 --- a/message/src/epilot/models/operations/getmessage.py +++ /dev/null @@ -1,107 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import dateutil.parser -import requests as requests_http -from ..shared import address as shared_address -from ..shared import attachmentsrelation as shared_attachmentsrelation -from dataclasses_json import Undefined, dataclass_json -from datetime import datetime -from enum import Enum -from epilot import utils -from marshmallow import fields -from typing import Optional - - -@dataclasses.dataclass -class GetMessageRequest: - - id: str = dataclasses.field(metadata={'path_param': { 'field_name': 'id', 'style': 'simple', 'explode': False }}) - r"""Message ID""" - -class GetMessage201ApplicationJSONSendStatusEnum(str, Enum): - SEND = "SEND" - DELIVERY = "DELIVERY" - REJECT = "REJECT" - COMPLAINT = "COMPLAINT" - BOUNCE = "BOUNCE" - ERROR = "ERROR" - -class GetMessage201ApplicationJSONTypeEnum(str, Enum): - r"""Message type""" - SENT = "SENT" - RECEIVED = "RECEIVED" - - -@dataclass_json(undefined=Undefined.EXCLUDE) -@dataclasses.dataclass -class GetMessage201ApplicationJSON: - r"""Success""" - - created_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_created_at'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) - r"""Created date""" - id: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_id') }}) - r"""Entity ID""" - org: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_org') }}) - r"""Ivy Organization ID the entity belongs to""" - schema: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_schema') }}) - r"""URL-friendly identifier for the entity schema""" - title: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_title') }}) - r"""Entity title""" - updated_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_updated_at'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) - r"""Updated date""" - from_: shared_address.Address = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('from') }}) - subject: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('subject') }}) - r"""Subject""" - tags: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_tags'), 'exclude': lambda f: f is None }}) - r"""Entity tags""" - bcc: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('bcc'), 'exclude': lambda f: f is None }}) - r"""Bcc email addresses""" - cc: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('cc'), 'exclude': lambda f: f is None }}) - r"""Cc email addresses""" - file: Optional[shared_attachmentsrelation.AttachmentsRelation] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('file'), 'exclude': lambda f: f is None }}) - r"""Message attachments""" - html: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('html'), 'exclude': lambda f: f is None }}) - r"""HTML body""" - in_reply_to: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('in_reply_to'), 'exclude': lambda f: f is None }}) - r"""In-Reply-To header. Value is the `message_id` of parent message. - - """ - message_id: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('message_id'), 'exclude': lambda f: f is None }}) - r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" - org_read_message: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('org_read_message'), 'exclude': lambda f: f is None }}) - r"""Ivy Organization ID of organization read the message.""" - references: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('references'), 'exclude': lambda f: f is None }}) - r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent.\ - The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread.\ - The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. - - """ - reply_to: Optional[shared_address.Address] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('reply_to'), 'exclude': lambda f: f is None }}) - send_status: Optional[list[GetMessage201ApplicationJSONSendStatusEnum]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('send_status'), 'exclude': lambda f: f is None }}) - r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc`\ - Reference at - - """ - sender: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('sender'), 'exclude': lambda f: f is None }}) - r"""Ivy User ID of user sends the message.""" - text: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('text'), 'exclude': lambda f: f is None }}) - r"""Text body""" - to: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('to'), 'exclude': lambda f: f is None }}) - r"""To email addresses""" - type: Optional[GetMessage201ApplicationJSONTypeEnum] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('type'), 'exclude': lambda f: f is None }}) - r"""Message type""" - user_read_message: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('user_read_message'), 'exclude': lambda f: f is None }}) - r"""Ivy User ID of user read the message.""" - - -@dataclasses.dataclass -class GetMessageResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - get_message_201_application_json_object: Optional[GetMessage201ApplicationJSON] = dataclasses.field(default=None) - r"""Success""" - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - \ No newline at end of file diff --git a/message/src/epilot/models/operations/markreadmessage.py b/message/src/epilot/models/operations/markreadmessage.py deleted file mode 100755 index d9ac93aa5..000000000 --- a/message/src/epilot/models/operations/markreadmessage.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import requests as requests_http -from typing import Optional - - -@dataclasses.dataclass -class MarkReadMessageRequest: - - id: str = dataclasses.field(metadata={'path_param': { 'field_name': 'id', 'style': 'simple', 'explode': False }}) - r"""Message ID""" - - -@dataclasses.dataclass -class MarkReadMessageResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - \ No newline at end of file diff --git a/message/src/epilot/models/operations/markreadthread.py b/message/src/epilot/models/operations/markreadthread.py deleted file mode 100755 index 4acbd11af..000000000 --- a/message/src/epilot/models/operations/markreadthread.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import requests as requests_http -from typing import Optional - - -@dataclasses.dataclass -class MarkReadThreadRequest: - - id: str = dataclasses.field(metadata={'path_param': { 'field_name': 'id', 'style': 'simple', 'explode': False }}) - r"""Thread ID""" - - -@dataclasses.dataclass -class MarkReadThreadResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - \ No newline at end of file diff --git a/message/src/epilot/models/operations/markunreadmessage.py b/message/src/epilot/models/operations/markunreadmessage.py deleted file mode 100755 index 4218b6f7e..000000000 --- a/message/src/epilot/models/operations/markunreadmessage.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import requests as requests_http -from typing import Optional - - -@dataclasses.dataclass -class MarkUnreadMessageRequest: - - id: str = dataclasses.field(metadata={'path_param': { 'field_name': 'id', 'style': 'simple', 'explode': False }}) - r"""Message ID""" - - -@dataclasses.dataclass -class MarkUnreadMessageResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - \ No newline at end of file diff --git a/message/src/epilot/models/operations/markunreadthread.py b/message/src/epilot/models/operations/markunreadthread.py deleted file mode 100755 index 9011f98e8..000000000 --- a/message/src/epilot/models/operations/markunreadthread.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import requests as requests_http -from typing import Optional - - -@dataclasses.dataclass -class MarkUnreadThreadRequest: - - id: str = dataclasses.field(metadata={'path_param': { 'field_name': 'id', 'style': 'simple', 'explode': False }}) - r"""Thread ID""" - - -@dataclasses.dataclass -class MarkUnreadThreadResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - \ No newline at end of file diff --git a/message/src/epilot/models/operations/searchthreads.py b/message/src/epilot/models/operations/searchthreads.py deleted file mode 100755 index 450b7e884..000000000 --- a/message/src/epilot/models/operations/searchthreads.py +++ /dev/null @@ -1,63 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import dateutil.parser -import requests as requests_http -from ..shared import message as shared_message -from dataclasses_json import Undefined, dataclass_json -from datetime import datetime -from epilot import utils -from marshmallow import fields -from typing import Optional - - -@dataclass_json(undefined=Undefined.EXCLUDE) -@dataclasses.dataclass -class SearchThreads200ApplicationJSONResults: - r"""Thread properties depend on API caller as it's not pre-defined. We do recommend having at least `topic` property for categorizing.""" - - created_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_created_at'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) - r"""Created date""" - id: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_id') }}) - r"""Entity ID""" - org: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_org') }}) - r"""Ivy Organization ID the entity belongs to""" - schema: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_schema') }}) - r"""URL-friendly identifier for the entity schema""" - title: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_title') }}) - r"""Entity title""" - updated_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_updated_at'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) - r"""Updated date""" - topic: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('topic') }}) - r"""Message topic (e.g. which service sends the message or message category)""" - tags: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_tags'), 'exclude': lambda f: f is None }}) - r"""Entity tags""" - assigned_to: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('assigned_to'), 'exclude': lambda f: f is None }}) - r"""Ivy User ID of who the message is assigned to. Default is the user who sends message.""" - latest_message: Optional[shared_message.Message] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('latest_message'), 'exclude': lambda f: f is None }}) - latest_trash_message: Optional[shared_message.Message] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('latest_trash_message'), 'exclude': lambda f: f is None }}) - org_read_message: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('org_read_message'), 'exclude': lambda f: f is None }}) - r"""Ivy Organization ID of organization read the message.""" - - -@dataclass_json(undefined=Undefined.EXCLUDE) -@dataclasses.dataclass -class SearchThreads200ApplicationJSON: - r"""Success""" - - hits: float = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('hits') }}) - r"""Total of matched threads""" - results: list[SearchThreads200ApplicationJSONResults] = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('results') }}) - r"""Matched threads""" - - -@dataclasses.dataclass -class SearchThreadsResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - search_threads_200_application_json_object: Optional[SearchThreads200ApplicationJSON] = dataclasses.field(default=None) - r"""Success""" - \ No newline at end of file diff --git a/message/src/epilot/models/operations/senddraft.py b/message/src/epilot/models/operations/senddraft.py deleted file mode 100755 index b9549949a..000000000 --- a/message/src/epilot/models/operations/senddraft.py +++ /dev/null @@ -1,100 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import dateutil.parser -import requests as requests_http -from ..shared import address as shared_address -from ..shared import attachmentsrelation as shared_attachmentsrelation -from dataclasses_json import Undefined, dataclass_json -from datetime import datetime -from enum import Enum -from epilot import utils -from marshmallow import fields -from typing import Optional - -class SendDraft201ApplicationJSONSendStatusEnum(str, Enum): - SEND = "SEND" - DELIVERY = "DELIVERY" - REJECT = "REJECT" - COMPLAINT = "COMPLAINT" - BOUNCE = "BOUNCE" - ERROR = "ERROR" - -class SendDraft201ApplicationJSONTypeEnum(str, Enum): - r"""Message type""" - SENT = "SENT" - RECEIVED = "RECEIVED" - - -@dataclass_json(undefined=Undefined.EXCLUDE) -@dataclasses.dataclass -class SendDraft201ApplicationJSON: - r"""Success""" - - created_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_created_at'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) - r"""Created date""" - id: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_id') }}) - r"""Entity ID""" - org: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_org') }}) - r"""Ivy Organization ID the entity belongs to""" - schema: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_schema') }}) - r"""URL-friendly identifier for the entity schema""" - title: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_title') }}) - r"""Entity title""" - updated_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_updated_at'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) - r"""Updated date""" - from_: shared_address.Address = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('from') }}) - subject: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('subject') }}) - r"""Subject""" - tags: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_tags'), 'exclude': lambda f: f is None }}) - r"""Entity tags""" - bcc: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('bcc'), 'exclude': lambda f: f is None }}) - r"""Bcc email addresses""" - cc: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('cc'), 'exclude': lambda f: f is None }}) - r"""Cc email addresses""" - file: Optional[shared_attachmentsrelation.AttachmentsRelation] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('file'), 'exclude': lambda f: f is None }}) - r"""Message attachments""" - html: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('html'), 'exclude': lambda f: f is None }}) - r"""HTML body""" - in_reply_to: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('in_reply_to'), 'exclude': lambda f: f is None }}) - r"""In-Reply-To header. Value is the `message_id` of parent message. - - """ - message_id: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('message_id'), 'exclude': lambda f: f is None }}) - r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" - org_read_message: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('org_read_message'), 'exclude': lambda f: f is None }}) - r"""Ivy Organization ID of organization read the message.""" - references: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('references'), 'exclude': lambda f: f is None }}) - r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent.\ - The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread.\ - The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. - - """ - reply_to: Optional[shared_address.Address] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('reply_to'), 'exclude': lambda f: f is None }}) - send_status: Optional[list[SendDraft201ApplicationJSONSendStatusEnum]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('send_status'), 'exclude': lambda f: f is None }}) - r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc`\ - Reference at - - """ - sender: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('sender'), 'exclude': lambda f: f is None }}) - r"""Ivy User ID of user sends the message.""" - text: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('text'), 'exclude': lambda f: f is None }}) - r"""Text body""" - to: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('to'), 'exclude': lambda f: f is None }}) - r"""To email addresses""" - type: Optional[SendDraft201ApplicationJSONTypeEnum] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('type'), 'exclude': lambda f: f is None }}) - r"""Message type""" - user_read_message: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('user_read_message'), 'exclude': lambda f: f is None }}) - r"""Ivy User ID of user read the message.""" - - -@dataclasses.dataclass -class SendDraftResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - send_draft_201_application_json_object: Optional[SendDraft201ApplicationJSON] = dataclasses.field(default=None) - r"""Success""" - \ No newline at end of file diff --git a/message/src/epilot/models/operations/sendmessage.py b/message/src/epilot/models/operations/sendmessage.py deleted file mode 100755 index f648f31ca..000000000 --- a/message/src/epilot/models/operations/sendmessage.py +++ /dev/null @@ -1,100 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import dateutil.parser -import requests as requests_http -from ..shared import address as shared_address -from ..shared import attachmentsrelation as shared_attachmentsrelation -from dataclasses_json import Undefined, dataclass_json -from datetime import datetime -from enum import Enum -from epilot import utils -from marshmallow import fields -from typing import Optional - -class SendMessage201ApplicationJSONSendStatusEnum(str, Enum): - SEND = "SEND" - DELIVERY = "DELIVERY" - REJECT = "REJECT" - COMPLAINT = "COMPLAINT" - BOUNCE = "BOUNCE" - ERROR = "ERROR" - -class SendMessage201ApplicationJSONTypeEnum(str, Enum): - r"""Message type""" - SENT = "SENT" - RECEIVED = "RECEIVED" - - -@dataclass_json(undefined=Undefined.EXCLUDE) -@dataclasses.dataclass -class SendMessage201ApplicationJSON: - r"""Success""" - - created_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_created_at'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) - r"""Created date""" - id: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_id') }}) - r"""Entity ID""" - org: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_org') }}) - r"""Ivy Organization ID the entity belongs to""" - schema: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_schema') }}) - r"""URL-friendly identifier for the entity schema""" - title: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_title') }}) - r"""Entity title""" - updated_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_updated_at'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) - r"""Updated date""" - from_: shared_address.Address = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('from') }}) - subject: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('subject') }}) - r"""Subject""" - tags: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_tags'), 'exclude': lambda f: f is None }}) - r"""Entity tags""" - bcc: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('bcc'), 'exclude': lambda f: f is None }}) - r"""Bcc email addresses""" - cc: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('cc'), 'exclude': lambda f: f is None }}) - r"""Cc email addresses""" - file: Optional[shared_attachmentsrelation.AttachmentsRelation] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('file'), 'exclude': lambda f: f is None }}) - r"""Message attachments""" - html: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('html'), 'exclude': lambda f: f is None }}) - r"""HTML body""" - in_reply_to: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('in_reply_to'), 'exclude': lambda f: f is None }}) - r"""In-Reply-To header. Value is the `message_id` of parent message. - - """ - message_id: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('message_id'), 'exclude': lambda f: f is None }}) - r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" - org_read_message: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('org_read_message'), 'exclude': lambda f: f is None }}) - r"""Ivy Organization ID of organization read the message.""" - references: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('references'), 'exclude': lambda f: f is None }}) - r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent.\ - The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread.\ - The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. - - """ - reply_to: Optional[shared_address.Address] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('reply_to'), 'exclude': lambda f: f is None }}) - send_status: Optional[list[SendMessage201ApplicationJSONSendStatusEnum]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('send_status'), 'exclude': lambda f: f is None }}) - r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc`\ - Reference at - - """ - sender: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('sender'), 'exclude': lambda f: f is None }}) - r"""Ivy User ID of user sends the message.""" - text: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('text'), 'exclude': lambda f: f is None }}) - r"""Text body""" - to: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('to'), 'exclude': lambda f: f is None }}) - r"""To email addresses""" - type: Optional[SendMessage201ApplicationJSONTypeEnum] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('type'), 'exclude': lambda f: f is None }}) - r"""Message type""" - user_read_message: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('user_read_message'), 'exclude': lambda f: f is None }}) - r"""Ivy User ID of user read the message.""" - - -@dataclasses.dataclass -class SendMessageResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - send_message_201_application_json_object: Optional[SendMessage201ApplicationJSON] = dataclasses.field(default=None) - r"""Success""" - \ No newline at end of file diff --git a/message/src/epilot/models/operations/trashmessage.py b/message/src/epilot/models/operations/trashmessage.py deleted file mode 100755 index bd3b2ab36..000000000 --- a/message/src/epilot/models/operations/trashmessage.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import requests as requests_http -from typing import Optional - - -@dataclasses.dataclass -class TrashMessageRequest: - - id: str = dataclasses.field(metadata={'path_param': { 'field_name': 'id', 'style': 'simple', 'explode': False }}) - r"""Message ID""" - - -@dataclasses.dataclass -class TrashMessageResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - \ No newline at end of file diff --git a/message/src/epilot/models/operations/trashthread.py b/message/src/epilot/models/operations/trashthread.py deleted file mode 100755 index f49bc16f2..000000000 --- a/message/src/epilot/models/operations/trashthread.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import requests as requests_http -from typing import Optional - - -@dataclasses.dataclass -class TrashThreadRequest: - - id: str = dataclasses.field(metadata={'path_param': { 'field_name': 'id', 'style': 'simple', 'explode': False }}) - r"""Thread ID""" - - -@dataclasses.dataclass -class TrashThreadResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - \ No newline at end of file diff --git a/message/src/epilot/models/operations/untrashmessage.py b/message/src/epilot/models/operations/untrashmessage.py deleted file mode 100755 index 912df9d61..000000000 --- a/message/src/epilot/models/operations/untrashmessage.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import requests as requests_http -from typing import Optional - - -@dataclasses.dataclass -class UntrashMessageRequest: - - id: str = dataclasses.field(metadata={'path_param': { 'field_name': 'id', 'style': 'simple', 'explode': False }}) - r"""Message ID""" - - -@dataclasses.dataclass -class UntrashMessageResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - \ No newline at end of file diff --git a/message/src/epilot/models/operations/untrashthread.py b/message/src/epilot/models/operations/untrashthread.py deleted file mode 100755 index 38e982e6c..000000000 --- a/message/src/epilot/models/operations/untrashthread.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import requests as requests_http -from typing import Optional - - -@dataclasses.dataclass -class UntrashThreadRequest: - - id: str = dataclasses.field(metadata={'path_param': { 'field_name': 'id', 'style': 'simple', 'explode': False }}) - r"""Thread ID""" - - -@dataclasses.dataclass -class UntrashThreadResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - \ No newline at end of file diff --git a/message/src/epilot/models/operations/updatemessage.py b/message/src/epilot/models/operations/updatemessage.py deleted file mode 100755 index 98d0ccb0c..000000000 --- a/message/src/epilot/models/operations/updatemessage.py +++ /dev/null @@ -1,100 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import dateutil.parser -import requests as requests_http -from ..shared import address as shared_address -from ..shared import attachmentsrelation as shared_attachmentsrelation -from dataclasses_json import Undefined, dataclass_json -from datetime import datetime -from enum import Enum -from epilot import utils -from marshmallow import fields -from typing import Optional - -class UpdateMessage201ApplicationJSONSendStatusEnum(str, Enum): - SEND = "SEND" - DELIVERY = "DELIVERY" - REJECT = "REJECT" - COMPLAINT = "COMPLAINT" - BOUNCE = "BOUNCE" - ERROR = "ERROR" - -class UpdateMessage201ApplicationJSONTypeEnum(str, Enum): - r"""Message type""" - SENT = "SENT" - RECEIVED = "RECEIVED" - - -@dataclass_json(undefined=Undefined.EXCLUDE) -@dataclasses.dataclass -class UpdateMessage201ApplicationJSON: - r"""Success""" - - created_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_created_at'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) - r"""Created date""" - id: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_id') }}) - r"""Entity ID""" - org: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_org') }}) - r"""Ivy Organization ID the entity belongs to""" - schema: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_schema') }}) - r"""URL-friendly identifier for the entity schema""" - title: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_title') }}) - r"""Entity title""" - updated_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_updated_at'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) - r"""Updated date""" - from_: shared_address.Address = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('from') }}) - subject: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('subject') }}) - r"""Subject""" - tags: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_tags'), 'exclude': lambda f: f is None }}) - r"""Entity tags""" - bcc: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('bcc'), 'exclude': lambda f: f is None }}) - r"""Bcc email addresses""" - cc: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('cc'), 'exclude': lambda f: f is None }}) - r"""Cc email addresses""" - file: Optional[shared_attachmentsrelation.AttachmentsRelation] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('file'), 'exclude': lambda f: f is None }}) - r"""Message attachments""" - html: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('html'), 'exclude': lambda f: f is None }}) - r"""HTML body""" - in_reply_to: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('in_reply_to'), 'exclude': lambda f: f is None }}) - r"""In-Reply-To header. Value is the `message_id` of parent message. - - """ - message_id: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('message_id'), 'exclude': lambda f: f is None }}) - r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" - org_read_message: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('org_read_message'), 'exclude': lambda f: f is None }}) - r"""Ivy Organization ID of organization read the message.""" - references: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('references'), 'exclude': lambda f: f is None }}) - r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent.\ - The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread.\ - The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. - - """ - reply_to: Optional[shared_address.Address] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('reply_to'), 'exclude': lambda f: f is None }}) - send_status: Optional[list[UpdateMessage201ApplicationJSONSendStatusEnum]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('send_status'), 'exclude': lambda f: f is None }}) - r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc`\ - Reference at - - """ - sender: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('sender'), 'exclude': lambda f: f is None }}) - r"""Ivy User ID of user sends the message.""" - text: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('text'), 'exclude': lambda f: f is None }}) - r"""Text body""" - to: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('to'), 'exclude': lambda f: f is None }}) - r"""To email addresses""" - type: Optional[UpdateMessage201ApplicationJSONTypeEnum] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('type'), 'exclude': lambda f: f is None }}) - r"""Message type""" - user_read_message: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('user_read_message'), 'exclude': lambda f: f is None }}) - r"""Ivy User ID of user read the message.""" - - -@dataclasses.dataclass -class UpdateMessageResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - update_message_201_application_json_object: Optional[UpdateMessage201ApplicationJSON] = dataclasses.field(default=None) - r"""Success""" - \ No newline at end of file diff --git a/message/src/epilot/models/operations/updatethread.py b/message/src/epilot/models/operations/updatethread.py deleted file mode 100755 index 27e74fd87..000000000 --- a/message/src/epilot/models/operations/updatethread.py +++ /dev/null @@ -1,52 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -import dateutil.parser -import requests as requests_http -from ..shared import message as shared_message -from dataclasses_json import Undefined, dataclass_json -from datetime import datetime -from epilot import utils -from marshmallow import fields -from typing import Optional - - -@dataclass_json(undefined=Undefined.EXCLUDE) -@dataclasses.dataclass -class UpdateThread201ApplicationJSON: - r"""Thread properties depend on API caller as it's not pre-defined. We do recommend having at least `topic` property for categorizing.""" - - created_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_created_at'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) - r"""Created date""" - id: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_id') }}) - r"""Entity ID""" - org: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_org') }}) - r"""Ivy Organization ID the entity belongs to""" - schema: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_schema') }}) - r"""URL-friendly identifier for the entity schema""" - title: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_title') }}) - r"""Entity title""" - updated_at: datetime = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_updated_at'), 'encoder': utils.datetimeisoformat(False), 'decoder': dateutil.parser.isoparse, 'mm_field': fields.DateTime(format='iso') }}) - r"""Updated date""" - topic: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('topic') }}) - r"""Message topic (e.g. which service sends the message or message category)""" - tags: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('_tags'), 'exclude': lambda f: f is None }}) - r"""Entity tags""" - assigned_to: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('assigned_to'), 'exclude': lambda f: f is None }}) - r"""Ivy User ID of who the message is assigned to. Default is the user who sends message.""" - latest_message: Optional[shared_message.Message] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('latest_message'), 'exclude': lambda f: f is None }}) - latest_trash_message: Optional[shared_message.Message] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('latest_trash_message'), 'exclude': lambda f: f is None }}) - org_read_message: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('org_read_message'), 'exclude': lambda f: f is None }}) - r"""Ivy Organization ID of organization read the message.""" - - -@dataclasses.dataclass -class UpdateThreadResponse: - - content_type: str = dataclasses.field() - status_code: int = dataclasses.field() - raw_response: Optional[requests_http.Response] = dataclasses.field(default=None) - update_thread_201_application_json_object: Optional[UpdateThread201ApplicationJSON] = dataclasses.field(default=None) - r"""Success""" - \ No newline at end of file diff --git a/message/src/epilot/models/shared/__init__.py b/message/src/epilot/models/shared/__init__.py deleted file mode 100755 index 6c3e6be02..000000000 --- a/message/src/epilot/models/shared/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from .address import * -from .attachmentsrelation import * -from .file import * -from .message import * -from .searchparams import * -from .security import * - -__all__ = ["Address","AddressSendStatusEnum","AttachmentsRelation","File","Message","MessageSendStatusEnum","MessageTypeEnum","SearchParams","Security"] diff --git a/message/src/epilot/models/shared/address.py b/message/src/epilot/models/shared/address.py deleted file mode 100755 index 42eb5f325..000000000 --- a/message/src/epilot/models/shared/address.py +++ /dev/null @@ -1,41 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -from dataclasses_json import Undefined, dataclass_json -from enum import Enum -from epilot import utils -from typing import Any, Optional - -class AddressSendStatusEnum(str, Enum): - r"""Sent message status regarding to this recipient.\ - Reference at - - """ - SEND = "SEND" - DELIVERY = "DELIVERY" - REJECT = "REJECT" - COMPLAINT = "COMPLAINT" - BOUNCE = "BOUNCE" - ERROR = "ERROR" - - -@dataclass_json(undefined=Undefined.EXCLUDE) -@dataclasses.dataclass -class Address: - - address: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('address') }}) - r"""Email address""" - name: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('name'), 'exclude': lambda f: f is None }}) - r"""Email address alias""" - send_error: Optional[dict[str, Any]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('send_error'), 'exclude': lambda f: f is None }}) - r"""Information about reject, complaint or bounce event. Only available if `send_status` is REJECT, COMPLAINT, BOUNCE or ERROR.\ - JSON object is defined by AWS SES. Reference at - - """ - send_status: Optional[AddressSendStatusEnum] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('send_status'), 'exclude': lambda f: f is None }}) - r"""Sent message status regarding to this recipient.\ - Reference at - - """ - \ No newline at end of file diff --git a/message/src/epilot/models/shared/attachmentsrelation.py b/message/src/epilot/models/shared/attachmentsrelation.py deleted file mode 100755 index fb2a6329d..000000000 --- a/message/src/epilot/models/shared/attachmentsrelation.py +++ /dev/null @@ -1,18 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -from ..shared import file as shared_file -from dataclasses_json import Undefined, dataclass_json -from epilot import utils -from typing import Optional - - -@dataclass_json(undefined=Undefined.EXCLUDE) -@dataclasses.dataclass -class AttachmentsRelation: - r"""Message attachments""" - - dollar_relation: Optional[list[shared_file.File]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('$relation'), 'exclude': lambda f: f is None }}) - r"""It's normal entity relation with some additional properties for sending message attachment.""" - \ No newline at end of file diff --git a/message/src/epilot/models/shared/file.py b/message/src/epilot/models/shared/file.py deleted file mode 100755 index 94f00e058..000000000 --- a/message/src/epilot/models/shared/file.py +++ /dev/null @@ -1,32 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -from dataclasses_json import Undefined, dataclass_json -from epilot import utils -from typing import Optional - - -@dataclass_json(undefined=Undefined.EXCLUDE) -@dataclasses.dataclass -class File: - - entity_id: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('entity_id') }}) - r"""File entity ID""" - cid: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('cid'), 'exclude': lambda f: f is None }}) - r"""Content ID (for inline)""" - filename: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('filename'), 'exclude': lambda f: f is None }}) - r"""File name""" - inline: Optional[bool] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('inline'), 'exclude': lambda f: f is None }}) - r"""If true then this attachment should not be offered for download (at least not in the main attachments list).\ - The usecase is CID embedded image (aka inline image). - - """ - is_message_attachment: Optional[bool] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('is_message_attachment'), 'exclude': lambda f: f is None }}) - r"""To indicate this file relation is message attachment. If false then this file will not be sent and simply kept as a file relation.""" - send_as_link: Optional[bool] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('send_as_link'), 'exclude': lambda f: f is None }}) - r"""If true then this attachment is sent via link. The link have to be inserted to email body by API caller.\ - In this case, service doesn't process this attachment. - - """ - \ No newline at end of file diff --git a/message/src/epilot/models/shared/message.py b/message/src/epilot/models/shared/message.py deleted file mode 100755 index 904bf79cf..000000000 --- a/message/src/epilot/models/shared/message.py +++ /dev/null @@ -1,71 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -from ..shared import address as shared_address -from ..shared import attachmentsrelation as shared_attachmentsrelation -from dataclasses_json import Undefined, dataclass_json -from enum import Enum -from epilot import utils -from typing import Optional - -class MessageSendStatusEnum(str, Enum): - SEND = "SEND" - DELIVERY = "DELIVERY" - REJECT = "REJECT" - COMPLAINT = "COMPLAINT" - BOUNCE = "BOUNCE" - ERROR = "ERROR" - -class MessageTypeEnum(str, Enum): - r"""Message type""" - SENT = "SENT" - RECEIVED = "RECEIVED" - - -@dataclass_json(undefined=Undefined.EXCLUDE) -@dataclasses.dataclass -class Message: - - from_: shared_address.Address = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('from') }}) - subject: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('subject') }}) - r"""Subject""" - bcc: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('bcc'), 'exclude': lambda f: f is None }}) - r"""Bcc email addresses""" - cc: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('cc'), 'exclude': lambda f: f is None }}) - r"""Cc email addresses""" - file: Optional[shared_attachmentsrelation.AttachmentsRelation] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('file'), 'exclude': lambda f: f is None }}) - r"""Message attachments""" - html: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('html'), 'exclude': lambda f: f is None }}) - r"""HTML body""" - in_reply_to: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('in_reply_to'), 'exclude': lambda f: f is None }}) - r"""In-Reply-To header. Value is the `message_id` of parent message. - - """ - message_id: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('message_id'), 'exclude': lambda f: f is None }}) - r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" - org_read_message: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('org_read_message'), 'exclude': lambda f: f is None }}) - r"""Ivy Organization ID of organization read the message.""" - references: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('references'), 'exclude': lambda f: f is None }}) - r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent.\ - The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread.\ - The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. - - """ - reply_to: Optional[shared_address.Address] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('reply_to'), 'exclude': lambda f: f is None }}) - send_status: Optional[list[MessageSendStatusEnum]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('send_status'), 'exclude': lambda f: f is None }}) - r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc`\ - Reference at - - """ - sender: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('sender'), 'exclude': lambda f: f is None }}) - r"""Ivy User ID of user sends the message.""" - text: Optional[str] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('text'), 'exclude': lambda f: f is None }}) - r"""Text body""" - to: Optional[list[shared_address.Address]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('to'), 'exclude': lambda f: f is None }}) - r"""To email addresses""" - type: Optional[MessageTypeEnum] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('type'), 'exclude': lambda f: f is None }}) - r"""Message type""" - user_read_message: Optional[list[str]] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('user_read_message'), 'exclude': lambda f: f is None }}) - r"""Ivy User ID of user read the message.""" - \ No newline at end of file diff --git a/message/src/epilot/models/shared/searchparams.py b/message/src/epilot/models/shared/searchparams.py deleted file mode 100755 index 56c5a5bf7..000000000 --- a/message/src/epilot/models/shared/searchparams.py +++ /dev/null @@ -1,18 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -from dataclasses_json import Undefined, dataclass_json -from epilot import utils -from typing import Optional - - -@dataclass_json(undefined=Undefined.EXCLUDE) -@dataclasses.dataclass -class SearchParams: - - q: str = dataclasses.field(metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('q') }}) - r"""Lucene query syntax supported with ElasticSearch""" - from_: Optional[int] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('from'), 'exclude': lambda f: f is None }}) - size: Optional[int] = dataclasses.field(default=None, metadata={'dataclasses_json': { 'letter_case': utils.get_field_name('size'), 'exclude': lambda f: f is None }}) - \ No newline at end of file diff --git a/message/src/epilot/models/shared/security.py b/message/src/epilot/models/shared/security.py deleted file mode 100755 index 0dedc5e9a..000000000 --- a/message/src/epilot/models/shared/security.py +++ /dev/null @@ -1,13 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from __future__ import annotations -import dataclasses -from typing import Optional - - -@dataclasses.dataclass -class Security: - - epilot_auth: Optional[str] = dataclasses.field(default=None, metadata={'security': { 'scheme': True, 'type': 'http', 'sub_type': 'bearer', 'field_name': 'Authorization' }}) - epilot_org: Optional[str] = dataclasses.field(default=None, metadata={'security': { 'scheme': True, 'type': 'apiKey', 'sub_type': 'header', 'field_name': 'x-epilot-org-id' }}) - \ No newline at end of file diff --git a/message/src/epilot/sdk.py b/message/src/epilot/sdk.py deleted file mode 100755 index 9dde9dd58..000000000 --- a/message/src/epilot/sdk.py +++ /dev/null @@ -1,92 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -import requests as requests_http -from . import utils -from .drafts import Drafts -from .messages import Messages -from .threads import Threads -from epilot.models import shared - -SERVERS = [ - "https://message.sls.epilot.io", -] -"""Contains the list of servers available to the SDK""" - -class Epilot: - r"""Send and receive email messages via your epilot organization - - """ - drafts: Drafts - messages: Messages - threads: Threads - - _client: requests_http.Session - _security_client: requests_http.Session - _server_url: str = SERVERS[0] - _language: str = "python" - _sdk_version: str = "1.2.2" - _gen_version: str = "2.16.5" - - def __init__(self, - security: shared.Security = None, - server_url: str = None, - url_params: dict[str, str] = None, - client: requests_http.Session = None - ) -> None: - """Instantiates the SDK configuring it with the provided parameters. - - :param security: The security details required for authentication - :type security: shared.Security - :param server_url: The server URL to use for all operations - :type server_url: str - :param url_params: Parameters to optionally template the server URL with - :type url_params: dict[str, str] - :param client: The requests.Session HTTP client to use for all operations - :type client: requests_http.Session - """ - self._client = requests_http.Session() - - - if server_url is not None: - if url_params is not None: - self._server_url = utils.template_url(server_url, url_params) - else: - self._server_url = server_url - - if client is not None: - self._client = client - - self._security_client = utils.configure_security_client(self._client, security) - - - self._init_sdks() - - def _init_sdks(self): - self.drafts = Drafts( - self._client, - self._security_client, - self._server_url, - self._language, - self._sdk_version, - self._gen_version - ) - - self.messages = Messages( - self._client, - self._security_client, - self._server_url, - self._language, - self._sdk_version, - self._gen_version - ) - - self.threads = Threads( - self._client, - self._security_client, - self._server_url, - self._language, - self._sdk_version, - self._gen_version - ) - - \ No newline at end of file diff --git a/message/src/epilot/threads.py b/message/src/epilot/threads.py deleted file mode 100755 index 5d2af4509..000000000 --- a/message/src/epilot/threads.py +++ /dev/null @@ -1,215 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -import requests as requests_http -from . import utils -from epilot.models import operations, shared -from typing import Optional - -class Threads: - _client: requests_http.Session - _security_client: requests_http.Session - _server_url: str - _language: str - _sdk_version: str - _gen_version: str - - def __init__(self, client: requests_http.Session, security_client: requests_http.Session, server_url: str, language: str, sdk_version: str, gen_version: str) -> None: - self._client = client - self._security_client = security_client - self._server_url = server_url - self._language = language - self._sdk_version = sdk_version - self._gen_version = gen_version - - def assign_thread(self, request: operations.AssignThreadRequest) -> operations.AssignThreadResponse: - r"""assignThread - Assign thread to entities - """ - base_url = self._server_url - - url = utils.generate_url(operations.AssignThreadRequest, base_url, '/v1/message/threads/{id}/assign', request) - - headers = {} - req_content_type, data, form = utils.serialize_request_body(request, "request_body", 'json') - if req_content_type not in ('multipart/form-data', 'multipart/mixed'): - headers['content-type'] = req_content_type - if data is None and form is None: - raise Exception('request body is required') - - client = self._security_client - - http_res = client.request('POST', url, data=data, files=form, headers=headers) - content_type = http_res.headers.get('Content-Type') - - res = operations.AssignThreadResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code in [204, 403]: - pass - - return res - - def delete_thread(self, request: operations.DeleteThreadRequest) -> operations.DeleteThreadResponse: - r"""deleteThread - Immediately and permanently delete a thread. This operation cannot be undone. - """ - base_url = self._server_url - - url = utils.generate_url(operations.DeleteThreadRequest, base_url, '/v1/message/threads/{id}', request) - - - client = self._security_client - - http_res = client.request('DELETE', url) - content_type = http_res.headers.get('Content-Type') - - res = operations.DeleteThreadResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code in [204, 403]: - pass - - return res - - def mark_read_thread(self, request: operations.MarkReadThreadRequest) -> operations.MarkReadThreadResponse: - r"""markReadThread - Mark thread as read - """ - base_url = self._server_url - - url = utils.generate_url(operations.MarkReadThreadRequest, base_url, '/v1/message/threads/{id}/read', request) - - - client = self._security_client - - http_res = client.request('POST', url) - content_type = http_res.headers.get('Content-Type') - - res = operations.MarkReadThreadResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code in [204, 403]: - pass - - return res - - def mark_unread_thread(self, request: operations.MarkUnreadThreadRequest) -> operations.MarkUnreadThreadResponse: - r"""markUnreadThread - Mark thread as unread - """ - base_url = self._server_url - - url = utils.generate_url(operations.MarkUnreadThreadRequest, base_url, '/v1/message/threads/{id}/unread', request) - - - client = self._security_client - - http_res = client.request('POST', url) - content_type = http_res.headers.get('Content-Type') - - res = operations.MarkUnreadThreadResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code in [204, 403]: - pass - - return res - - def search_threads(self, request: shared.SearchParams) -> operations.SearchThreadsResponse: - r"""searchThreads - Search for threads of email messages. - - Messages with no replies yet are treated as threads with single message. - - Lucene syntax supported. - - """ - base_url = self._server_url - - url = base_url.removesuffix('/') + '/v1/message/threads:search' - - headers = {} - req_content_type, data, form = utils.serialize_request_body(request, "request", 'json') - if req_content_type not in ('multipart/form-data', 'multipart/mixed'): - headers['content-type'] = req_content_type - - client = self._security_client - - http_res = client.request('POST', url, data=data, files=form, headers=headers) - content_type = http_res.headers.get('Content-Type') - - res = operations.SearchThreadsResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code == 200: - if utils.match_content_type(content_type, 'application/json'): - out = utils.unmarshal_json(http_res.text, Optional[operations.SearchThreads200ApplicationJSON]) - res.search_threads_200_application_json_object = out - elif http_res.status_code == 403: - pass - - return res - - def trash_thread(self, request: operations.TrashThreadRequest) -> operations.TrashThreadResponse: - r"""trashThread - Move a thread to trash - """ - base_url = self._server_url - - url = utils.generate_url(operations.TrashThreadRequest, base_url, '/v1/message/threads/{id}/trash', request) - - - client = self._security_client - - http_res = client.request('POST', url) - content_type = http_res.headers.get('Content-Type') - - res = operations.TrashThreadResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code in [204, 403]: - pass - - return res - - def untrash_thread(self, request: operations.UntrashThreadRequest) -> operations.UntrashThreadResponse: - r"""untrashThread - Restore a trashed thread - """ - base_url = self._server_url - - url = utils.generate_url(operations.UntrashThreadRequest, base_url, '/v1/message/threads/{id}/untrash', request) - - - client = self._security_client - - http_res = client.request('POST', url) - content_type = http_res.headers.get('Content-Type') - - res = operations.UntrashThreadResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code in [204, 403]: - pass - - return res - - def update_thread(self) -> operations.UpdateThreadResponse: - r"""updateThread - Modify thread metadata - """ - base_url = self._server_url - - url = base_url.removesuffix('/') + '/v1/message/threads' - - - client = self._security_client - - http_res = client.request('PUT', url) - content_type = http_res.headers.get('Content-Type') - - res = operations.UpdateThreadResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res) - - if http_res.status_code == 201: - if utils.match_content_type(content_type, 'application/json'): - out = utils.unmarshal_json(http_res.text, Optional[operations.UpdateThread201ApplicationJSON]) - res.update_thread_201_application_json_object = out - elif http_res.status_code == 403: - pass - - return res - - \ No newline at end of file diff --git a/message/src/epilot/utils/__init__.py b/message/src/epilot/utils/__init__.py deleted file mode 100755 index 94b739857..000000000 --- a/message/src/epilot/utils/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -from .retries import * -from .utils import * diff --git a/message/src/epilot/utils/retries.py b/message/src/epilot/utils/retries.py deleted file mode 100755 index c6251d948..000000000 --- a/message/src/epilot/utils/retries.py +++ /dev/null @@ -1,118 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -import random -import time - -import requests - - -class BackoffStrategy: - initial_interval: int - max_interval: int - exponent: float - max_elapsed_time: int - - def __init__(self, initial_interval: int, max_interval: int, exponent: float, max_elapsed_time: int): - self.initial_interval = initial_interval - self.max_interval = max_interval - self.exponent = exponent - self.max_elapsed_time = max_elapsed_time - - -class RetryConfig: - strategy: str - backoff: BackoffStrategy - retry_connection_errors: bool - - def __init__(self, strategy: str, retry_connection_errors: bool): - self.strategy = strategy - self.retry_connection_errors = retry_connection_errors - - -class Retries: - config: RetryConfig - status_codes: list[str] - - def __init__(self, config: RetryConfig, status_codes: list[str]): - self.config = config - self.status_codes = status_codes - - -class TemporaryError(Exception): - response: requests.Response - - def __init__(self, response: requests.Response): - self.response = response - - -class PermanentError(Exception): - inner: Exception - - def __init__(self, inner: Exception): - self.inner = inner - - -def retry(func, retries: Retries): - if retries.config.strategy == 'backoff': - def do_request(): - res: requests.Response - try: - res = func() - - for code in retries.status_codes: - if "X" in code.upper(): - code_range = int(code[0]) - - status_major = res.status_code / 100 - - if status_major >= code_range and status_major < code_range + 1: - raise TemporaryError(res) - else: - parsed_code = int(code) - - if res.status_code == parsed_code: - raise TemporaryError(res) - except requests.exceptions.ConnectionError as exception: - if not retries.config.config.retry_connection_errors: - raise - - raise PermanentError(exception) from exception - except requests.exceptions.Timeout as exception: - if not retries.config.config.retry_connection_errors: - raise - - raise PermanentError(exception) from exception - except TemporaryError: - raise - except Exception as exception: - raise PermanentError(exception) from exception - - return res - - return retry_with_backoff(do_request, retries.config.backoff.initial_interval, retries.config.backoff.max_interval, retries.config.backoff.exponent, retries.config.backoff.max_elapsed_time) - - return func() - - -def retry_with_backoff(func, initial_interval=500, max_interval=60000, exponent=1.5, max_elapsed_time=3600000): - start = round(time.time()*1000) - retries = 0 - - while True: - try: - return func() - except PermanentError as exception: - raise exception.inner - except Exception as exception: # pylint: disable=broad-exception-caught - now = round(time.time()*1000) - if now - start > max_elapsed_time: - if isinstance(exception, TemporaryError): - return exception.response - - raise - sleep = ((initial_interval/1000) * - exponent**retries + random.uniform(0, 1)) - if sleep > max_interval/1000: - sleep = max_interval/1000 - time.sleep(sleep) - retries += 1 diff --git a/message/src/epilot/utils/utils.py b/message/src/epilot/utils/utils.py deleted file mode 100755 index 9d4fba324..000000000 --- a/message/src/epilot/utils/utils.py +++ /dev/null @@ -1,735 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.""" - -import base64 -import json -import re -from dataclasses import Field, dataclass, fields, is_dataclass, make_dataclass -from datetime import date, datetime -from email.message import Message -from enum import Enum -from typing import Any, Callable, Optional, Tuple, Union, get_args, get_origin -from xmlrpc.client import boolean - -import dateutil.parser -import requests -from dataclasses_json import DataClassJsonMixin - - -class SecurityClient: - client: requests.Session - query_params: dict[str, str] = {} - - def __init__(self, client: requests.Session): - self.client = client - - def request(self, method, url, **kwargs): - params = kwargs.get('params', {}) - kwargs["params"] = self.query_params | params - - return self.client.request(method, url, **kwargs) - - -def configure_security_client(client: requests.Session, security: dataclass): - client = SecurityClient(client) - - if security is None: - return client - - sec_fields: Tuple[Field, ...] = fields(security) - for sec_field in sec_fields: - value = getattr(security, sec_field.name) - if value is None: - continue - - metadata = sec_field.metadata.get('security') - if metadata is None: - continue - if metadata.get('option'): - _parse_security_option(client, value) - return client - if metadata.get('scheme'): - # Special case for basic auth which could be a flattened struct - if metadata.get("sub_type") == "basic" and not is_dataclass(value): - _parse_security_scheme(client, metadata, security) - else: - _parse_security_scheme(client, metadata, value) - - return client - - -def _parse_security_option(client: SecurityClient, option: dataclass): - opt_fields: Tuple[Field, ...] = fields(option) - for opt_field in opt_fields: - metadata = opt_field.metadata.get('security') - if metadata is None or metadata.get('scheme') is None: - continue - _parse_security_scheme( - client, metadata, getattr(option, opt_field.name)) - - -def _parse_security_scheme(client: SecurityClient, scheme_metadata: dict, scheme: any): - scheme_type = scheme_metadata.get('type') - sub_type = scheme_metadata.get('sub_type') - - if is_dataclass(scheme): - if scheme_type == 'http' and sub_type == 'basic': - _parse_basic_auth_scheme(client, scheme) - return - - scheme_fields: Tuple[Field, ...] = fields(scheme) - for scheme_field in scheme_fields: - metadata = scheme_field.metadata.get('security') - if metadata is None or metadata.get('field_name') is None: - continue - - value = getattr(scheme, scheme_field.name) - - _parse_security_scheme_value( - client, scheme_metadata, metadata, value) - else: - _parse_security_scheme_value( - client, scheme_metadata, scheme_metadata, scheme) - - -def _parse_security_scheme_value(client: SecurityClient, scheme_metadata: dict, security_metadata: dict, value: any): - scheme_type = scheme_metadata.get('type') - sub_type = scheme_metadata.get('sub_type') - - header_name = security_metadata.get('field_name') - - if scheme_type == "apiKey": - if sub_type == 'header': - client.client.headers[header_name] = value - elif sub_type == 'query': - client.query_params[header_name] = value - elif sub_type == 'cookie': - client.client.cookies[header_name] = value - else: - raise Exception('not supported') - elif scheme_type == "openIdConnect": - client.client.headers[header_name] = value - elif scheme_type == 'oauth2': - client.client.headers[header_name] = value - elif scheme_type == 'http': - if sub_type == 'bearer': - client.client.headers[header_name] = value - else: - raise Exception('not supported') - else: - raise Exception('not supported') - - -def _parse_basic_auth_scheme(client: SecurityClient, scheme: dataclass): - username = "" - password = "" - - scheme_fields: Tuple[Field, ...] = fields(scheme) - for scheme_field in scheme_fields: - metadata = scheme_field.metadata.get('security') - if metadata is None or metadata.get('field_name') is None: - continue - - field_name = metadata.get('field_name') - value = getattr(scheme, scheme_field.name) - - if field_name == 'username': - username = value - if field_name == 'password': - password = value - - data = f'{username}:{password}'.encode() - client.client.headers['Authorization'] = f'Basic {base64.b64encode(data).decode()}' - - -def generate_url(clazz: type, server_url: str, path: str, path_params: dataclass, gbls: dict[str, dict[str, dict[str, Any]]] = None) -> str: - path_param_fields: Tuple[Field, ...] = fields(clazz) - for field in path_param_fields: - request_metadata = field.metadata.get('request') - if request_metadata is not None: - continue - - param_metadata = field.metadata.get('path_param') - if param_metadata is None: - continue - - if param_metadata.get('style', 'simple') == 'simple': - param = getattr( - path_params, field.name) if path_params is not None else None - param = _populate_from_globals( - field.name, param, 'pathParam', gbls) - - if param is None: - continue - - if isinstance(param, list): - pp_vals: list[str] = [] - for pp_val in param: - if pp_val is None: - continue - pp_vals.append(_val_to_string(pp_val)) - path = path.replace( - '{' + param_metadata.get('field_name', field.name) + '}', ",".join(pp_vals), 1) - elif isinstance(param, dict): - pp_vals: list[str] = [] - for pp_key in param: - if param[pp_key] is None: - continue - if param_metadata.get('explode'): - pp_vals.append( - f"{pp_key}={_val_to_string(param[pp_key])}") - else: - pp_vals.append( - f"{pp_key},{_val_to_string(param[pp_key])}") - path = path.replace( - '{' + param_metadata.get('field_name', field.name) + '}', ",".join(pp_vals), 1) - elif not isinstance(param, (str, int, float, complex, bool)): - pp_vals: list[str] = [] - param_fields: Tuple[Field, ...] = fields(param) - for param_field in param_fields: - param_value_metadata = param_field.metadata.get( - 'path_param') - if not param_value_metadata: - continue - - parm_name = param_value_metadata.get( - 'field_name', field.name) - - param_field_val = getattr(param, param_field.name) - if param_field_val is None: - continue - if param_metadata.get('explode'): - pp_vals.append( - f"{parm_name}={_val_to_string(param_field_val)}") - else: - pp_vals.append( - f"{parm_name},{_val_to_string(param_field_val)}") - path = path.replace( - '{' + param_metadata.get('field_name', field.name) + '}', ",".join(pp_vals), 1) - else: - path = path.replace( - '{' + param_metadata.get('field_name', field.name) + '}', _val_to_string(param), 1) - - return server_url.removesuffix("/") + path - - -def is_optional(field): - return get_origin(field) is Union and type(None) in get_args(field) - - -def template_url(url_with_params: str, params: dict[str, str]) -> str: - for key, value in params.items(): - url_with_params = url_with_params.replace( - '{' + key + '}', value) - - return url_with_params - - -def get_query_params(clazz: type, query_params: dataclass, gbls: dict[str, dict[str, dict[str, Any]]] = None) -> dict[str, list[str]]: - params: dict[str, list[str]] = {} - - param_fields: Tuple[Field, ...] = fields(clazz) - for field in param_fields: - request_metadata = field.metadata.get('request') - if request_metadata is not None: - continue - - metadata = field.metadata.get('query_param') - if not metadata: - continue - - param_name = field.name - value = getattr( - query_params, param_name) if query_params is not None else None - - value = _populate_from_globals(param_name, value, 'queryParam', gbls) - - f_name = metadata.get("field_name") - serialization = metadata.get('serialization', '') - if serialization != '': - params = params | _get_serialized_query_params( - metadata, f_name, value) - else: - style = metadata.get('style', 'form') - if style == 'deepObject': - params = params | _get_deep_object_query_params( - metadata, f_name, value) - elif style == 'form': - params = params | _get_form_query_params( - metadata, f_name, value) - else: - raise Exception('not yet implemented') - return params - - -def get_headers(headers_params: dataclass) -> dict[str, str]: - if headers_params is None: - return {} - - headers: dict[str, str] = {} - - param_fields: Tuple[Field, ...] = fields(headers_params) - for field in param_fields: - metadata = field.metadata.get('header') - if not metadata: - continue - - value = _serialize_header(metadata.get( - 'explode', False), getattr(headers_params, field.name)) - - if value != '': - headers[metadata.get('field_name', field.name)] = value - - return headers - - -def _get_serialized_query_params(metadata: dict, field_name: str, obj: any) -> dict[str, list[str]]: - params: dict[str, list[str]] = {} - - serialization = metadata.get('serialization', '') - if serialization == 'json': - params[metadata.get("field_name", field_name)] = marshal_json(obj) - - return params - - -def _get_deep_object_query_params(metadata: dict, field_name: str, obj: any) -> dict[str, list[str]]: - params: dict[str, list[str]] = {} - - if obj is None: - return params - - if is_dataclass(obj): - obj_fields: Tuple[Field, ...] = fields(obj) - for obj_field in obj_fields: - obj_param_metadata = obj_field.metadata.get('query_param') - if not obj_param_metadata: - continue - - obj_val = getattr(obj, obj_field.name) - if obj_val is None: - continue - - if isinstance(obj_val, list): - for val in obj_val: - if val is None: - continue - - if params.get(f'{metadata.get("field_name", field_name)}[{obj_param_metadata.get("field_name", obj_field.name)}]') is None: - params[f'{metadata.get("field_name", field_name)}[{obj_param_metadata.get("field_name", obj_field.name)}]'] = [ - ] - - params[ - f'{metadata.get("field_name", field_name)}[{obj_param_metadata.get("field_name", obj_field.name)}]'].append(_val_to_string(val)) - else: - params[ - f'{metadata.get("field_name", field_name)}[{obj_param_metadata.get("field_name", obj_field.name)}]'] = [ - _val_to_string(obj_val)] - elif isinstance(obj, dict): - for key, value in obj.items(): - if value is None: - continue - - if isinstance(value, list): - for val in value: - if val is None: - continue - - if params.get(f'{metadata.get("field_name", field_name)}[{key}]') is None: - params[f'{metadata.get("field_name", field_name)}[{key}]'] = [ - ] - - params[ - f'{metadata.get("field_name", field_name)}[{key}]'].append(_val_to_string(val)) - else: - params[f'{metadata.get("field_name", field_name)}[{key}]'] = [ - _val_to_string(value)] - return params - - -def _get_query_param_field_name(obj_field: Field) -> str: - obj_param_metadata = obj_field.metadata.get('query_param') - - if not obj_param_metadata: - return "" - - return obj_param_metadata.get("field_name", obj_field.name) - - -def _get_form_query_params(metadata: dict, field_name: str, obj: any) -> dict[str, list[str]]: - return _populate_form(field_name, metadata.get("explode", True), obj, _get_query_param_field_name) - - -SERIALIZATION_METHOD_TO_CONTENT_TYPE = { - 'json': 'application/json', - 'form': 'application/x-www-form-urlencoded', - 'multipart': 'multipart/form-data', - 'raw': 'application/octet-stream', - 'string': 'text/plain', -} - - -def serialize_request_body(request: dataclass, request_field_name: str, serialization_method: str) -> Tuple[str, any, any]: - if request is None: - return None, None, None, None - - if not is_dataclass(request) or not hasattr(request, request_field_name): - return serialize_content_type(request_field_name, SERIALIZATION_METHOD_TO_CONTENT_TYPE[serialization_method], request) - - request_val = getattr(request, request_field_name) - - request_fields: Tuple[Field, ...] = fields(request) - request_metadata = None - - for field in request_fields: - if field.name == request_field_name: - request_metadata = field.metadata.get('request') - break - - if request_metadata is None: - raise Exception('invalid request type') - - return serialize_content_type(request_field_name, request_metadata.get('media_type', 'application/octet-stream'), request_val) - - -def serialize_content_type(field_name: str, media_type: str, request: dataclass) -> Tuple[str, any, list[list[any]]]: - if re.match(r'(application|text)\/.*?\+*json.*', media_type) is not None: - return media_type, marshal_json(request), None - if re.match(r'multipart\/.*', media_type) is not None: - return serialize_multipart_form(media_type, request) - if re.match(r'application\/x-www-form-urlencoded.*', media_type) is not None: - return media_type, serialize_form_data(field_name, request), None - if isinstance(request, (bytes, bytearray)): - return media_type, request, None - if isinstance(request, str): - return media_type, request, None - - raise Exception( - f"invalid request body type {type(request)} for mediaType {media_type}") - - -def serialize_multipart_form(media_type: str, request: dataclass) -> Tuple[str, any, list[list[any]]]: - form: list[list[any]] = [] - request_fields = fields(request) - - for field in request_fields: - val = getattr(request, field.name) - if val is None: - continue - - field_metadata = field.metadata.get('multipart_form') - if not field_metadata: - continue - - if field_metadata.get("file") is True: - file_fields = fields(val) - - file_name = "" - field_name = "" - content = bytes() - - for file_field in file_fields: - file_metadata = file_field.metadata.get('multipart_form') - if file_metadata is None: - continue - - if file_metadata.get("content") is True: - content = getattr(val, file_field.name) - else: - field_name = file_metadata.get( - "field_name", file_field.name) - file_name = getattr(val, file_field.name) - if field_name == "" or file_name == "" or content == bytes(): - raise Exception('invalid multipart/form-data file') - - form.append([field_name, [file_name, content]]) - elif field_metadata.get("json") is True: - to_append = [field_metadata.get("field_name", field.name), [ - None, marshal_json(val), "application/json"]] - form.append(to_append) - else: - field_name = field_metadata.get( - "field_name", field.name) - if isinstance(val, list): - for value in val: - if value is None: - continue - form.append( - [field_name + "[]", [None, _val_to_string(value)]]) - else: - form.append([field_name, [None, _val_to_string(val)]]) - return media_type, None, form - - -def serialize_dict(original: dict, explode: bool, field_name, existing: Optional[dict[str, list[str]]]) -> dict[ - str, list[str]]: - if existing is None: - existing = [] - - if explode is True: - for key, val in original.items(): - if key not in existing: - existing[key] = [] - existing[key].append(val) - else: - temp = [] - for key, val in original.items(): - temp.append(str(key)) - temp.append(str(val)) - if field_name not in existing: - existing[field_name] = [] - existing[field_name].append(",".join(temp)) - return existing - - -def serialize_form_data(field_name: str, data: dataclass) -> dict[str, any]: - form: dict[str, list[str]] = {} - - if is_dataclass(data): - for field in fields(data): - val = getattr(data, field.name) - if val is None: - continue - - metadata = field.metadata.get('form') - if metadata is None: - continue - - field_name = metadata.get('field_name', field.name) - - if metadata.get('json'): - form[field_name] = [marshal_json(val)] - else: - if metadata.get('style', 'form') == 'form': - form = form | _populate_form( - field_name, metadata.get('explode', True), val, _get_form_field_name) - else: - raise Exception( - f'Invalid form style for field {field.name}') - elif isinstance(data, dict): - for key, value in data.items(): - form[key] = [_val_to_string(value)] - else: - raise Exception(f'Invalid request body type for field {field_name}') - - return form - - -def _get_form_field_name(obj_field: Field) -> str: - obj_param_metadata = obj_field.metadata.get('form') - - if not obj_param_metadata: - return "" - - return obj_param_metadata.get("field_name", obj_field.name) - - -def _populate_form(field_name: str, explode: boolean, obj: any, get_field_name_func: Callable) -> dict[str, list[str]]: - params: dict[str, list[str]] = {} - - if obj is None: - return params - - if is_dataclass(obj): - items = [] - - obj_fields: Tuple[Field, ...] = fields(obj) - for obj_field in obj_fields: - obj_field_name = get_field_name_func(obj_field) - if obj_field_name == '': - continue - - val = getattr(obj, obj_field.name) - if val is None: - continue - - if explode: - params[obj_field_name] = [_val_to_string(val)] - else: - items.append( - f'{obj_field_name},{_val_to_string(val)}') - - if len(items) > 0: - params[field_name] = [','.join(items)] - elif isinstance(obj, dict): - items = [] - for key, value in obj.items(): - if value is None: - continue - - if explode: - params[key] = _val_to_string(value) - else: - items.append(f'{key},{_val_to_string(value)}') - - if len(items) > 0: - params[field_name] = [','.join(items)] - elif isinstance(obj, list): - items = [] - - for value in obj: - if value is None: - continue - - if explode: - if not field_name in params: - params[field_name] = [] - params[field_name].append(_val_to_string(value)) - else: - items.append(_val_to_string(value)) - - if len(items) > 0: - params[field_name] = [','.join([str(item) for item in items])] - else: - params[field_name] = [_val_to_string(obj)] - - return params - - -def _serialize_header(explode: bool, obj: any) -> str: - if obj is None: - return '' - - if is_dataclass(obj): - items = [] - obj_fields: Tuple[Field, ...] = fields(obj) - for obj_field in obj_fields: - obj_param_metadata = obj_field.metadata.get('header') - - if not obj_param_metadata: - continue - - obj_field_name = obj_param_metadata.get( - 'field_name', obj_field.name) - if obj_field_name == '': - continue - - val = getattr(obj, obj_field.name) - if val is None: - continue - - if explode: - items.append( - f'{obj_field_name}={_val_to_string(val)}') - else: - items.append(obj_field_name) - items.append(_val_to_string(val)) - - if len(items) > 0: - return ','.join(items) - elif isinstance(obj, dict): - items = [] - - for key, value in obj.items(): - if value is None: - continue - - if explode: - items.append(f'{key}={_val_to_string(value)}') - else: - items.append(key) - items.append(_val_to_string(value)) - - if len(items) > 0: - return ','.join([str(item) for item in items]) - elif isinstance(obj, list): - items = [] - - for value in obj: - if value is None: - continue - - items.append(_val_to_string(value)) - - if len(items) > 0: - return ','.join(items) - else: - return f'{_val_to_string(obj)}' - - return '' - - -def unmarshal_json(data, typ): - unmarhsal = make_dataclass('Unmarhsal', [('res', typ)], - bases=(DataClassJsonMixin,)) - json_dict = json.loads(data) - out = unmarhsal.from_dict({"res": json_dict}) - return out.res - - -def marshal_json(val): - marshal = make_dataclass('Marshal', [('res', type(val))], - bases=(DataClassJsonMixin,)) - marshaller = marshal(res=val) - json_dict = marshaller.to_dict() - return json.dumps(json_dict["res"]) - - -def match_content_type(content_type: str, pattern: str) -> boolean: - if pattern in (content_type, "*", "*/*"): - return True - - msg = Message() - msg['content-type'] = content_type - media_type = msg.get_content_type() - - if media_type == pattern: - return True - - parts = media_type.split("/") - if len(parts) == 2: - if pattern in (f'{parts[0]}/*', f'*/{parts[1]}'): - return True - - return False - - -def datetimeisoformat(optional: bool): - def isoformatoptional(val): - if optional and val is None: - return None - return _val_to_string(val) - - return isoformatoptional - - -def dateisoformat(optional: bool): - def isoformatoptional(val): - if optional and val is None: - return None - return date.isoformat(val) - - return isoformatoptional - - -def datefromisoformat(date_str: str): - return dateutil.parser.parse(date_str).date() - - -def get_field_name(name): - def override(_, _field_name=name): - return _field_name - - return override - - -def _val_to_string(val): - if isinstance(val, bool): - return str(val).lower() - if isinstance(val, datetime): - return val.isoformat().replace('+00:00', 'Z') - if isinstance(val, Enum): - return val.value - - return str(val) - - -def _populate_from_globals(param_name: str, value: any, param_type: str, gbls: dict[str, dict[str, dict[str, Any]]]): - if value is None and gbls is not None: - if 'parameters' in gbls: - if param_type in gbls['parameters']: - if param_name in gbls['parameters'][param_type]: - global_value = gbls['parameters'][param_type][param_name] - if global_value is not None: - value = global_value - - return value diff --git a/message/src/epilot_message/__init__.py b/message/src/epilot_message/__init__.py new file mode 100644 index 000000000..68138c477 --- /dev/null +++ b/message/src/epilot_message/__init__.py @@ -0,0 +1,5 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .sdk import * +from .sdkconfiguration import * +from .models import * diff --git a/message/src/epilot_message/_hooks/__init__.py b/message/src/epilot_message/_hooks/__init__.py new file mode 100644 index 000000000..2ee66cdd5 --- /dev/null +++ b/message/src/epilot_message/_hooks/__init__.py @@ -0,0 +1,5 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .sdkhooks import * +from .types import * +from .registration import * diff --git a/message/src/epilot_message/_hooks/registration.py b/message/src/epilot_message/_hooks/registration.py new file mode 100644 index 000000000..1db6a5293 --- /dev/null +++ b/message/src/epilot_message/_hooks/registration.py @@ -0,0 +1,13 @@ +from .types import Hooks + + +# This file is only ever generated once on the first generation and then is free to be modified. +# Any hooks you wish to add should be registered in the init_hooks function. Feel free to define them +# in this file or in separate files in the hooks folder. + + +def init_hooks(hooks: Hooks): + # pylint: disable=unused-argument + """Add hooks by calling hooks.register{sdk_init/before_request/after_success/after_error}Hook + with an instance of a hook that implements that specific Hook interface + Hooks are registered per SDK instance, and are valid for the lifetime of the SDK instance""" diff --git a/message/src/epilot_message/_hooks/sdkhooks.py b/message/src/epilot_message/_hooks/sdkhooks.py new file mode 100644 index 000000000..52a063727 --- /dev/null +++ b/message/src/epilot_message/_hooks/sdkhooks.py @@ -0,0 +1,57 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +import httpx +from .types import SDKInitHook, BeforeRequestContext, BeforeRequestHook, AfterSuccessContext, AfterSuccessHook, AfterErrorContext, AfterErrorHook, Hooks +from .registration import init_hooks +from typing import List, Optional, Tuple +from epilot_message.httpclient import HttpClient + +class SDKHooks(Hooks): + def __init__(self) -> None: + self.sdk_init_hooks: List[SDKInitHook] = [] + self.before_request_hooks: List[BeforeRequestHook] = [] + self.after_success_hooks: List[AfterSuccessHook] = [] + self.after_error_hooks: List[AfterErrorHook] = [] + init_hooks(self) + + def register_sdk_init_hook(self, hook: SDKInitHook) -> None: + self.sdk_init_hooks.append(hook) + + def register_before_request_hook(self, hook: BeforeRequestHook) -> None: + self.before_request_hooks.append(hook) + + def register_after_success_hook(self, hook: AfterSuccessHook) -> None: + self.after_success_hooks.append(hook) + + def register_after_error_hook(self, hook: AfterErrorHook) -> None: + self.after_error_hooks.append(hook) + + def sdk_init(self, base_url: str, client: HttpClient) -> Tuple[str, HttpClient]: + for hook in self.sdk_init_hooks: + base_url, client = hook.sdk_init(base_url, client) + return base_url, client + + def before_request(self, hook_ctx: BeforeRequestContext, request: httpx.Request) -> httpx.Request: + for hook in self.before_request_hooks: + out = hook.before_request(hook_ctx, request) + if isinstance(out, Exception): + raise out + request = out + + return request + + def after_success(self, hook_ctx: AfterSuccessContext, response: httpx.Response) -> httpx.Response: + for hook in self.after_success_hooks: + out = hook.after_success(hook_ctx, response) + if isinstance(out, Exception): + raise out + response = out + return response + + def after_error(self, hook_ctx: AfterErrorContext, response: Optional[httpx.Response], error: Optional[Exception]) -> Tuple[Optional[httpx.Response], Optional[Exception]]: + for hook in self.after_error_hooks: + result = hook.after_error(hook_ctx, response, error) + if isinstance(result, Exception): + raise result + response, error = result + return response, error diff --git a/message/src/epilot_message/_hooks/types.py b/message/src/epilot_message/_hooks/types.py new file mode 100644 index 000000000..ab96391a8 --- /dev/null +++ b/message/src/epilot_message/_hooks/types.py @@ -0,0 +1,76 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + + +from abc import ABC, abstractmethod +from epilot_message.httpclient import HttpClient +import httpx +from typing import Any, Callable, List, Optional, Tuple, Union + + +class HookContext: + operation_id: str + oauth2_scopes: Optional[List[str]] = None + security_source: Optional[Union[Any, Callable[[], Any]]] = None + + def __init__(self, operation_id: str, oauth2_scopes: Optional[List[str]], security_source: Optional[Union[Any, Callable[[], Any]]]): + self.operation_id = operation_id + self.oauth2_scopes = oauth2_scopes + self.security_source = security_source + + +class BeforeRequestContext(HookContext): + def __init__(self, hook_ctx: HookContext): + super().__init__(hook_ctx.operation_id, hook_ctx.oauth2_scopes, hook_ctx.security_source) + + +class AfterSuccessContext(HookContext): + def __init__(self, hook_ctx: HookContext): + super().__init__(hook_ctx.operation_id, hook_ctx.oauth2_scopes, hook_ctx.security_source) + + + +class AfterErrorContext(HookContext): + def __init__(self, hook_ctx: HookContext): + super().__init__(hook_ctx.operation_id, hook_ctx.oauth2_scopes, hook_ctx.security_source) + + +class SDKInitHook(ABC): + @abstractmethod + def sdk_init(self, base_url: str, client: HttpClient) -> Tuple[str, HttpClient]: + pass + + +class BeforeRequestHook(ABC): + @abstractmethod + def before_request(self, hook_ctx: BeforeRequestContext, request: httpx.Request) -> Union[httpx.Request, Exception]: + pass + + +class AfterSuccessHook(ABC): + @abstractmethod + def after_success(self, hook_ctx: AfterSuccessContext, response: httpx.Response) -> Union[httpx.Response, Exception]: + pass + + +class AfterErrorHook(ABC): + @abstractmethod + def after_error(self, hook_ctx: AfterErrorContext, response: Optional[httpx.Response], error: Optional[Exception]) -> Union[Tuple[Optional[httpx.Response], Optional[Exception]], Exception]: + pass + + +class Hooks(ABC): + @abstractmethod + def register_sdk_init_hook(self, hook: SDKInitHook): + pass + + @abstractmethod + def register_before_request_hook(self, hook: BeforeRequestHook): + pass + + @abstractmethod + def register_after_success_hook(self, hook: AfterSuccessHook): + pass + + @abstractmethod + def register_after_error_hook(self, hook: AfterErrorHook): + pass diff --git a/message/src/epilot_message/basesdk.py b/message/src/epilot_message/basesdk.py new file mode 100644 index 000000000..d2796f832 --- /dev/null +++ b/message/src/epilot_message/basesdk.py @@ -0,0 +1,253 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .sdkconfiguration import SDKConfiguration +from epilot_message import models, utils +from epilot_message._hooks import AfterErrorContext, AfterSuccessContext, BeforeRequestContext +from epilot_message.utils import RetryConfig, SerializedRequestBody, get_body_content +import httpx +from typing import Callable, List, Optional, Tuple + +class BaseSDK: + sdk_configuration: SDKConfiguration + + def __init__(self, sdk_config: SDKConfiguration) -> None: + self.sdk_configuration = sdk_config + + def get_url(self, base_url, url_variables): + sdk_url, sdk_variables = self.sdk_configuration.get_server_details() + + if base_url is None: + base_url = sdk_url + + if url_variables is None: + url_variables = sdk_variables + + return utils.template_url(base_url, url_variables) + + def build_request( + self, + method, + path, + base_url, + url_variables, + request, + request_body_required, + request_has_path_params, + request_has_query_params, + user_agent_header, + accept_header_value, + _globals=None, + security=None, + timeout_ms: Optional[int] = None, + get_serialized_body: Optional[ + Callable[[], Optional[SerializedRequestBody]] + ] = None, + url_override: Optional[str] = None, + ) -> httpx.Request: + client = self.sdk_configuration.client + + query_params = {} + + url = url_override + if url is None: + url = utils.generate_url( + self.get_url(base_url, url_variables), + path, + request if request_has_path_params else None, + _globals if request_has_path_params else None, + ) + + query_params = utils.get_query_params( + request if request_has_query_params else None, + _globals if request_has_query_params else None, + ) + + headers = utils.get_headers(request, _globals) + headers["Accept"] = accept_header_value + headers[user_agent_header] = self.sdk_configuration.user_agent + + if security is not None: + if callable(security): + security = security() + + if security is not None: + security_headers, security_query_params = utils.get_security(security) + headers = {**headers, **security_headers} + query_params = {**query_params, **security_query_params} + + serialized_request_body = SerializedRequestBody("application/octet-stream") + if get_serialized_body is not None: + rb = get_serialized_body() + if request_body_required and rb is None: + raise ValueError("request body is required") + + if rb is not None: + serialized_request_body = rb + + if ( + serialized_request_body.media_type is not None + and serialized_request_body.media_type + not in ( + "multipart/form-data", + "multipart/mixed", + ) + ): + headers["content-type"] = serialized_request_body.media_type + + timeout = timeout_ms / 1000 if timeout_ms is not None else None + + return client.build_request( + method, + url, + params=query_params, + content=serialized_request_body.content, + data=serialized_request_body.data, + files=serialized_request_body.files, + headers=headers, + timeout=timeout, + ) + + def do_request( + self, + hook_ctx, + request, + error_status_codes, + stream=False, + retry_config: Optional[Tuple[RetryConfig, List[str]]] = None, + ) -> httpx.Response: + client = self.sdk_configuration.client + logger = self.sdk_configuration.debug_logger + + def do(): + http_res = None + try: + req = self.sdk_configuration.get_hooks().before_request( + BeforeRequestContext(hook_ctx), request + ) + logger.debug( + "Request:\nMethod: %s\nURL: %s\nHeaders: %s\nBody: %s", + req.method, + req.url, + req.headers, + get_body_content(req) + ) + http_res = client.send(req, stream=stream) + except Exception as e: + _, e = self.sdk_configuration.get_hooks().after_error( + AfterErrorContext(hook_ctx), None, e + ) + if e is not None: + logger.debug("Request Exception", exc_info=True) + raise e + + if http_res is None: + logger.debug("Raising no response SDK error") + raise models.SDKError("No response received") + + logger.debug( + "Response:\nStatus Code: %s\nURL: %s\nHeaders: %s\nBody: %s", + http_res.status_code, + http_res.url, + http_res.headers, + "" if stream else http_res.text + ) + + if utils.match_status_codes(error_status_codes, http_res.status_code): + result, err = self.sdk_configuration.get_hooks().after_error( + AfterErrorContext(hook_ctx), http_res, None + ) + if err is not None: + logger.debug("Request Exception", exc_info=True) + raise err + if result is not None: + http_res = result + else: + logger.debug("Raising unexpected SDK error") + raise models.SDKError("Unexpected error occurred") + + return http_res + + if retry_config is not None: + http_res = utils.retry(do, utils.Retries(retry_config[0], retry_config[1])) + else: + http_res = do() + + if not utils.match_status_codes(error_status_codes, http_res.status_code): + http_res = self.sdk_configuration.get_hooks().after_success( + AfterSuccessContext(hook_ctx), http_res + ) + + return http_res + + async def do_request_async( + self, + hook_ctx, + request, + error_status_codes, + stream=False, + retry_config: Optional[Tuple[RetryConfig, List[str]]] = None, + ) -> httpx.Response: + client = self.sdk_configuration.async_client + logger = self.sdk_configuration.debug_logger + async def do(): + http_res = None + try: + req = self.sdk_configuration.get_hooks().before_request( + BeforeRequestContext(hook_ctx), request + ) + logger.debug( + "Request:\nMethod: %s\nURL: %s\nHeaders: %s\nBody: %s", + req.method, + req.url, + req.headers, + get_body_content(req) + ) + http_res = await client.send(req, stream=stream) + except Exception as e: + _, e = self.sdk_configuration.get_hooks().after_error( + AfterErrorContext(hook_ctx), None, e + ) + if e is not None: + logger.debug("Request Exception", exc_info=True) + raise e + + if http_res is None: + logger.debug("Raising no response SDK error") + raise models.SDKError("No response received") + + logger.debug( + "Response:\nStatus Code: %s\nURL: %s\nHeaders: %s\nBody: %s", + http_res.status_code, + http_res.url, + http_res.headers, + "" if stream else http_res.text + ) + + if utils.match_status_codes(error_status_codes, http_res.status_code): + result, err = self.sdk_configuration.get_hooks().after_error( + AfterErrorContext(hook_ctx), http_res, None + ) + if err is not None: + logger.debug("Request Exception", exc_info=True) + raise err + if result is not None: + http_res = result + else: + logger.debug("Raising unexpected SDK error") + raise models.SDKError("Unexpected error occurred") + + return http_res + + if retry_config is not None: + http_res = await utils.retry_async( + do, utils.Retries(retry_config[0], retry_config[1]) + ) + else: + http_res = await do() + + if not utils.match_status_codes(error_status_codes, http_res.status_code): + http_res = self.sdk_configuration.get_hooks().after_success( + AfterSuccessContext(hook_ctx), http_res + ) + + return http_res diff --git a/message/src/epilot_message/drafts.py b/message/src/epilot_message/drafts.py new file mode 100644 index 000000000..46aa8b54b --- /dev/null +++ b/message/src/epilot_message/drafts.py @@ -0,0 +1,294 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .basesdk import BaseSDK +from epilot_message import models, utils +from epilot_message._hooks import HookContext +from epilot_message.types import BaseModel, OptionalNullable, UNSET +from typing import Optional, Union, cast + +class Drafts(BaseSDK): + + + def create_draft( + self, *, + request: Optional[Union[models.MessageRequestParams, models.MessageRequestParamsTypedDict]] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.CreateDraftResponseBody]: + r"""createDraft + + Create a new draft + + :param request: The request object to send. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + if not isinstance(request, BaseModel) and request is not None: + request = utils.unmarshal(request, models.MessageRequestParams) + request = cast(models.MessageRequestParams, request) + + req = self.build_request( + method="POST", + path="/v1/message/drafts", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body(request, False, True, "json", Optional[models.MessageRequestParams]), + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="createDraft", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "201", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.CreateDraftResponseBody]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def create_draft_async( + self, *, + request: Optional[Union[models.MessageRequestParams, models.MessageRequestParamsTypedDict]] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.CreateDraftResponseBody]: + r"""createDraft + + Create a new draft + + :param request: The request object to send. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + if not isinstance(request, BaseModel) and request is not None: + request = utils.unmarshal(request, models.MessageRequestParams) + request = cast(models.MessageRequestParams, request) + + req = self.build_request( + method="POST", + path="/v1/message/drafts", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body(request, False, True, "json", Optional[models.MessageRequestParams]), + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="createDraft", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "201", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.CreateDraftResponseBody]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def send_draft( + self, *, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.SendDraftResponseBody]: + r"""sendDraft + + Send the existing draft to the recipients + + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + req = self.build_request( + method="POST", + path="/v1/message/drafts:send", + base_url=base_url, + url_variables=url_variables, + request=None, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="sendDraft", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "201", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.SendDraftResponseBody]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def send_draft_async( + self, *, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.SendDraftResponseBody]: + r"""sendDraft + + Send the existing draft to the recipients + + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + req = self.build_request( + method="POST", + path="/v1/message/drafts:send", + base_url=base_url, + url_variables=url_variables, + request=None, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="sendDraft", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "201", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.SendDraftResponseBody]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + diff --git a/message/src/epilot_message/genai.py b/message/src/epilot_message/genai.py new file mode 100644 index 000000000..70ea3f863 --- /dev/null +++ b/message/src/epilot_message/genai.py @@ -0,0 +1,650 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .basesdk import BaseSDK +from epilot_message import models, utils +from epilot_message._hooks import HookContext +from epilot_message.types import OptionalNullable, UNSET +from typing import Any, Optional, Union + +class GenAI(BaseSDK): + + + def generate_suggested_reply( + self, *, + message_id: str, + thread_id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.GenerateSuggestedReplyResponseBody]: + r"""generateSuggestedReply + + Generate suggested reply of the message in the thread + + :param message_id: Message ID + :param thread_id: Thread ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.GenerateSuggestedReplyRequest( + message_id=message_id, + thread_id=thread_id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/messages/{messageId}/genai:reply", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="generateSuggestedReply", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "200", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.GenerateSuggestedReplyResponseBody]) + if utils.match_response(http_res, "202", "*"): + return None + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def generate_suggested_reply_async( + self, *, + message_id: str, + thread_id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.GenerateSuggestedReplyResponseBody]: + r"""generateSuggestedReply + + Generate suggested reply of the message in the thread + + :param message_id: Message ID + :param thread_id: Thread ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.GenerateSuggestedReplyRequest( + message_id=message_id, + thread_id=thread_id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/messages/{messageId}/genai:reply", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="generateSuggestedReply", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "200", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.GenerateSuggestedReplyResponseBody]) + if utils.match_response(http_res, "202", "*"): + return None + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def get_gen_ai_feedback( + self, *, + from_: Optional[float] = 0, + size: Optional[float] = 10, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.GetGenAIFeedbackResponseBody]: + r"""getGenAIFeedback + + Fetch the feedback list for genai + + :param from_: + :param size: Number of feedback to return + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.GetGenAIFeedbackRequest( + from_=from_, + size=size, + ) + + req = self.build_request( + method="GET", + path="/v1/message/threads/genai:feedback", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="getGenAIFeedback", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "200", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.GetGenAIFeedbackResponseBody]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def get_gen_ai_feedback_async( + self, *, + from_: Optional[float] = 0, + size: Optional[float] = 10, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.GetGenAIFeedbackResponseBody]: + r"""getGenAIFeedback + + Fetch the feedback list for genai + + :param from_: + :param size: Number of feedback to return + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.GetGenAIFeedbackRequest( + from_=from_, + size=size, + ) + + req = self.build_request( + method="GET", + path="/v1/message/threads/genai:feedback", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="getGenAIFeedback", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "200", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.GetGenAIFeedbackResponseBody]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def get_info( + self, *, + thread_id: str, + message_id: Optional[str] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.GetInfoResponse]: + r"""getInfo + + Get generated information of the thread + + :param thread_id: Thread ID + :param message_id: Message ID, If not passed defaults to latest message ID in the thread + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.GetInfoRequest( + message_id=message_id, + thread_id=thread_id, + ) + + req = self.build_request( + method="GET", + path="/v1/message/threads/{threadId}/genai:info", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="getInfo", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "200", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.GetInfoResponseBody]) + if utils.match_response(http_res, "202", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.GetInfoGenAIResponseBody]) + if utils.match_response(http_res, ["4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def get_info_async( + self, *, + thread_id: str, + message_id: Optional[str] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.GetInfoResponse]: + r"""getInfo + + Get generated information of the thread + + :param thread_id: Thread ID + :param message_id: Message ID, If not passed defaults to latest message ID in the thread + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.GetInfoRequest( + message_id=message_id, + thread_id=thread_id, + ) + + req = self.build_request( + method="GET", + path="/v1/message/threads/{threadId}/genai:info", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="getInfo", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "200", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.GetInfoResponseBody]) + if utils.match_response(http_res, "202", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.GetInfoGenAIResponseBody]) + if utils.match_response(http_res, ["4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def patch_info( + self, *, + message_id: str, + thread_id: str, + request_body: Union[models.PatchInfoRequestBody, models.PatchInfoRequestBodyTypedDict], + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.PatchInfoResponseBody]: + r"""patchInfo + + patch generated information of the thread + + :param message_id: Message ID + :param thread_id: Thread ID + :param request_body: Request body for genai info update + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.PatchInfoRequest( + message_id=message_id, + thread_id=thread_id, + request_body=utils.get_pydantic_model(request_body, models.PatchInfoRequestBody), + ) + + req = self.build_request( + method="PATCH", + path="/v1/message/threads/{threadId}/messages/{messageId}/genai:info", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body(request.request_body, False, False, "json", models.PatchInfoRequestBody), + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="patchInfo", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["400","403","4XX","500","5XX"], + retry_config=retry_config + ) + + data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.PatchInfoResponseBody]) + if utils.match_response(http_res, ["400","403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + if utils.match_response(http_res, "500", "application/json"): + data = utils.unmarshal_json(http_res.text, models.PatchInfoGenAIResponseBodyData) + raise models.PatchInfoGenAIResponseBody(data=data) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def patch_info_async( + self, *, + message_id: str, + thread_id: str, + request_body: Union[models.PatchInfoRequestBody, models.PatchInfoRequestBodyTypedDict], + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.PatchInfoResponseBody]: + r"""patchInfo + + patch generated information of the thread + + :param message_id: Message ID + :param thread_id: Thread ID + :param request_body: Request body for genai info update + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.PatchInfoRequest( + message_id=message_id, + thread_id=thread_id, + request_body=utils.get_pydantic_model(request_body, models.PatchInfoRequestBody), + ) + + req = self.build_request( + method="PATCH", + path="/v1/message/threads/{threadId}/messages/{messageId}/genai:info", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body(request.request_body, False, False, "json", models.PatchInfoRequestBody), + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="patchInfo", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["400","403","4XX","500","5XX"], + retry_config=retry_config + ) + + data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.PatchInfoResponseBody]) + if utils.match_response(http_res, ["400","403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + if utils.match_response(http_res, "500", "application/json"): + data = utils.unmarshal_json(http_res.text, models.PatchInfoGenAIResponseBodyData) + raise models.PatchInfoGenAIResponseBody(data=data) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + diff --git a/message/src/epilot_message/httpclient.py b/message/src/epilot_message/httpclient.py new file mode 100644 index 000000000..36b642a0e --- /dev/null +++ b/message/src/epilot_message/httpclient.py @@ -0,0 +1,78 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +# pyright: reportReturnType = false +from typing_extensions import Protocol, runtime_checkable +import httpx +from typing import Any, Optional, Union + + +@runtime_checkable +class HttpClient(Protocol): + def send( + self, + request: httpx.Request, + *, + stream: bool = False, + auth: Union[ + httpx._types.AuthTypes, httpx._client.UseClientDefault, None + ] = httpx.USE_CLIENT_DEFAULT, + follow_redirects: Union[ + bool, httpx._client.UseClientDefault + ] = httpx.USE_CLIENT_DEFAULT, + ) -> httpx.Response: + pass + + def build_request( + self, + method: str, + url: httpx._types.URLTypes, + *, + content: Optional[httpx._types.RequestContent] = None, + data: Optional[httpx._types.RequestData] = None, + files: Optional[httpx._types.RequestFiles] = None, + json: Optional[Any] = None, + params: Optional[httpx._types.QueryParamTypes] = None, + headers: Optional[httpx._types.HeaderTypes] = None, + cookies: Optional[httpx._types.CookieTypes] = None, + timeout: Union[ + httpx._types.TimeoutTypes, httpx._client.UseClientDefault + ] = httpx.USE_CLIENT_DEFAULT, + extensions: Optional[httpx._types.RequestExtensions] = None, + ) -> httpx.Request: + pass + + +@runtime_checkable +class AsyncHttpClient(Protocol): + async def send( + self, + request: httpx.Request, + *, + stream: bool = False, + auth: Union[ + httpx._types.AuthTypes, httpx._client.UseClientDefault, None + ] = httpx.USE_CLIENT_DEFAULT, + follow_redirects: Union[ + bool, httpx._client.UseClientDefault + ] = httpx.USE_CLIENT_DEFAULT, + ) -> httpx.Response: + pass + + def build_request( + self, + method: str, + url: httpx._types.URLTypes, + *, + content: Optional[httpx._types.RequestContent] = None, + data: Optional[httpx._types.RequestData] = None, + files: Optional[httpx._types.RequestFiles] = None, + json: Optional[Any] = None, + params: Optional[httpx._types.QueryParamTypes] = None, + headers: Optional[httpx._types.HeaderTypes] = None, + cookies: Optional[httpx._types.CookieTypes] = None, + timeout: Union[ + httpx._types.TimeoutTypes, httpx._client.UseClientDefault + ] = httpx.USE_CLIENT_DEFAULT, + extensions: Optional[httpx._types.RequestExtensions] = None, + ) -> httpx.Request: + pass diff --git a/message/src/epilot_message/internal.py b/message/src/epilot_message/internal.py new file mode 100644 index 000000000..f952af4d7 --- /dev/null +++ b/message/src/epilot_message/internal.py @@ -0,0 +1,164 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .basesdk import BaseSDK +from epilot_message import models, utils +from epilot_message._hooks import HookContext +from epilot_message.types import OptionalNullable, UNSET +from typing import Optional + +class Internal(BaseSDK): + + + def get_gen_ai_feedback( + self, *, + from_: Optional[float] = 0, + size: Optional[float] = 10, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.GetGenAIFeedbackResponseBody]: + r"""getGenAIFeedback + + Fetch the feedback list for genai + + :param from_: + :param size: Number of feedback to return + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.GetGenAIFeedbackRequest( + from_=from_, + size=size, + ) + + req = self.build_request( + method="GET", + path="/v1/message/threads/genai:feedback", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="getGenAIFeedback", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "200", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.GetGenAIFeedbackResponseBody]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def get_gen_ai_feedback_async( + self, *, + from_: Optional[float] = 0, + size: Optional[float] = 10, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.GetGenAIFeedbackResponseBody]: + r"""getGenAIFeedback + + Fetch the feedback list for genai + + :param from_: + :param size: Number of feedback to return + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.GetGenAIFeedbackRequest( + from_=from_, + size=size, + ) + + req = self.build_request( + method="GET", + path="/v1/message/threads/genai:feedback", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="getGenAIFeedback", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "200", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.GetGenAIFeedbackResponseBody]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + diff --git a/message/src/epilot_message/messages.py b/message/src/epilot_message/messages.py new file mode 100644 index 000000000..381f6a2af --- /dev/null +++ b/message/src/epilot_message/messages.py @@ -0,0 +1,1360 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .basesdk import BaseSDK +from epilot_message import models, utils +from epilot_message._hooks import HookContext +from epilot_message.types import OptionalNullable, UNSET +from typing import Optional, Union + +class Messages(BaseSDK): + + + def delete_message( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""deleteMessage + + Immediately and permanently delete a message. This operation cannot be undone. + + :param id: Message ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.DeleteMessageRequest( + id=id, + ) + + req = self.build_request( + method="DELETE", + path="/v1/message/messages/{id}", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="deleteMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def delete_message_async( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""deleteMessage + + Immediately and permanently delete a message. This operation cannot be undone. + + :param id: Message ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.DeleteMessageRequest( + id=id, + ) + + req = self.build_request( + method="DELETE", + path="/v1/message/messages/{id}", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="deleteMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def get_message( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> models.GetMessageResponse: + r"""getMessage + + Get an email message by id + + :param id: Message ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.GetMessageRequest( + id=id, + ) + + req = self.build_request( + method="GET", + path="/v1/message/messages/{id}", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="getMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "200", "application/json"): + return models.GetMessageResponse(result=utils.unmarshal_json(http_res.text, Optional[models.GetMessageResponseBody]), headers={}) + if utils.match_response(http_res, "302", "*"): + return models.GetMessageResponse(headers=utils.get_response_headers(http_res.headers)) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def get_message_async( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> models.GetMessageResponse: + r"""getMessage + + Get an email message by id + + :param id: Message ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.GetMessageRequest( + id=id, + ) + + req = self.build_request( + method="GET", + path="/v1/message/messages/{id}", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="getMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "200", "application/json"): + return models.GetMessageResponse(result=utils.unmarshal_json(http_res.text, Optional[models.GetMessageResponseBody]), headers={}) + if utils.match_response(http_res, "302", "*"): + return models.GetMessageResponse(headers=utils.get_response_headers(http_res.headers)) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def get_message_v2( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.MessageV2]: + r"""getMessageV2 + + - Fetches message by ID + - If the message html is omitted on the entity, then it keeps the content on the message as a signed url + { + ... + _id: \"4d74976d-fb64-47fd-85e2-65eea140f5eb\", + _schema: \"message\", + _org: \"org-123\", + html_omitted: true, + html_download_url: \"https://s3.eu-central-1.amazonaws.com/epilot-attachments/3f34ce73-089c-4d45-a5ee-c161234e41c3/3f34ce73-089c-4d45-a5ee-c161234e41c3.html\" + } + + + :param id: Message ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.GetMessageV2Request( + id=id, + ) + + req = self.build_request( + method="GET", + path="/v2/message/messages/{id}", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="getMessageV2", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "200", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.MessageV2]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def get_message_v2_async( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.MessageV2]: + r"""getMessageV2 + + - Fetches message by ID + - If the message html is omitted on the entity, then it keeps the content on the message as a signed url + { + ... + _id: \"4d74976d-fb64-47fd-85e2-65eea140f5eb\", + _schema: \"message\", + _org: \"org-123\", + html_omitted: true, + html_download_url: \"https://s3.eu-central-1.amazonaws.com/epilot-attachments/3f34ce73-089c-4d45-a5ee-c161234e41c3/3f34ce73-089c-4d45-a5ee-c161234e41c3.html\" + } + + + :param id: Message ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.GetMessageV2Request( + id=id, + ) + + req = self.build_request( + method="GET", + path="/v2/message/messages/{id}", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="getMessageV2", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "200", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.MessageV2]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def mark_read_message( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""markReadMessage + + Mark message as read + + :param id: Message ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.MarkReadMessageRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/messages/{id}/read", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="markReadMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def mark_read_message_async( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""markReadMessage + + Mark message as read + + :param id: Message ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.MarkReadMessageRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/messages/{id}/read", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="markReadMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def mark_unread_message( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""markUnreadMessage + + Mark message as unread + + :param id: Message ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.MarkUnreadMessageRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/messages/{id}/unread", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="markUnreadMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def mark_unread_message_async( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""markUnreadMessage + + Mark message as unread + + :param id: Message ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.MarkUnreadMessageRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/messages/{id}/unread", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="markUnreadMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def send_message( + self, *, + do_not_create_entities: Optional[bool] = False, + message_request_params: Optional[Union[models.MessageRequestParams, models.MessageRequestParamsTypedDict]] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.MessageRequestParams]: + r"""sendMessage + + Send an email message + + :param do_not_create_entities: When true, this flag lets the caller to send only the message and by-pass creating the thread & message entities. + :param message_request_params: + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.SendMessageRequest( + do_not_create_entities=do_not_create_entities, + message_request_params=utils.get_pydantic_model(message_request_params, Optional[models.MessageRequestParams]), + ) + + req = self.build_request( + method="POST", + path="/v1/message/messages", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body(request.message_request_params, False, True, "json", Optional[models.MessageRequestParams]), + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="sendMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "201", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.MessageRequestParams]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def send_message_async( + self, *, + do_not_create_entities: Optional[bool] = False, + message_request_params: Optional[Union[models.MessageRequestParams, models.MessageRequestParamsTypedDict]] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.MessageRequestParams]: + r"""sendMessage + + Send an email message + + :param do_not_create_entities: When true, this flag lets the caller to send only the message and by-pass creating the thread & message entities. + :param message_request_params: + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.SendMessageRequest( + do_not_create_entities=do_not_create_entities, + message_request_params=utils.get_pydantic_model(message_request_params, Optional[models.MessageRequestParams]), + ) + + req = self.build_request( + method="POST", + path="/v1/message/messages", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body(request.message_request_params, False, True, "json", Optional[models.MessageRequestParams]), + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="sendMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "201", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.MessageRequestParams]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def trash_message( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""trashMessage + + Move a message to the trash + + :param id: Message ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.TrashMessageRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/messages/{id}/trash", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="trashMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def trash_message_async( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""trashMessage + + Move a message to the trash + + :param id: Message ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.TrashMessageRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/messages/{id}/trash", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="trashMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def untrash_message( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""untrashMessage + + Restore a trashed message + + :param id: Message ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.UntrashMessageRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/messages/{id}/untrash", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="untrashMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def untrash_message_async( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""untrashMessage + + Restore a trashed message + + :param id: Message ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.UntrashMessageRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/messages/{id}/untrash", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="untrashMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def update_message( + self, *, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.UpdateMessageResponseBody]: + r"""updateMessage + + Update message metadata + + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + req = self.build_request( + method="PUT", + path="/v1/message/messages", + base_url=base_url, + url_variables=url_variables, + request=None, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="updateMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "201", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.UpdateMessageResponseBody]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def update_message_async( + self, *, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.UpdateMessageResponseBody]: + r"""updateMessage + + Update message metadata + + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + req = self.build_request( + method="PUT", + path="/v1/message/messages", + base_url=base_url, + url_variables=url_variables, + request=None, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="updateMessage", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "201", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.UpdateMessageResponseBody]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + diff --git a/message/src/epilot_message/models/__init__.py b/message/src/epilot_message/models/__init__.py new file mode 100644 index 000000000..cfcd3c681 --- /dev/null +++ b/message/src/epilot_message/models/__init__.py @@ -0,0 +1,37 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .address import Address, AddressTypedDict, EmailType, SendError, SendErrorTypedDict, SendStatus +from .assignthreadop import AssignThreadRequest, AssignThreadRequestTypedDict, RequestBody, RequestBodyTypedDict +from .assignusersop import AssignUsersRequest, AssignUsersRequestBody, AssignUsersRequestBodyTypedDict, AssignUsersRequestTypedDict +from .attachmentsrelation import AttachmentsRelation, AttachmentsRelationTypedDict +from .createdraftop import CreateDraftResponseBody, CreateDraftResponseBodyTypedDict, CreateDraftSendStatus, CreateDraftType +from .deletemessageop import DeleteMessageRequest, DeleteMessageRequestTypedDict +from .deletethreadop import DeleteThreadRequest, DeleteThreadRequestTypedDict +from .file import File, FileTypedDict +from .generatesuggestedreplyop import GenerateSuggestedReplyRequest, GenerateSuggestedReplyRequestTypedDict, GenerateSuggestedReplyResponseBody, GenerateSuggestedReplyResponseBodyTypedDict, GenerateSuggestedReplyStatus, GenerateSuggestedReplyType, Payload, PayloadTypedDict +from .getgenaifeedbackop import GetGenAIFeedbackRequest, GetGenAIFeedbackRequestTypedDict, GetGenAIFeedbackResponseBody, GetGenAIFeedbackResponseBodyTypedDict, GetGenAIFeedbackResults, GetGenAIFeedbackResultsTypedDict, GetGenAIFeedbackType +from .getinfoop import GetInfoGenAIPayload, GetInfoGenAIPayloadTypedDict, GetInfoGenAIResponseBody, GetInfoGenAIResponseBodyTypedDict, GetInfoGenAIStatus, GetInfoGenAIType, GetInfoPayload, GetInfoPayloadTypedDict, GetInfoRequest, GetInfoRequestTypedDict, GetInfoResponse, GetInfoResponseBody, GetInfoResponseBodyTypedDict, GetInfoResponseTypedDict, GetInfoStatus, GetInfoType +from .getmessageop import GetMessageRequest, GetMessageRequestTypedDict, GetMessageResponse, GetMessageResponseBody, GetMessageResponseBodyTypedDict, GetMessageResponseTypedDict, GetMessageSendStatus, GetMessageType +from .getmessagev2op import GetMessageV2Request, GetMessageV2RequestTypedDict +from .markreadmessageop import MarkReadMessageRequest, MarkReadMessageRequestTypedDict +from .markreadthreadop import MarkReadThreadRequest, MarkReadThreadRequestTypedDict +from .markunreadmessageop import MarkUnreadMessageRequest, MarkUnreadMessageRequestTypedDict +from .markunreadthreadop import MarkUnreadThreadRequest, MarkUnreadThreadRequestTypedDict +from .message import Message, MessageSendStatus, MessageTypedDict, Type +from .messagerequestparams import MessageRequestParams, MessageRequestParamsTypedDict, Thread, ThreadTypedDict +from .messagev2 import MessageV2, MessageV2SendStatus, MessageV2Type, MessageV2TypedDict +from .patchinfoop import PatchInfoGenAIResponseBody, PatchInfoGenAIResponseBodyData, PatchInfoPayload, PatchInfoPayloadTypedDict, PatchInfoRequest, PatchInfoRequestBody, PatchInfoRequestBodyTypedDict, PatchInfoRequestTypedDict, PatchInfoResponseBody, PatchInfoResponseBodyTypedDict, PatchInfoStatus, PatchInfoType, Status +from .sdkerror import SDKError +from .searchparams import SearchParams, SearchParamsTypedDict +from .searchthreadsop import Results, ResultsTypedDict, SearchThreadsResponseBody, SearchThreadsResponseBodyTypedDict +from .security import Security, SecurityTypedDict +from .senddraftop import SendDraftResponseBody, SendDraftResponseBodyTypedDict, SendDraftSendStatus, SendDraftType +from .sendmessageop import SendMessageRequest, SendMessageRequestTypedDict +from .trashmessageop import TrashMessageRequest, TrashMessageRequestTypedDict +from .trashthreadop import TrashThreadRequest, TrashThreadRequestTypedDict +from .untrashmessageop import UntrashMessageRequest, UntrashMessageRequestTypedDict +from .untrashthreadop import UntrashThreadRequest, UntrashThreadRequestTypedDict +from .updatemessageop import UpdateMessageResponseBody, UpdateMessageResponseBodyTypedDict, UpdateMessageSendStatus, UpdateMessageType +from .updatethreadop import UpdateThreadResponseBody, UpdateThreadResponseBodyTypedDict + +__all__ = ["Address", "AddressTypedDict", "AssignThreadRequest", "AssignThreadRequestTypedDict", "AssignUsersRequest", "AssignUsersRequestBody", "AssignUsersRequestBodyTypedDict", "AssignUsersRequestTypedDict", "AttachmentsRelation", "AttachmentsRelationTypedDict", "CreateDraftResponseBody", "CreateDraftResponseBodyTypedDict", "CreateDraftSendStatus", "CreateDraftType", "DeleteMessageRequest", "DeleteMessageRequestTypedDict", "DeleteThreadRequest", "DeleteThreadRequestTypedDict", "EmailType", "File", "FileTypedDict", "GenerateSuggestedReplyRequest", "GenerateSuggestedReplyRequestTypedDict", "GenerateSuggestedReplyResponseBody", "GenerateSuggestedReplyResponseBodyTypedDict", "GenerateSuggestedReplyStatus", "GenerateSuggestedReplyType", "GetGenAIFeedbackRequest", "GetGenAIFeedbackRequestTypedDict", "GetGenAIFeedbackResponseBody", "GetGenAIFeedbackResponseBodyTypedDict", "GetGenAIFeedbackResults", "GetGenAIFeedbackResultsTypedDict", "GetGenAIFeedbackType", "GetInfoGenAIPayload", "GetInfoGenAIPayloadTypedDict", "GetInfoGenAIResponseBody", "GetInfoGenAIResponseBodyTypedDict", "GetInfoGenAIStatus", "GetInfoGenAIType", "GetInfoPayload", "GetInfoPayloadTypedDict", "GetInfoRequest", "GetInfoRequestTypedDict", "GetInfoResponse", "GetInfoResponseBody", "GetInfoResponseBodyTypedDict", "GetInfoResponseTypedDict", "GetInfoStatus", "GetInfoType", "GetMessageRequest", "GetMessageRequestTypedDict", "GetMessageResponse", "GetMessageResponseBody", "GetMessageResponseBodyTypedDict", "GetMessageResponseTypedDict", "GetMessageSendStatus", "GetMessageType", "GetMessageV2Request", "GetMessageV2RequestTypedDict", "MarkReadMessageRequest", "MarkReadMessageRequestTypedDict", "MarkReadThreadRequest", "MarkReadThreadRequestTypedDict", "MarkUnreadMessageRequest", "MarkUnreadMessageRequestTypedDict", "MarkUnreadThreadRequest", "MarkUnreadThreadRequestTypedDict", "Message", "MessageRequestParams", "MessageRequestParamsTypedDict", "MessageSendStatus", "MessageTypedDict", "MessageV2", "MessageV2SendStatus", "MessageV2Type", "MessageV2TypedDict", "PatchInfoGenAIResponseBody", "PatchInfoGenAIResponseBodyData", "PatchInfoPayload", "PatchInfoPayloadTypedDict", "PatchInfoRequest", "PatchInfoRequestBody", "PatchInfoRequestBodyTypedDict", "PatchInfoRequestTypedDict", "PatchInfoResponseBody", "PatchInfoResponseBodyTypedDict", "PatchInfoStatus", "PatchInfoType", "Payload", "PayloadTypedDict", "RequestBody", "RequestBodyTypedDict", "Results", "ResultsTypedDict", "SDKError", "SearchParams", "SearchParamsTypedDict", "SearchThreadsResponseBody", "SearchThreadsResponseBodyTypedDict", "Security", "SecurityTypedDict", "SendDraftResponseBody", "SendDraftResponseBodyTypedDict", "SendDraftSendStatus", "SendDraftType", "SendError", "SendErrorTypedDict", "SendMessageRequest", "SendMessageRequestTypedDict", "SendStatus", "Status", "Thread", "ThreadTypedDict", "TrashMessageRequest", "TrashMessageRequestTypedDict", "TrashThreadRequest", "TrashThreadRequestTypedDict", "Type", "UntrashMessageRequest", "UntrashMessageRequestTypedDict", "UntrashThreadRequest", "UntrashThreadRequestTypedDict", "UpdateMessageResponseBody", "UpdateMessageResponseBodyTypedDict", "UpdateMessageSendStatus", "UpdateMessageType", "UpdateThreadResponseBody", "UpdateThreadResponseBodyTypedDict"] diff --git a/message/src/epilot_message/models/address.py b/message/src/epilot_message/models/address.py new file mode 100644 index 000000000..3ddf09979 --- /dev/null +++ b/message/src/epilot_message/models/address.py @@ -0,0 +1,106 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from enum import Enum +from epilot_message.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL +from pydantic import model_serializer +from typing import Optional, TypedDict +from typing_extensions import NotRequired + + +class EmailType(str, Enum): + r"""Type of the email, Internal (360 Agents), Partners, External users(Customers) + + """ + INTERNAL = "INTERNAL" + EXTERNAL = "EXTERNAL" + PARTNER = "PARTNER" + +class SendErrorTypedDict(TypedDict): + r"""Information about reject, complaint or bounce event. Only available if `send_status` is REJECT, COMPLAINT, BOUNCE or ERROR. JSON object is defined by AWS SES. Reference at + + """ + + + +class SendError(BaseModel): + r"""Information about reject, complaint or bounce event. Only available if `send_status` is REJECT, COMPLAINT, BOUNCE or ERROR. JSON object is defined by AWS SES. Reference at + + """ + + + +class SendStatus(str, Enum): + r"""Sent message status regarding to this recipient. Reference at + + """ + SEND = "SEND" + DELIVERY = "DELIVERY" + REJECT = "REJECT" + COMPLAINT = "COMPLAINT" + BOUNCE = "BOUNCE" + ERROR = "ERROR" + +class AddressTypedDict(TypedDict): + address: str + r"""Email address""" + email_type: NotRequired[Nullable[EmailType]] + r"""Type of the email, Internal (360 Agents), Partners, External users(Customers) + + """ + name: NotRequired[str] + r"""Email address alias""" + send_error: NotRequired[SendErrorTypedDict] + r"""Information about reject, complaint or bounce event. Only available if `send_status` is REJECT, COMPLAINT, BOUNCE or ERROR. JSON object is defined by AWS SES. Reference at + + """ + send_status: NotRequired[SendStatus] + r"""Sent message status regarding to this recipient. Reference at + + """ + + +class Address(BaseModel): + address: str + r"""Email address""" + email_type: OptionalNullable[EmailType] = UNSET + r"""Type of the email, Internal (360 Agents), Partners, External users(Customers) + + """ + name: Optional[str] = None + r"""Email address alias""" + send_error: Optional[SendError] = None + r"""Information about reject, complaint or bounce event. Only available if `send_status` is REJECT, COMPLAINT, BOUNCE or ERROR. JSON object is defined by AWS SES. Reference at + + """ + send_status: Optional[SendStatus] = None + r"""Sent message status regarding to this recipient. Reference at + + """ + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = ["email_type", "name", "send_error", "send_status"] + nullable_fields = ["email_type"] + null_default_fields = [] + + serialized = handler(self) + + m = {} + + for n, f in self.model_fields.items(): + k = f.alias or n + val = serialized.get(k) + + optional_nullable = k in optional_fields and k in nullable_fields + is_set = (self.__pydantic_fields_set__.intersection({n}) or k in null_default_fields) # pylint: disable=no-member + + if val is not None and val != UNSET_SENTINEL: + m[k] = val + elif val != UNSET_SENTINEL and ( + not k in optional_fields or (optional_nullable and is_set) + ): + m[k] = val + + return m + diff --git a/message/src/epilot_message/models/assignthreadop.py b/message/src/epilot_message/models/assignthreadop.py new file mode 100644 index 000000000..b1c00165d --- /dev/null +++ b/message/src/epilot_message/models/assignthreadop.py @@ -0,0 +1,38 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, PathParamMetadata, RequestMetadata +from typing import List, Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class RequestBodyTypedDict(TypedDict): + entity_id: NotRequired[str] + r"""Entity ID""" + is_main_entity: NotRequired[bool] + r"""To indicate this is main entity""" + slug: NotRequired[str] + r"""Entity slug""" + + +class RequestBody(BaseModel): + entity_id: Optional[str] = None + r"""Entity ID""" + is_main_entity: Optional[bool] = None + r"""To indicate this is main entity""" + slug: Optional[str] = None + r"""Entity slug""" + + +class AssignThreadRequestTypedDict(TypedDict): + request_body: List[RequestBodyTypedDict] + id: str + r"""Thread ID""" + + +class AssignThreadRequest(BaseModel): + request_body: Annotated[List[RequestBody], FieldMetadata(request=RequestMetadata(media_type="application/json"))] + id: Annotated[str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Thread ID""" + diff --git a/message/src/epilot_message/models/assignusersop.py b/message/src/epilot_message/models/assignusersop.py new file mode 100644 index 000000000..afdac6785 --- /dev/null +++ b/message/src/epilot_message/models/assignusersop.py @@ -0,0 +1,34 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, PathParamMetadata, RequestMetadata +from typing import List, Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class AssignUsersRequestBodyTypedDict(TypedDict): + r"""User IDs of users assigned to thread""" + + assigned_to: NotRequired[List[str]] + r"""IDs of users assigned to thread""" + + +class AssignUsersRequestBody(BaseModel): + r"""User IDs of users assigned to thread""" + + assigned_to: Optional[List[str]] = None + r"""IDs of users assigned to thread""" + + +class AssignUsersRequestTypedDict(TypedDict): + request_body: AssignUsersRequestBodyTypedDict + id: str + r"""Thread ID""" + + +class AssignUsersRequest(BaseModel): + request_body: Annotated[AssignUsersRequestBody, FieldMetadata(request=RequestMetadata(media_type="application/json"))] + id: Annotated[str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Thread ID""" + diff --git a/message/src/epilot_message/models/attachmentsrelation.py b/message/src/epilot_message/models/attachmentsrelation.py new file mode 100644 index 000000000..cc27fe432 --- /dev/null +++ b/message/src/epilot_message/models/attachmentsrelation.py @@ -0,0 +1,23 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .file import File, FileTypedDict +from epilot_message.types import BaseModel +import pydantic +from typing import List, Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class AttachmentsRelationTypedDict(TypedDict): + r"""Message attachments""" + + dollar_relation: NotRequired[List[FileTypedDict]] + r"""It's normal entity relation with some additional properties for sending message attachment.""" + + +class AttachmentsRelation(BaseModel): + r"""Message attachments""" + + dollar_relation: Annotated[Optional[List[File]], pydantic.Field(alias="$relation")] = None + r"""It's normal entity relation with some additional properties for sending message attachment.""" + diff --git a/message/src/epilot_message/models/createdraftop.py b/message/src/epilot_message/models/createdraftop.py new file mode 100644 index 000000000..aafbcbcb4 --- /dev/null +++ b/message/src/epilot_message/models/createdraftop.py @@ -0,0 +1,139 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .address import Address, AddressTypedDict +from .attachmentsrelation import AttachmentsRelation, AttachmentsRelationTypedDict +from datetime import datetime +from enum import Enum +from epilot_message.types import BaseModel +import pydantic +from typing import List, Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class CreateDraftSendStatus(str, Enum): + SEND = "SEND" + DELIVERY = "DELIVERY" + REJECT = "REJECT" + COMPLAINT = "COMPLAINT" + BOUNCE = "BOUNCE" + ERROR = "ERROR" + +class CreateDraftType(str, Enum): + r"""Message type""" + SENT = "SENT" + RECEIVED = "RECEIVED" + +class CreateDraftResponseBodyTypedDict(TypedDict): + r"""Success""" + + created_at: datetime + r"""Created date""" + id: str + r"""Entity ID""" + org: str + r"""Ivy Organization ID the entity belongs to""" + schema_: str + r"""URL-friendly identifier for the entity schema""" + title: str + r"""Entity title""" + updated_at: datetime + r"""Updated date""" + from_: AddressTypedDict + subject: str + r"""Subject""" + tags: NotRequired[List[str]] + r"""Entity tags""" + bcc: NotRequired[List[AddressTypedDict]] + r"""Bcc email addresses""" + cc: NotRequired[List[AddressTypedDict]] + r"""Cc email addresses""" + file: NotRequired[AttachmentsRelationTypedDict] + r"""Message attachments""" + html: NotRequired[str] + r"""HTML body""" + in_reply_to: NotRequired[str] + r"""In-Reply-To header. Value is the `message_id` of parent message. + + """ + message_id: NotRequired[str] + r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" + org_read_message: NotRequired[List[str]] + r"""Ivy Organization ID of organization read the message.""" + references: NotRequired[str] + r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. + + """ + reply_to: NotRequired[AddressTypedDict] + send_status: NotRequired[List[CreateDraftSendStatus]] + r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at + + """ + sender: NotRequired[str] + r"""Ivy User ID of user sends the message.""" + text: NotRequired[str] + r"""Text body""" + to: NotRequired[List[AddressTypedDict]] + r"""To email addresses""" + type: NotRequired[CreateDraftType] + r"""Message type""" + user_read_message: NotRequired[List[str]] + r"""Ivy User ID of user read the message.""" + + +class CreateDraftResponseBody(BaseModel): + r"""Success""" + + created_at: Annotated[datetime, pydantic.Field(alias="_created_at")] + r"""Created date""" + id: Annotated[str, pydantic.Field(alias="_id")] + r"""Entity ID""" + org: Annotated[str, pydantic.Field(alias="_org")] + r"""Ivy Organization ID the entity belongs to""" + schema_: Annotated[str, pydantic.Field(alias="_schema")] + r"""URL-friendly identifier for the entity schema""" + title: Annotated[str, pydantic.Field(alias="_title")] + r"""Entity title""" + updated_at: Annotated[datetime, pydantic.Field(alias="_updated_at")] + r"""Updated date""" + from_: Annotated[Address, pydantic.Field(alias="from")] + subject: str + r"""Subject""" + tags: Annotated[Optional[List[str]], pydantic.Field(alias="_tags")] = None + r"""Entity tags""" + bcc: Optional[List[Address]] = None + r"""Bcc email addresses""" + cc: Optional[List[Address]] = None + r"""Cc email addresses""" + file: Optional[AttachmentsRelation] = None + r"""Message attachments""" + html: Optional[str] = None + r"""HTML body""" + in_reply_to: Optional[str] = None + r"""In-Reply-To header. Value is the `message_id` of parent message. + + """ + message_id: Optional[str] = None + r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" + org_read_message: Optional[List[str]] = None + r"""Ivy Organization ID of organization read the message.""" + references: Optional[str] = None + r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. + + """ + reply_to: Optional[Address] = None + send_status: Optional[List[CreateDraftSendStatus]] = None + r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at + + """ + sender: Optional[str] = None + r"""Ivy User ID of user sends the message.""" + text: Optional[str] = None + r"""Text body""" + to: Optional[List[Address]] = None + r"""To email addresses""" + type: Optional[CreateDraftType] = None + r"""Message type""" + user_read_message: Optional[List[str]] = None + r"""Ivy User ID of user read the message.""" + diff --git a/message/src/epilot_message/models/deletemessageop.py b/message/src/epilot_message/models/deletemessageop.py new file mode 100644 index 000000000..cb1cff993 --- /dev/null +++ b/message/src/epilot_message/models/deletemessageop.py @@ -0,0 +1,18 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, PathParamMetadata +from typing import TypedDict +from typing_extensions import Annotated + + +class DeleteMessageRequestTypedDict(TypedDict): + id: str + r"""Message ID""" + + +class DeleteMessageRequest(BaseModel): + id: Annotated[str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Message ID""" + diff --git a/message/src/epilot_message/models/deletethreadop.py b/message/src/epilot_message/models/deletethreadop.py new file mode 100644 index 000000000..ca0894383 --- /dev/null +++ b/message/src/epilot_message/models/deletethreadop.py @@ -0,0 +1,18 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, PathParamMetadata +from typing import TypedDict +from typing_extensions import Annotated + + +class DeleteThreadRequestTypedDict(TypedDict): + id: str + r"""Thread ID""" + + +class DeleteThreadRequest(BaseModel): + id: Annotated[str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Thread ID""" + diff --git a/message/src/epilot_message/models/file.py b/message/src/epilot_message/models/file.py new file mode 100644 index 000000000..bb269d047 --- /dev/null +++ b/message/src/epilot_message/models/file.py @@ -0,0 +1,45 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from typing import Optional, TypedDict +from typing_extensions import NotRequired + + +class FileTypedDict(TypedDict): + entity_id: str + r"""File entity ID""" + cid: NotRequired[str] + r"""Content ID (for inline)""" + filename: NotRequired[str] + r"""File name""" + inline: NotRequired[bool] + r"""If true then this attachment should not be offered for download (at least not in the main attachments list). The usecase is CID embedded image (aka inline image). + + """ + is_message_attachment: NotRequired[bool] + r"""To indicate this file relation is message attachment. If false then this file will not be sent and simply kept as a file relation.""" + send_as_link: NotRequired[bool] + r"""If true then this attachment is sent via link. The link have to be inserted to email body by API caller. In this case, service doesn't process this attachment. + + """ + + +class File(BaseModel): + entity_id: str + r"""File entity ID""" + cid: Optional[str] = None + r"""Content ID (for inline)""" + filename: Optional[str] = None + r"""File name""" + inline: Optional[bool] = False + r"""If true then this attachment should not be offered for download (at least not in the main attachments list). The usecase is CID embedded image (aka inline image). + + """ + is_message_attachment: Optional[bool] = None + r"""To indicate this file relation is message attachment. If false then this file will not be sent and simply kept as a file relation.""" + send_as_link: Optional[bool] = False + r"""If true then this attachment is sent via link. The link have to be inserted to email body by API caller. In this case, service doesn't process this attachment. + + """ + diff --git a/message/src/epilot_message/models/generatesuggestedreplyop.py b/message/src/epilot_message/models/generatesuggestedreplyop.py new file mode 100644 index 000000000..6058ad8e7 --- /dev/null +++ b/message/src/epilot_message/models/generatesuggestedreplyop.py @@ -0,0 +1,129 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from enum import Enum +from epilot_message.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL +from epilot_message.utils import FieldMetadata, PathParamMetadata, QueryParamMetadata +import pydantic +from pydantic import model_serializer +from typing import Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class GenerateSuggestedReplyRequestTypedDict(TypedDict): + message_id: str + r"""Message ID""" + thread_id: str + r"""Thread ID""" + + +class GenerateSuggestedReplyRequest(BaseModel): + message_id: Annotated[str, pydantic.Field(alias="messageId"), FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Message ID""" + thread_id: Annotated[str, pydantic.Field(alias="threadId"), FieldMetadata(query=QueryParamMetadata(style="form", explode=True))] + r"""Thread ID""" + + +class GenerateSuggestedReplyStatus(str, Enum): + r"""Status of the GenAI job""" + INITIATED = "INITIATED" + IN_PROGRESS = "IN_PROGRESS" + COMPLETED = "COMPLETED" + FAILED = "FAILED" + +class PayloadTypedDict(TypedDict): + created_at: NotRequired[float] + r"""Job created date""" + error: NotRequired[Nullable[str]] + r"""Error message if the job failed""" + feedback: NotRequired[Nullable[str]] + r"""Feedback of the suggested reply""" + progress: NotRequired[float] + r"""Progress of the GenAI job in percentage""" + rating: NotRequired[Nullable[str]] + r"""Rating of the suggested reply""" + status: NotRequired[GenerateSuggestedReplyStatus] + r"""Status of the GenAI job""" + suggested_reply: NotRequired[Nullable[str]] + r"""Suggested reply""" + updated_at: NotRequired[float] + r"""Job last updated date""" + + +class Payload(BaseModel): + created_at: Optional[float] = None + r"""Job created date""" + error: OptionalNullable[str] = UNSET + r"""Error message if the job failed""" + feedback: OptionalNullable[str] = UNSET + r"""Feedback of the suggested reply""" + progress: Optional[float] = None + r"""Progress of the GenAI job in percentage""" + rating: OptionalNullable[str] = UNSET + r"""Rating of the suggested reply""" + status: Optional[GenerateSuggestedReplyStatus] = None + r"""Status of the GenAI job""" + suggested_reply: OptionalNullable[str] = UNSET + r"""Suggested reply""" + updated_at: Optional[float] = None + r"""Job last updated date""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = ["created_at", "error", "feedback", "progress", "rating", "status", "suggested_reply", "updated_at"] + nullable_fields = ["error", "feedback", "rating", "suggested_reply"] + null_default_fields = [] + + serialized = handler(self) + + m = {} + + for n, f in self.model_fields.items(): + k = f.alias or n + val = serialized.get(k) + + optional_nullable = k in optional_fields and k in nullable_fields + is_set = (self.__pydantic_fields_set__.intersection({n}) or k in null_default_fields) # pylint: disable=no-member + + if val is not None and val != UNSET_SENTINEL: + m[k] = val + elif val != UNSET_SENTINEL and ( + not k in optional_fields or (optional_nullable and is_set) + ): + m[k] = val + + return m + + +class GenerateSuggestedReplyType(str, Enum): + r"""Job type""" + INFO = "INFO" + REPLY = "REPLY" + +class GenerateSuggestedReplyResponseBodyTypedDict(TypedDict): + r"""Success""" + + message_id: NotRequired[str] + r"""Message ID""" + org_id: NotRequired[str] + r"""Organization ID""" + payload: NotRequired[PayloadTypedDict] + thread_id: NotRequired[str] + r"""Thread ID""" + type: NotRequired[GenerateSuggestedReplyType] + r"""Job type""" + + +class GenerateSuggestedReplyResponseBody(BaseModel): + r"""Success""" + + message_id: Optional[str] = None + r"""Message ID""" + org_id: Optional[str] = None + r"""Organization ID""" + payload: Optional[Payload] = None + thread_id: Optional[str] = None + r"""Thread ID""" + type: Optional[GenerateSuggestedReplyType] = None + r"""Job type""" + diff --git a/message/src/epilot_message/models/getgenaifeedbackop.py b/message/src/epilot_message/models/getgenaifeedbackop.py new file mode 100644 index 000000000..d615955e2 --- /dev/null +++ b/message/src/epilot_message/models/getgenaifeedbackop.py @@ -0,0 +1,113 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from datetime import datetime +from enum import Enum +from epilot_message.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL +from epilot_message.utils import FieldMetadata, QueryParamMetadata +import pydantic +from pydantic import model_serializer +from typing import List, Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class GetGenAIFeedbackRequestTypedDict(TypedDict): + from_: NotRequired[float] + size: NotRequired[float] + r"""Number of feedback to return""" + + +class GetGenAIFeedbackRequest(BaseModel): + from_: Annotated[Optional[float], pydantic.Field(alias="from"), FieldMetadata(query=QueryParamMetadata(style="form", explode=True))] = 0 + size: Annotated[Optional[float], FieldMetadata(query=QueryParamMetadata(style="form", explode=True))] = 10 + r"""Number of feedback to return""" + + +class GetGenAIFeedbackType(str, Enum): + r"""Job type""" + INFO = "INFO" + REPLY = "REPLY" + +class GetGenAIFeedbackResultsTypedDict(TypedDict): + created_at: NotRequired[datetime] + r"""Created date""" + feedback: NotRequired[Nullable[str]] + r"""Feedback of the suggested reply""" + last_updated_at: NotRequired[datetime] + r"""Updated date""" + message_id: NotRequired[str] + r"""Message ID""" + org_id: NotRequired[str] + r"""Organization ID""" + org_name: NotRequired[str] + r"""Name of the org""" + rating: NotRequired[Nullable[str]] + r"""Rating of the suggested reply""" + thread_id: NotRequired[str] + r"""Thread ID""" + type: NotRequired[GetGenAIFeedbackType] + r"""Job type""" + + +class GetGenAIFeedbackResults(BaseModel): + created_at: Optional[datetime] = None + r"""Created date""" + feedback: OptionalNullable[str] = UNSET + r"""Feedback of the suggested reply""" + last_updated_at: Optional[datetime] = None + r"""Updated date""" + message_id: Optional[str] = None + r"""Message ID""" + org_id: Optional[str] = None + r"""Organization ID""" + org_name: Optional[str] = None + r"""Name of the org""" + rating: OptionalNullable[str] = UNSET + r"""Rating of the suggested reply""" + thread_id: Optional[str] = None + r"""Thread ID""" + type: Optional[GetGenAIFeedbackType] = None + r"""Job type""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = ["created_at", "feedback", "last_updated_at", "message_id", "org_id", "org_name", "rating", "thread_id", "type"] + nullable_fields = ["feedback", "rating"] + null_default_fields = [] + + serialized = handler(self) + + m = {} + + for n, f in self.model_fields.items(): + k = f.alias or n + val = serialized.get(k) + + optional_nullable = k in optional_fields and k in nullable_fields + is_set = (self.__pydantic_fields_set__.intersection({n}) or k in null_default_fields) # pylint: disable=no-member + + if val is not None and val != UNSET_SENTINEL: + m[k] = val + elif val != UNSET_SENTINEL and ( + not k in optional_fields or (optional_nullable and is_set) + ): + m[k] = val + + return m + + +class GetGenAIFeedbackResponseBodyTypedDict(TypedDict): + r"""Success""" + + hits: NotRequired[float] + r"""Total hits""" + results: NotRequired[List[GetGenAIFeedbackResultsTypedDict]] + + +class GetGenAIFeedbackResponseBody(BaseModel): + r"""Success""" + + hits: Optional[float] = None + r"""Total hits""" + results: Optional[List[GetGenAIFeedbackResults]] = None + diff --git a/message/src/epilot_message/models/getinfoop.py b/message/src/epilot_message/models/getinfoop.py new file mode 100644 index 000000000..626515ccd --- /dev/null +++ b/message/src/epilot_message/models/getinfoop.py @@ -0,0 +1,263 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from enum import Enum +from epilot_message.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL +from epilot_message.utils import FieldMetadata, PathParamMetadata, QueryParamMetadata +import pydantic +from pydantic import model_serializer +from typing import List, Optional, TypedDict, Union +from typing_extensions import Annotated, NotRequired + + +class GetInfoRequestTypedDict(TypedDict): + thread_id: str + r"""Thread ID""" + message_id: NotRequired[str] + r"""Message ID, If not passed defaults to latest message ID in the thread""" + + +class GetInfoRequest(BaseModel): + thread_id: Annotated[str, pydantic.Field(alias="threadId"), FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Thread ID""" + message_id: Annotated[Optional[str], pydantic.Field(alias="messageId"), FieldMetadata(query=QueryParamMetadata(style="form", explode=True))] = None + r"""Message ID, If not passed defaults to latest message ID in the thread""" + + +class GetInfoGenAIStatus(str, Enum): + r"""Status of the GenAI job""" + INITIATED = "INITIATED" + IN_PROGRESS = "IN_PROGRESS" + COMPLETED = "COMPLETED" + FAILED = "FAILED" + +class GetInfoGenAIPayloadTypedDict(TypedDict): + created_at: NotRequired[float] + r"""Job created date""" + error: NotRequired[Nullable[str]] + r"""Error message if the job failed""" + feedback: NotRequired[Nullable[str]] + r"""Feedback of the suggested reply""" + next_steps: NotRequired[Nullable[List[str]]] + r"""Recommended next steps""" + progress: NotRequired[float] + r"""Progress of the GenAI job in percentage""" + rating: NotRequired[Nullable[str]] + r"""Rating of the suggested reply""" + status: NotRequired[GetInfoGenAIStatus] + r"""Status of the GenAI job""" + summary: NotRequired[Nullable[List[str]]] + r"""Generated summary""" + tags: NotRequired[Nullable[List[str]]] + r"""Tags""" + topics: NotRequired[Nullable[List[str]]] + r"""Topics of the email thread""" + updated_at: NotRequired[float] + r"""Job last updated date""" + + +class GetInfoGenAIPayload(BaseModel): + created_at: Optional[float] = None + r"""Job created date""" + error: OptionalNullable[str] = UNSET + r"""Error message if the job failed""" + feedback: OptionalNullable[str] = UNSET + r"""Feedback of the suggested reply""" + next_steps: OptionalNullable[List[str]] = UNSET + r"""Recommended next steps""" + progress: Optional[float] = None + r"""Progress of the GenAI job in percentage""" + rating: OptionalNullable[str] = UNSET + r"""Rating of the suggested reply""" + status: Optional[GetInfoGenAIStatus] = None + r"""Status of the GenAI job""" + summary: OptionalNullable[List[str]] = UNSET + r"""Generated summary""" + tags: OptionalNullable[List[str]] = UNSET + r"""Tags""" + topics: OptionalNullable[List[str]] = UNSET + r"""Topics of the email thread""" + updated_at: Optional[float] = None + r"""Job last updated date""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = ["created_at", "error", "feedback", "next_steps", "progress", "rating", "status", "summary", "tags", "topics", "updated_at"] + nullable_fields = ["error", "feedback", "next_steps", "rating", "summary", "tags", "topics"] + null_default_fields = [] + + serialized = handler(self) + + m = {} + + for n, f in self.model_fields.items(): + k = f.alias or n + val = serialized.get(k) + + optional_nullable = k in optional_fields and k in nullable_fields + is_set = (self.__pydantic_fields_set__.intersection({n}) or k in null_default_fields) # pylint: disable=no-member + + if val is not None and val != UNSET_SENTINEL: + m[k] = val + elif val != UNSET_SENTINEL and ( + not k in optional_fields or (optional_nullable and is_set) + ): + m[k] = val + + return m + + +class GetInfoGenAIType(str, Enum): + r"""Job type""" + INFO = "INFO" + REPLY = "REPLY" + +class GetInfoGenAIResponseBodyTypedDict(TypedDict): + r"""Accepted""" + + message_id: NotRequired[str] + r"""Message ID""" + org_id: NotRequired[str] + r"""Organization ID""" + payload: NotRequired[GetInfoGenAIPayloadTypedDict] + thread_id: NotRequired[str] + r"""Thread ID""" + type: NotRequired[GetInfoGenAIType] + r"""Job type""" + + +class GetInfoGenAIResponseBody(BaseModel): + r"""Accepted""" + + message_id: Optional[str] = None + r"""Message ID""" + org_id: Optional[str] = None + r"""Organization ID""" + payload: Optional[GetInfoGenAIPayload] = None + thread_id: Optional[str] = None + r"""Thread ID""" + type: Optional[GetInfoGenAIType] = None + r"""Job type""" + + +class GetInfoStatus(str, Enum): + r"""Status of the GenAI job""" + INITIATED = "INITIATED" + IN_PROGRESS = "IN_PROGRESS" + COMPLETED = "COMPLETED" + FAILED = "FAILED" + +class GetInfoPayloadTypedDict(TypedDict): + created_at: NotRequired[float] + r"""Job created date""" + error: NotRequired[Nullable[str]] + r"""Error message if the job failed""" + feedback: NotRequired[Nullable[str]] + r"""Feedback of the suggested reply""" + next_steps: NotRequired[Nullable[List[str]]] + r"""Recommended next steps""" + progress: NotRequired[float] + r"""Progress of the GenAI job in percentage""" + rating: NotRequired[Nullable[str]] + r"""Rating of the suggested reply""" + status: NotRequired[GetInfoStatus] + r"""Status of the GenAI job""" + summary: NotRequired[Nullable[List[str]]] + r"""Generated summary""" + tags: NotRequired[Nullable[List[str]]] + r"""Tags""" + topics: NotRequired[Nullable[List[str]]] + r"""Topics of the email thread""" + updated_at: NotRequired[float] + r"""Job last updated date""" + + +class GetInfoPayload(BaseModel): + created_at: Optional[float] = None + r"""Job created date""" + error: OptionalNullable[str] = UNSET + r"""Error message if the job failed""" + feedback: OptionalNullable[str] = UNSET + r"""Feedback of the suggested reply""" + next_steps: OptionalNullable[List[str]] = UNSET + r"""Recommended next steps""" + progress: Optional[float] = None + r"""Progress of the GenAI job in percentage""" + rating: OptionalNullable[str] = UNSET + r"""Rating of the suggested reply""" + status: Optional[GetInfoStatus] = None + r"""Status of the GenAI job""" + summary: OptionalNullable[List[str]] = UNSET + r"""Generated summary""" + tags: OptionalNullable[List[str]] = UNSET + r"""Tags""" + topics: OptionalNullable[List[str]] = UNSET + r"""Topics of the email thread""" + updated_at: Optional[float] = None + r"""Job last updated date""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = ["created_at", "error", "feedback", "next_steps", "progress", "rating", "status", "summary", "tags", "topics", "updated_at"] + nullable_fields = ["error", "feedback", "next_steps", "rating", "summary", "tags", "topics"] + null_default_fields = [] + + serialized = handler(self) + + m = {} + + for n, f in self.model_fields.items(): + k = f.alias or n + val = serialized.get(k) + + optional_nullable = k in optional_fields and k in nullable_fields + is_set = (self.__pydantic_fields_set__.intersection({n}) or k in null_default_fields) # pylint: disable=no-member + + if val is not None and val != UNSET_SENTINEL: + m[k] = val + elif val != UNSET_SENTINEL and ( + not k in optional_fields or (optional_nullable and is_set) + ): + m[k] = val + + return m + + +class GetInfoType(str, Enum): + r"""Job type""" + INFO = "INFO" + REPLY = "REPLY" + +class GetInfoResponseBodyTypedDict(TypedDict): + r"""Success""" + + message_id: NotRequired[str] + r"""Message ID""" + org_id: NotRequired[str] + r"""Organization ID""" + payload: NotRequired[GetInfoPayloadTypedDict] + thread_id: NotRequired[str] + r"""Thread ID""" + type: NotRequired[GetInfoType] + r"""Job type""" + + +class GetInfoResponseBody(BaseModel): + r"""Success""" + + message_id: Optional[str] = None + r"""Message ID""" + org_id: Optional[str] = None + r"""Organization ID""" + payload: Optional[GetInfoPayload] = None + thread_id: Optional[str] = None + r"""Thread ID""" + type: Optional[GetInfoType] = None + r"""Job type""" + + +GetInfoResponseTypedDict = Union[GetInfoResponseBodyTypedDict, GetInfoGenAIResponseBodyTypedDict] + + +GetInfoResponse = Union[GetInfoResponseBody, GetInfoGenAIResponseBody] + diff --git a/message/src/epilot_message/models/getmessageop.py b/message/src/epilot_message/models/getmessageop.py new file mode 100644 index 000000000..8a49082e3 --- /dev/null +++ b/message/src/epilot_message/models/getmessageop.py @@ -0,0 +1,160 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .address import Address, AddressTypedDict +from .attachmentsrelation import AttachmentsRelation, AttachmentsRelationTypedDict +from datetime import datetime +from enum import Enum +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, PathParamMetadata +import pydantic +from typing import Dict, List, Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class GetMessageRequestTypedDict(TypedDict): + id: str + r"""Message ID""" + + +class GetMessageRequest(BaseModel): + id: Annotated[str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Message ID""" + + +class GetMessageSendStatus(str, Enum): + SEND = "SEND" + DELIVERY = "DELIVERY" + REJECT = "REJECT" + COMPLAINT = "COMPLAINT" + BOUNCE = "BOUNCE" + ERROR = "ERROR" + +class GetMessageType(str, Enum): + r"""Message type""" + SENT = "SENT" + RECEIVED = "RECEIVED" + +class GetMessageResponseBodyTypedDict(TypedDict): + r"""Success""" + + created_at: datetime + r"""Created date""" + id: str + r"""Entity ID""" + org: str + r"""Ivy Organization ID the entity belongs to""" + schema_: str + r"""URL-friendly identifier for the entity schema""" + title: str + r"""Entity title""" + updated_at: datetime + r"""Updated date""" + from_: AddressTypedDict + subject: str + r"""Subject""" + tags: NotRequired[List[str]] + r"""Entity tags""" + bcc: NotRequired[List[AddressTypedDict]] + r"""Bcc email addresses""" + cc: NotRequired[List[AddressTypedDict]] + r"""Cc email addresses""" + file: NotRequired[AttachmentsRelationTypedDict] + r"""Message attachments""" + html: NotRequired[str] + r"""HTML body""" + in_reply_to: NotRequired[str] + r"""In-Reply-To header. Value is the `message_id` of parent message. + + """ + message_id: NotRequired[str] + r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" + org_read_message: NotRequired[List[str]] + r"""Ivy Organization ID of organization read the message.""" + references: NotRequired[str] + r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. + + """ + reply_to: NotRequired[AddressTypedDict] + send_status: NotRequired[List[GetMessageSendStatus]] + r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at + + """ + sender: NotRequired[str] + r"""Ivy User ID of user sends the message.""" + text: NotRequired[str] + r"""Text body""" + to: NotRequired[List[AddressTypedDict]] + r"""To email addresses""" + type: NotRequired[GetMessageType] + r"""Message type""" + user_read_message: NotRequired[List[str]] + r"""Ivy User ID of user read the message.""" + + +class GetMessageResponseBody(BaseModel): + r"""Success""" + + created_at: Annotated[datetime, pydantic.Field(alias="_created_at")] + r"""Created date""" + id: Annotated[str, pydantic.Field(alias="_id")] + r"""Entity ID""" + org: Annotated[str, pydantic.Field(alias="_org")] + r"""Ivy Organization ID the entity belongs to""" + schema_: Annotated[str, pydantic.Field(alias="_schema")] + r"""URL-friendly identifier for the entity schema""" + title: Annotated[str, pydantic.Field(alias="_title")] + r"""Entity title""" + updated_at: Annotated[datetime, pydantic.Field(alias="_updated_at")] + r"""Updated date""" + from_: Annotated[Address, pydantic.Field(alias="from")] + subject: str + r"""Subject""" + tags: Annotated[Optional[List[str]], pydantic.Field(alias="_tags")] = None + r"""Entity tags""" + bcc: Optional[List[Address]] = None + r"""Bcc email addresses""" + cc: Optional[List[Address]] = None + r"""Cc email addresses""" + file: Optional[AttachmentsRelation] = None + r"""Message attachments""" + html: Optional[str] = None + r"""HTML body""" + in_reply_to: Optional[str] = None + r"""In-Reply-To header. Value is the `message_id` of parent message. + + """ + message_id: Optional[str] = None + r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" + org_read_message: Optional[List[str]] = None + r"""Ivy Organization ID of organization read the message.""" + references: Optional[str] = None + r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. + + """ + reply_to: Optional[Address] = None + send_status: Optional[List[GetMessageSendStatus]] = None + r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at + + """ + sender: Optional[str] = None + r"""Ivy User ID of user sends the message.""" + text: Optional[str] = None + r"""Text body""" + to: Optional[List[Address]] = None + r"""To email addresses""" + type: Optional[GetMessageType] = None + r"""Message type""" + user_read_message: Optional[List[str]] = None + r"""Ivy User ID of user read the message.""" + + +class GetMessageResponseTypedDict(TypedDict): + headers: Dict[str, List[str]] + result: GetMessageResponseBodyTypedDict + + +class GetMessageResponse(BaseModel): + headers: Dict[str, List[str]] + result: GetMessageResponseBody + diff --git a/message/src/epilot_message/models/getmessagev2op.py b/message/src/epilot_message/models/getmessagev2op.py new file mode 100644 index 000000000..9749e6a5b --- /dev/null +++ b/message/src/epilot_message/models/getmessagev2op.py @@ -0,0 +1,18 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, PathParamMetadata +from typing import TypedDict +from typing_extensions import Annotated + + +class GetMessageV2RequestTypedDict(TypedDict): + id: str + r"""Message ID""" + + +class GetMessageV2Request(BaseModel): + id: Annotated[str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Message ID""" + diff --git a/message/src/epilot_message/models/markreadmessageop.py b/message/src/epilot_message/models/markreadmessageop.py new file mode 100644 index 000000000..e6c9ec960 --- /dev/null +++ b/message/src/epilot_message/models/markreadmessageop.py @@ -0,0 +1,18 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, PathParamMetadata +from typing import TypedDict +from typing_extensions import Annotated + + +class MarkReadMessageRequestTypedDict(TypedDict): + id: str + r"""Message ID""" + + +class MarkReadMessageRequest(BaseModel): + id: Annotated[str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Message ID""" + diff --git a/message/src/epilot_message/models/markreadthreadop.py b/message/src/epilot_message/models/markreadthreadop.py new file mode 100644 index 000000000..9d305761f --- /dev/null +++ b/message/src/epilot_message/models/markreadthreadop.py @@ -0,0 +1,18 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, PathParamMetadata +from typing import TypedDict +from typing_extensions import Annotated + + +class MarkReadThreadRequestTypedDict(TypedDict): + id: str + r"""Thread ID""" + + +class MarkReadThreadRequest(BaseModel): + id: Annotated[str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Thread ID""" + diff --git a/message/src/epilot_message/models/markunreadmessageop.py b/message/src/epilot_message/models/markunreadmessageop.py new file mode 100644 index 000000000..643298373 --- /dev/null +++ b/message/src/epilot_message/models/markunreadmessageop.py @@ -0,0 +1,18 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, PathParamMetadata +from typing import TypedDict +from typing_extensions import Annotated + + +class MarkUnreadMessageRequestTypedDict(TypedDict): + id: str + r"""Message ID""" + + +class MarkUnreadMessageRequest(BaseModel): + id: Annotated[str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Message ID""" + diff --git a/message/src/epilot_message/models/markunreadthreadop.py b/message/src/epilot_message/models/markunreadthreadop.py new file mode 100644 index 000000000..4f6351229 --- /dev/null +++ b/message/src/epilot_message/models/markunreadthreadop.py @@ -0,0 +1,18 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, PathParamMetadata +from typing import TypedDict +from typing_extensions import Annotated + + +class MarkUnreadThreadRequestTypedDict(TypedDict): + id: str + r"""Thread ID""" + + +class MarkUnreadThreadRequest(BaseModel): + id: Annotated[str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Thread ID""" + diff --git a/message/src/epilot_message/models/message.py b/message/src/epilot_message/models/message.py new file mode 100644 index 000000000..5b2cb188b --- /dev/null +++ b/message/src/epilot_message/models/message.py @@ -0,0 +1,106 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .address import Address, AddressTypedDict +from .attachmentsrelation import AttachmentsRelation, AttachmentsRelationTypedDict +from enum import Enum +from epilot_message.types import BaseModel +import pydantic +from typing import List, Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class MessageSendStatus(str, Enum): + SEND = "SEND" + DELIVERY = "DELIVERY" + REJECT = "REJECT" + COMPLAINT = "COMPLAINT" + BOUNCE = "BOUNCE" + ERROR = "ERROR" + +class Type(str, Enum): + r"""Message type""" + SENT = "SENT" + RECEIVED = "RECEIVED" + +class MessageTypedDict(TypedDict): + from_: AddressTypedDict + subject: str + r"""Subject""" + bcc: NotRequired[List[AddressTypedDict]] + r"""Bcc email addresses""" + cc: NotRequired[List[AddressTypedDict]] + r"""Cc email addresses""" + file: NotRequired[AttachmentsRelationTypedDict] + r"""Message attachments""" + html: NotRequired[str] + r"""HTML body""" + in_reply_to: NotRequired[str] + r"""In-Reply-To header. Value is the `message_id` of parent message. + + """ + message_id: NotRequired[str] + r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" + org_read_message: NotRequired[List[str]] + r"""Ivy Organization ID of organization read the message.""" + references: NotRequired[str] + r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. + + """ + reply_to: NotRequired[AddressTypedDict] + send_status: NotRequired[List[MessageSendStatus]] + r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at + + """ + sender: NotRequired[str] + r"""Ivy User ID of user sends the message.""" + text: NotRequired[str] + r"""Text body""" + to: NotRequired[List[AddressTypedDict]] + r"""To email addresses""" + type: NotRequired[Type] + r"""Message type""" + user_read_message: NotRequired[List[str]] + r"""Ivy User ID of user read the message.""" + + +class Message(BaseModel): + from_: Annotated[Address, pydantic.Field(alias="from")] + subject: str + r"""Subject""" + bcc: Optional[List[Address]] = None + r"""Bcc email addresses""" + cc: Optional[List[Address]] = None + r"""Cc email addresses""" + file: Optional[AttachmentsRelation] = None + r"""Message attachments""" + html: Optional[str] = None + r"""HTML body""" + in_reply_to: Optional[str] = None + r"""In-Reply-To header. Value is the `message_id` of parent message. + + """ + message_id: Optional[str] = None + r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" + org_read_message: Optional[List[str]] = None + r"""Ivy Organization ID of organization read the message.""" + references: Optional[str] = None + r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. + + """ + reply_to: Optional[Address] = None + send_status: Optional[List[MessageSendStatus]] = None + r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at + + """ + sender: Optional[str] = None + r"""Ivy User ID of user sends the message.""" + text: Optional[str] = None + r"""Text body""" + to: Optional[List[Address]] = None + r"""To email addresses""" + type: Optional[Type] = None + r"""Message type""" + user_read_message: Optional[List[str]] = None + r"""Ivy User ID of user read the message.""" + diff --git a/message/src/epilot_message/models/messagerequestparams.py b/message/src/epilot_message/models/messagerequestparams.py new file mode 100644 index 000000000..ef44eaa48 --- /dev/null +++ b/message/src/epilot_message/models/messagerequestparams.py @@ -0,0 +1,98 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .address import Address, AddressTypedDict +from .attachmentsrelation import AttachmentsRelation, AttachmentsRelationTypedDict +from epilot_message.types import BaseModel +import pydantic +from pydantic import ConfigDict +from typing import Any, Dict, List, Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class ThreadTypedDict(TypedDict): + r"""Open new thread when sending the very first message in conversation. Thread should contains context related to all messages in it (eg. topic, brand_id, opportunity_id, assigned_to,...). Thread properties depend on API caller as it's not pre-defined. We do recommend having at least `topic` property for categorizing. `thread` or `parent_id` must be provided either. + + """ + + topic: str + r"""Message topic (e.g. which service sends the message or message category)""" + assigned_to: NotRequired[List[str]] + r"""Ivy User ID of who the message is assigned to. Default is the user who sends message.""" + + +class Thread(BaseModel): + r"""Open new thread when sending the very first message in conversation. Thread should contains context related to all messages in it (eg. topic, brand_id, opportunity_id, assigned_to,...). Thread properties depend on API caller as it's not pre-defined. We do recommend having at least `topic` property for categorizing. `thread` or `parent_id` must be provided either. + + """ + + topic: str + r"""Message topic (e.g. which service sends the message or message category)""" + assigned_to: Optional[List[str]] = None + r"""Ivy User ID of who the message is assigned to. Default is the user who sends message.""" + + +class MessageRequestParamsTypedDict(TypedDict): + from_: AddressTypedDict + subject: str + r"""Subject""" + bcc: NotRequired[List[AddressTypedDict]] + r"""Bcc email addresses""" + cc: NotRequired[List[AddressTypedDict]] + r"""Cc email addresses""" + file: NotRequired[AttachmentsRelationTypedDict] + r"""Message attachments""" + html: NotRequired[str] + r"""HTML body""" + parent_id: NotRequired[str] + r"""Entity ID of parent message which this message replies to or forwards from. If both `parent_id` and `thread` are provided, `thread` is discarded. + + """ + reply_to: NotRequired[AddressTypedDict] + text: NotRequired[str] + r"""Text body. If not provided, text body is converted from HTML body using [html-to-text](https://www.npmjs.com/package/html-to-text)""" + thread: NotRequired[ThreadTypedDict] + r"""Open new thread when sending the very first message in conversation. Thread should contains context related to all messages in it (eg. topic, brand_id, opportunity_id, assigned_to,...). Thread properties depend on API caller as it's not pre-defined. We do recommend having at least `topic` property for categorizing. `thread` or `parent_id` must be provided either. + + """ + to: NotRequired[List[AddressTypedDict]] + r"""To email addresses""" + + +class MessageRequestParams(BaseModel): + model_config = ConfigDict(populate_by_name=True, arbitrary_types_allowed=True, extra="allow") + __pydantic_extra__: Dict[str, Any] = pydantic.Field(init=False) + + from_: Annotated[Address, pydantic.Field(alias="from")] + subject: str + r"""Subject""" + bcc: Optional[List[Address]] = None + r"""Bcc email addresses""" + cc: Optional[List[Address]] = None + r"""Cc email addresses""" + file: Optional[AttachmentsRelation] = None + r"""Message attachments""" + html: Optional[str] = None + r"""HTML body""" + parent_id: Optional[str] = None + r"""Entity ID of parent message which this message replies to or forwards from. If both `parent_id` and `thread` are provided, `thread` is discarded. + + """ + reply_to: Optional[Address] = None + text: Optional[str] = None + r"""Text body. If not provided, text body is converted from HTML body using [html-to-text](https://www.npmjs.com/package/html-to-text)""" + thread: Optional[Thread] = None + r"""Open new thread when sending the very first message in conversation. Thread should contains context related to all messages in it (eg. topic, brand_id, opportunity_id, assigned_to,...). Thread properties depend on API caller as it's not pre-defined. We do recommend having at least `topic` property for categorizing. `thread` or `parent_id` must be provided either. + + """ + to: Optional[List[Address]] = None + r"""To email addresses""" + + @property + def additional_properties(self): + return self.__pydantic_extra__ + + @additional_properties.setter + def additional_properties(self, value): + self.__pydantic_extra__ = value # pyright: ignore[reportIncompatibleVariableOverride] + diff --git a/message/src/epilot_message/models/messagev2.py b/message/src/epilot_message/models/messagev2.py new file mode 100644 index 000000000..d64082bbe --- /dev/null +++ b/message/src/epilot_message/models/messagev2.py @@ -0,0 +1,143 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .address import Address, AddressTypedDict +from .attachmentsrelation import AttachmentsRelation, AttachmentsRelationTypedDict +from datetime import datetime +from enum import Enum +from epilot_message.types import BaseModel +import pydantic +from typing import List, Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class MessageV2SendStatus(str, Enum): + SEND = "SEND" + DELIVERY = "DELIVERY" + REJECT = "REJECT" + COMPLAINT = "COMPLAINT" + BOUNCE = "BOUNCE" + ERROR = "ERROR" + +class MessageV2Type(str, Enum): + r"""Message type""" + SENT = "SENT" + RECEIVED = "RECEIVED" + +class MessageV2TypedDict(TypedDict): + created_at: datetime + r"""Created date""" + id: str + r"""Entity ID""" + org: str + r"""Ivy Organization ID the entity belongs to""" + schema_: str + r"""URL-friendly identifier for the entity schema""" + title: str + r"""Entity title""" + updated_at: datetime + r"""Updated date""" + from_: AddressTypedDict + subject: str + r"""Subject""" + tags: NotRequired[List[str]] + r"""Entity tags""" + bcc: NotRequired[List[AddressTypedDict]] + r"""Bcc email addresses""" + cc: NotRequired[List[AddressTypedDict]] + r"""Cc email addresses""" + file: NotRequired[AttachmentsRelationTypedDict] + r"""Message attachments""" + html: NotRequired[str] + r"""HTML body""" + html_download_url: NotRequired[str] + r"""HTML body download URL""" + html_omitted: NotRequired[bool] + r"""If true then html is not provided and must be downloaded using the html_download_url""" + in_reply_to: NotRequired[str] + r"""In-Reply-To header. Value is the `message_id` of parent message. + + """ + message_id: NotRequired[str] + r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" + org_read_message: NotRequired[List[str]] + r"""Ivy Organization ID of organization read the message.""" + references: NotRequired[str] + r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. + + """ + reply_to: NotRequired[AddressTypedDict] + send_status: NotRequired[List[MessageV2SendStatus]] + r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at + + """ + sender: NotRequired[str] + r"""Ivy User ID of user sends the message.""" + text: NotRequired[str] + r"""Text body""" + to: NotRequired[List[AddressTypedDict]] + r"""To email addresses""" + type: NotRequired[MessageV2Type] + r"""Message type""" + user_read_message: NotRequired[List[str]] + r"""Ivy User ID of user read the message.""" + + +class MessageV2(BaseModel): + created_at: Annotated[datetime, pydantic.Field(alias="_created_at")] + r"""Created date""" + id: Annotated[str, pydantic.Field(alias="_id")] + r"""Entity ID""" + org: Annotated[str, pydantic.Field(alias="_org")] + r"""Ivy Organization ID the entity belongs to""" + schema_: Annotated[str, pydantic.Field(alias="_schema")] + r"""URL-friendly identifier for the entity schema""" + title: Annotated[str, pydantic.Field(alias="_title")] + r"""Entity title""" + updated_at: Annotated[datetime, pydantic.Field(alias="_updated_at")] + r"""Updated date""" + from_: Annotated[Address, pydantic.Field(alias="from")] + subject: str + r"""Subject""" + tags: Annotated[Optional[List[str]], pydantic.Field(alias="_tags")] = None + r"""Entity tags""" + bcc: Optional[List[Address]] = None + r"""Bcc email addresses""" + cc: Optional[List[Address]] = None + r"""Cc email addresses""" + file: Optional[AttachmentsRelation] = None + r"""Message attachments""" + html: Optional[str] = None + r"""HTML body""" + html_download_url: Optional[str] = None + r"""HTML body download URL""" + html_omitted: Optional[bool] = False + r"""If true then html is not provided and must be downloaded using the html_download_url""" + in_reply_to: Optional[str] = None + r"""In-Reply-To header. Value is the `message_id` of parent message. + + """ + message_id: Optional[str] = None + r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" + org_read_message: Optional[List[str]] = None + r"""Ivy Organization ID of organization read the message.""" + references: Optional[str] = None + r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. + + """ + reply_to: Optional[Address] = None + send_status: Optional[List[MessageV2SendStatus]] = None + r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at + + """ + sender: Optional[str] = None + r"""Ivy User ID of user sends the message.""" + text: Optional[str] = None + r"""Text body""" + to: Optional[List[Address]] = None + r"""To email addresses""" + type: Optional[MessageV2Type] = None + r"""Message type""" + user_read_message: Optional[List[str]] = None + r"""Ivy User ID of user read the message.""" + diff --git a/message/src/epilot_message/models/patchinfoop.py b/message/src/epilot_message/models/patchinfoop.py new file mode 100644 index 000000000..6db685f8b --- /dev/null +++ b/message/src/epilot_message/models/patchinfoop.py @@ -0,0 +1,248 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from enum import Enum +from epilot_message import utils +from epilot_message.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL +from epilot_message.utils import FieldMetadata, PathParamMetadata, RequestMetadata +import pydantic +from pydantic import model_serializer +from typing import List, Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class Status(str, Enum): + r"""Status of the GenAI job""" + INITIATED = "INITIATED" + IN_PROGRESS = "IN_PROGRESS" + COMPLETED = "COMPLETED" + FAILED = "FAILED" + +class PatchInfoRequestBodyTypedDict(TypedDict): + r"""Request body for genai info update""" + + created_at: NotRequired[float] + r"""Job created date""" + error: NotRequired[Nullable[str]] + r"""Error message if the job failed""" + feedback: NotRequired[Nullable[str]] + r"""Feedback of the suggested reply""" + next_steps: NotRequired[Nullable[List[str]]] + r"""Recommended next steps""" + progress: NotRequired[float] + r"""Progress of the GenAI job in percentage""" + rating: NotRequired[Nullable[str]] + r"""Rating of the suggested reply""" + status: NotRequired[Status] + r"""Status of the GenAI job""" + summary: NotRequired[Nullable[List[str]]] + r"""Generated summary""" + tags: NotRequired[Nullable[List[str]]] + r"""Tags""" + topics: NotRequired[Nullable[List[str]]] + r"""Topics of the email thread""" + updated_at: NotRequired[float] + r"""Job last updated date""" + + +class PatchInfoRequestBody(BaseModel): + r"""Request body for genai info update""" + + created_at: Optional[float] = None + r"""Job created date""" + error: OptionalNullable[str] = UNSET + r"""Error message if the job failed""" + feedback: OptionalNullable[str] = UNSET + r"""Feedback of the suggested reply""" + next_steps: OptionalNullable[List[str]] = UNSET + r"""Recommended next steps""" + progress: Optional[float] = None + r"""Progress of the GenAI job in percentage""" + rating: OptionalNullable[str] = UNSET + r"""Rating of the suggested reply""" + status: Optional[Status] = None + r"""Status of the GenAI job""" + summary: OptionalNullable[List[str]] = UNSET + r"""Generated summary""" + tags: OptionalNullable[List[str]] = UNSET + r"""Tags""" + topics: OptionalNullable[List[str]] = UNSET + r"""Topics of the email thread""" + updated_at: Optional[float] = None + r"""Job last updated date""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = ["created_at", "error", "feedback", "next_steps", "progress", "rating", "status", "summary", "tags", "topics", "updated_at"] + nullable_fields = ["error", "feedback", "next_steps", "rating", "summary", "tags", "topics"] + null_default_fields = [] + + serialized = handler(self) + + m = {} + + for n, f in self.model_fields.items(): + k = f.alias or n + val = serialized.get(k) + + optional_nullable = k in optional_fields and k in nullable_fields + is_set = (self.__pydantic_fields_set__.intersection({n}) or k in null_default_fields) # pylint: disable=no-member + + if val is not None and val != UNSET_SENTINEL: + m[k] = val + elif val != UNSET_SENTINEL and ( + not k in optional_fields or (optional_nullable and is_set) + ): + m[k] = val + + return m + + +class PatchInfoRequestTypedDict(TypedDict): + request_body: PatchInfoRequestBodyTypedDict + r"""Request body for genai info update""" + message_id: str + r"""Message ID""" + thread_id: str + r"""Thread ID""" + + +class PatchInfoRequest(BaseModel): + request_body: Annotated[PatchInfoRequestBody, FieldMetadata(request=RequestMetadata(media_type="application/json"))] + r"""Request body for genai info update""" + message_id: Annotated[str, pydantic.Field(alias="messageId"), FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Message ID""" + thread_id: Annotated[str, pydantic.Field(alias="threadId"), FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Thread ID""" + +class PatchInfoGenAIResponseBodyData(BaseModel): + error: Optional[str] = None + + + +class PatchInfoGenAIResponseBody(Exception): + r"""Internal server error""" + data: PatchInfoGenAIResponseBodyData + + def __init__(self, data: PatchInfoGenAIResponseBodyData): + self.data = data + + def __str__(self) -> str: + return utils.marshal_json(self.data, PatchInfoGenAIResponseBodyData) + + +class PatchInfoStatus(str, Enum): + r"""Status of the GenAI job""" + INITIATED = "INITIATED" + IN_PROGRESS = "IN_PROGRESS" + COMPLETED = "COMPLETED" + FAILED = "FAILED" + +class PatchInfoPayloadTypedDict(TypedDict): + created_at: NotRequired[float] + r"""Job created date""" + error: NotRequired[Nullable[str]] + r"""Error message if the job failed""" + feedback: NotRequired[Nullable[str]] + r"""Feedback of the suggested reply""" + next_steps: NotRequired[Nullable[List[str]]] + r"""Recommended next steps""" + progress: NotRequired[float] + r"""Progress of the GenAI job in percentage""" + rating: NotRequired[Nullable[str]] + r"""Rating of the suggested reply""" + status: NotRequired[PatchInfoStatus] + r"""Status of the GenAI job""" + summary: NotRequired[Nullable[List[str]]] + r"""Generated summary""" + tags: NotRequired[Nullable[List[str]]] + r"""Tags""" + topics: NotRequired[Nullable[List[str]]] + r"""Topics of the email thread""" + updated_at: NotRequired[float] + r"""Job last updated date""" + + +class PatchInfoPayload(BaseModel): + created_at: Optional[float] = None + r"""Job created date""" + error: OptionalNullable[str] = UNSET + r"""Error message if the job failed""" + feedback: OptionalNullable[str] = UNSET + r"""Feedback of the suggested reply""" + next_steps: OptionalNullable[List[str]] = UNSET + r"""Recommended next steps""" + progress: Optional[float] = None + r"""Progress of the GenAI job in percentage""" + rating: OptionalNullable[str] = UNSET + r"""Rating of the suggested reply""" + status: Optional[PatchInfoStatus] = None + r"""Status of the GenAI job""" + summary: OptionalNullable[List[str]] = UNSET + r"""Generated summary""" + tags: OptionalNullable[List[str]] = UNSET + r"""Tags""" + topics: OptionalNullable[List[str]] = UNSET + r"""Topics of the email thread""" + updated_at: Optional[float] = None + r"""Job last updated date""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = ["created_at", "error", "feedback", "next_steps", "progress", "rating", "status", "summary", "tags", "topics", "updated_at"] + nullable_fields = ["error", "feedback", "next_steps", "rating", "summary", "tags", "topics"] + null_default_fields = [] + + serialized = handler(self) + + m = {} + + for n, f in self.model_fields.items(): + k = f.alias or n + val = serialized.get(k) + + optional_nullable = k in optional_fields and k in nullable_fields + is_set = (self.__pydantic_fields_set__.intersection({n}) or k in null_default_fields) # pylint: disable=no-member + + if val is not None and val != UNSET_SENTINEL: + m[k] = val + elif val != UNSET_SENTINEL and ( + not k in optional_fields or (optional_nullable and is_set) + ): + m[k] = val + + return m + + +class PatchInfoType(str, Enum): + r"""Job type""" + INFO = "INFO" + REPLY = "REPLY" + +class PatchInfoResponseBodyTypedDict(TypedDict): + r"""Successfully updated, returns the updated info""" + + message_id: NotRequired[str] + r"""Message ID""" + org_id: NotRequired[str] + r"""Organization ID""" + payload: NotRequired[PatchInfoPayloadTypedDict] + thread_id: NotRequired[str] + r"""Thread ID""" + type: NotRequired[PatchInfoType] + r"""Job type""" + + +class PatchInfoResponseBody(BaseModel): + r"""Successfully updated, returns the updated info""" + + message_id: Optional[str] = None + r"""Message ID""" + org_id: Optional[str] = None + r"""Organization ID""" + payload: Optional[PatchInfoPayload] = None + thread_id: Optional[str] = None + r"""Thread ID""" + type: Optional[PatchInfoType] = None + r"""Job type""" + diff --git a/message/src/epilot_message/models/sdkerror.py b/message/src/epilot_message/models/sdkerror.py new file mode 100644 index 000000000..03216cbf5 --- /dev/null +++ b/message/src/epilot_message/models/sdkerror.py @@ -0,0 +1,22 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from dataclasses import dataclass +from typing import Optional +import httpx + + +@dataclass +class SDKError(Exception): + """Represents an error returned by the API.""" + + message: str + status_code: int = -1 + body: str = "" + raw_response: Optional[httpx.Response] = None + + def __str__(self): + body = "" + if len(self.body) > 0: + body = f"\n{self.body}" + + return f"{self.message}: Status {self.status_code}{body}" diff --git a/message/src/epilot_message/models/searchparams.py b/message/src/epilot_message/models/searchparams.py new file mode 100644 index 000000000..42424158b --- /dev/null +++ b/message/src/epilot_message/models/searchparams.py @@ -0,0 +1,22 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +import pydantic +from typing import Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class SearchParamsTypedDict(TypedDict): + q: str + r"""Lucene query syntax supported with ElasticSearch""" + from_: NotRequired[int] + size: NotRequired[int] + + +class SearchParams(BaseModel): + q: str + r"""Lucene query syntax supported with ElasticSearch""" + from_: Annotated[Optional[int], pydantic.Field(alias="from")] = 0 + size: Optional[int] = 10 + diff --git a/message/src/epilot_message/models/searchthreadsop.py b/message/src/epilot_message/models/searchthreadsop.py new file mode 100644 index 000000000..cf880cb02 --- /dev/null +++ b/message/src/epilot_message/models/searchthreadsop.py @@ -0,0 +1,86 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .message import Message, MessageTypedDict +from datetime import datetime +from epilot_message.types import BaseModel +import pydantic +from typing import List, Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class ResultsTypedDict(TypedDict): + r"""Thread properties depend on API caller as it's not pre-defined. We do recommend having at least `topic` property for categorizing.""" + + created_at: datetime + r"""Created date""" + id: str + r"""Entity ID""" + org: str + r"""Ivy Organization ID the entity belongs to""" + schema_: str + r"""URL-friendly identifier for the entity schema""" + title: str + r"""Entity title""" + updated_at: datetime + r"""Updated date""" + topic: str + r"""Message topic (e.g. which service sends the message or message category)""" + tags: NotRequired[List[str]] + r"""Entity tags""" + assigned_to: NotRequired[List[str]] + r"""Ivy User ID of who the message is assigned to. Default is the user who sends message.""" + latest_message: NotRequired[MessageTypedDict] + latest_message_at: NotRequired[str] + r"""The date of the latest message time in the thread""" + latest_trash_message: NotRequired[MessageTypedDict] + org_read_message: NotRequired[List[str]] + r"""Ivy Organization ID of organization read the message.""" + + +class Results(BaseModel): + r"""Thread properties depend on API caller as it's not pre-defined. We do recommend having at least `topic` property for categorizing.""" + + created_at: Annotated[datetime, pydantic.Field(alias="_created_at")] + r"""Created date""" + id: Annotated[str, pydantic.Field(alias="_id")] + r"""Entity ID""" + org: Annotated[str, pydantic.Field(alias="_org")] + r"""Ivy Organization ID the entity belongs to""" + schema_: Annotated[str, pydantic.Field(alias="_schema")] + r"""URL-friendly identifier for the entity schema""" + title: Annotated[str, pydantic.Field(alias="_title")] + r"""Entity title""" + updated_at: Annotated[datetime, pydantic.Field(alias="_updated_at")] + r"""Updated date""" + topic: str + r"""Message topic (e.g. which service sends the message or message category)""" + tags: Annotated[Optional[List[str]], pydantic.Field(alias="_tags")] = None + r"""Entity tags""" + assigned_to: Optional[List[str]] = None + r"""Ivy User ID of who the message is assigned to. Default is the user who sends message.""" + latest_message: Optional[Message] = None + latest_message_at: Optional[str] = None + r"""The date of the latest message time in the thread""" + latest_trash_message: Optional[Message] = None + org_read_message: Optional[List[str]] = None + r"""Ivy Organization ID of organization read the message.""" + + +class SearchThreadsResponseBodyTypedDict(TypedDict): + r"""Success""" + + hits: float + r"""Total of matched threads""" + results: List[ResultsTypedDict] + r"""Matched threads""" + + +class SearchThreadsResponseBody(BaseModel): + r"""Success""" + + hits: float + r"""Total of matched threads""" + results: List[Results] + r"""Matched threads""" + diff --git a/message/src/epilot_message/models/security.py b/message/src/epilot_message/models/security.py new file mode 100644 index 000000000..e2051db7a --- /dev/null +++ b/message/src/epilot_message/models/security.py @@ -0,0 +1,18 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, SecurityMetadata +from typing import Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class SecurityTypedDict(TypedDict): + epilot_auth: NotRequired[str] + epilot_org: NotRequired[str] + + +class Security(BaseModel): + epilot_auth: Annotated[Optional[str], FieldMetadata(security=SecurityMetadata(scheme=True, scheme_type="http", sub_type="bearer", field_name="Authorization"))] = None + epilot_org: Annotated[Optional[str], FieldMetadata(security=SecurityMetadata(scheme=True, scheme_type="apiKey", sub_type="header", field_name="x-epilot-org-id"))] = None + diff --git a/message/src/epilot_message/models/senddraftop.py b/message/src/epilot_message/models/senddraftop.py new file mode 100644 index 000000000..f03810ae3 --- /dev/null +++ b/message/src/epilot_message/models/senddraftop.py @@ -0,0 +1,139 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .address import Address, AddressTypedDict +from .attachmentsrelation import AttachmentsRelation, AttachmentsRelationTypedDict +from datetime import datetime +from enum import Enum +from epilot_message.types import BaseModel +import pydantic +from typing import List, Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class SendDraftSendStatus(str, Enum): + SEND = "SEND" + DELIVERY = "DELIVERY" + REJECT = "REJECT" + COMPLAINT = "COMPLAINT" + BOUNCE = "BOUNCE" + ERROR = "ERROR" + +class SendDraftType(str, Enum): + r"""Message type""" + SENT = "SENT" + RECEIVED = "RECEIVED" + +class SendDraftResponseBodyTypedDict(TypedDict): + r"""Success""" + + created_at: datetime + r"""Created date""" + id: str + r"""Entity ID""" + org: str + r"""Ivy Organization ID the entity belongs to""" + schema_: str + r"""URL-friendly identifier for the entity schema""" + title: str + r"""Entity title""" + updated_at: datetime + r"""Updated date""" + from_: AddressTypedDict + subject: str + r"""Subject""" + tags: NotRequired[List[str]] + r"""Entity tags""" + bcc: NotRequired[List[AddressTypedDict]] + r"""Bcc email addresses""" + cc: NotRequired[List[AddressTypedDict]] + r"""Cc email addresses""" + file: NotRequired[AttachmentsRelationTypedDict] + r"""Message attachments""" + html: NotRequired[str] + r"""HTML body""" + in_reply_to: NotRequired[str] + r"""In-Reply-To header. Value is the `message_id` of parent message. + + """ + message_id: NotRequired[str] + r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" + org_read_message: NotRequired[List[str]] + r"""Ivy Organization ID of organization read the message.""" + references: NotRequired[str] + r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. + + """ + reply_to: NotRequired[AddressTypedDict] + send_status: NotRequired[List[SendDraftSendStatus]] + r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at + + """ + sender: NotRequired[str] + r"""Ivy User ID of user sends the message.""" + text: NotRequired[str] + r"""Text body""" + to: NotRequired[List[AddressTypedDict]] + r"""To email addresses""" + type: NotRequired[SendDraftType] + r"""Message type""" + user_read_message: NotRequired[List[str]] + r"""Ivy User ID of user read the message.""" + + +class SendDraftResponseBody(BaseModel): + r"""Success""" + + created_at: Annotated[datetime, pydantic.Field(alias="_created_at")] + r"""Created date""" + id: Annotated[str, pydantic.Field(alias="_id")] + r"""Entity ID""" + org: Annotated[str, pydantic.Field(alias="_org")] + r"""Ivy Organization ID the entity belongs to""" + schema_: Annotated[str, pydantic.Field(alias="_schema")] + r"""URL-friendly identifier for the entity schema""" + title: Annotated[str, pydantic.Field(alias="_title")] + r"""Entity title""" + updated_at: Annotated[datetime, pydantic.Field(alias="_updated_at")] + r"""Updated date""" + from_: Annotated[Address, pydantic.Field(alias="from")] + subject: str + r"""Subject""" + tags: Annotated[Optional[List[str]], pydantic.Field(alias="_tags")] = None + r"""Entity tags""" + bcc: Optional[List[Address]] = None + r"""Bcc email addresses""" + cc: Optional[List[Address]] = None + r"""Cc email addresses""" + file: Optional[AttachmentsRelation] = None + r"""Message attachments""" + html: Optional[str] = None + r"""HTML body""" + in_reply_to: Optional[str] = None + r"""In-Reply-To header. Value is the `message_id` of parent message. + + """ + message_id: Optional[str] = None + r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" + org_read_message: Optional[List[str]] = None + r"""Ivy Organization ID of organization read the message.""" + references: Optional[str] = None + r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. + + """ + reply_to: Optional[Address] = None + send_status: Optional[List[SendDraftSendStatus]] = None + r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at + + """ + sender: Optional[str] = None + r"""Ivy User ID of user sends the message.""" + text: Optional[str] = None + r"""Text body""" + to: Optional[List[Address]] = None + r"""To email addresses""" + type: Optional[SendDraftType] = None + r"""Message type""" + user_read_message: Optional[List[str]] = None + r"""Ivy User ID of user read the message.""" + diff --git a/message/src/epilot_message/models/sendmessageop.py b/message/src/epilot_message/models/sendmessageop.py new file mode 100644 index 000000000..757042cb8 --- /dev/null +++ b/message/src/epilot_message/models/sendmessageop.py @@ -0,0 +1,21 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .messagerequestparams import MessageRequestParams, MessageRequestParamsTypedDict +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, QueryParamMetadata, RequestMetadata +from typing import Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class SendMessageRequestTypedDict(TypedDict): + message_request_params: NotRequired[MessageRequestParamsTypedDict] + do_not_create_entities: NotRequired[bool] + r"""When true, this flag lets the caller to send only the message and by-pass creating the thread & message entities.""" + + +class SendMessageRequest(BaseModel): + message_request_params: Annotated[Optional[MessageRequestParams], FieldMetadata(request=RequestMetadata(media_type="application/json"))] = None + do_not_create_entities: Annotated[Optional[bool], FieldMetadata(query=QueryParamMetadata(style="form", explode=True))] = False + r"""When true, this flag lets the caller to send only the message and by-pass creating the thread & message entities.""" + diff --git a/message/src/epilot_message/models/trashmessageop.py b/message/src/epilot_message/models/trashmessageop.py new file mode 100644 index 000000000..ef67cc559 --- /dev/null +++ b/message/src/epilot_message/models/trashmessageop.py @@ -0,0 +1,18 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, PathParamMetadata +from typing import TypedDict +from typing_extensions import Annotated + + +class TrashMessageRequestTypedDict(TypedDict): + id: str + r"""Message ID""" + + +class TrashMessageRequest(BaseModel): + id: Annotated[str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Message ID""" + diff --git a/message/src/epilot_message/models/trashthreadop.py b/message/src/epilot_message/models/trashthreadop.py new file mode 100644 index 000000000..a279a9deb --- /dev/null +++ b/message/src/epilot_message/models/trashthreadop.py @@ -0,0 +1,18 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, PathParamMetadata +from typing import TypedDict +from typing_extensions import Annotated + + +class TrashThreadRequestTypedDict(TypedDict): + id: str + r"""Thread ID""" + + +class TrashThreadRequest(BaseModel): + id: Annotated[str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Thread ID""" + diff --git a/message/src/epilot_message/models/untrashmessageop.py b/message/src/epilot_message/models/untrashmessageop.py new file mode 100644 index 000000000..906a33941 --- /dev/null +++ b/message/src/epilot_message/models/untrashmessageop.py @@ -0,0 +1,18 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, PathParamMetadata +from typing import TypedDict +from typing_extensions import Annotated + + +class UntrashMessageRequestTypedDict(TypedDict): + id: str + r"""Message ID""" + + +class UntrashMessageRequest(BaseModel): + id: Annotated[str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Message ID""" + diff --git a/message/src/epilot_message/models/untrashthreadop.py b/message/src/epilot_message/models/untrashthreadop.py new file mode 100644 index 000000000..3f6b96a89 --- /dev/null +++ b/message/src/epilot_message/models/untrashthreadop.py @@ -0,0 +1,18 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from epilot_message.types import BaseModel +from epilot_message.utils import FieldMetadata, PathParamMetadata +from typing import TypedDict +from typing_extensions import Annotated + + +class UntrashThreadRequestTypedDict(TypedDict): + id: str + r"""Thread ID""" + + +class UntrashThreadRequest(BaseModel): + id: Annotated[str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))] + r"""Thread ID""" + diff --git a/message/src/epilot_message/models/updatemessageop.py b/message/src/epilot_message/models/updatemessageop.py new file mode 100644 index 000000000..927e0db9e --- /dev/null +++ b/message/src/epilot_message/models/updatemessageop.py @@ -0,0 +1,139 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .address import Address, AddressTypedDict +from .attachmentsrelation import AttachmentsRelation, AttachmentsRelationTypedDict +from datetime import datetime +from enum import Enum +from epilot_message.types import BaseModel +import pydantic +from typing import List, Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class UpdateMessageSendStatus(str, Enum): + SEND = "SEND" + DELIVERY = "DELIVERY" + REJECT = "REJECT" + COMPLAINT = "COMPLAINT" + BOUNCE = "BOUNCE" + ERROR = "ERROR" + +class UpdateMessageType(str, Enum): + r"""Message type""" + SENT = "SENT" + RECEIVED = "RECEIVED" + +class UpdateMessageResponseBodyTypedDict(TypedDict): + r"""Success""" + + created_at: datetime + r"""Created date""" + id: str + r"""Entity ID""" + org: str + r"""Ivy Organization ID the entity belongs to""" + schema_: str + r"""URL-friendly identifier for the entity schema""" + title: str + r"""Entity title""" + updated_at: datetime + r"""Updated date""" + from_: AddressTypedDict + subject: str + r"""Subject""" + tags: NotRequired[List[str]] + r"""Entity tags""" + bcc: NotRequired[List[AddressTypedDict]] + r"""Bcc email addresses""" + cc: NotRequired[List[AddressTypedDict]] + r"""Cc email addresses""" + file: NotRequired[AttachmentsRelationTypedDict] + r"""Message attachments""" + html: NotRequired[str] + r"""HTML body""" + in_reply_to: NotRequired[str] + r"""In-Reply-To header. Value is the `message_id` of parent message. + + """ + message_id: NotRequired[str] + r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" + org_read_message: NotRequired[List[str]] + r"""Ivy Organization ID of organization read the message.""" + references: NotRequired[str] + r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. + + """ + reply_to: NotRequired[AddressTypedDict] + send_status: NotRequired[List[UpdateMessageSendStatus]] + r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at + + """ + sender: NotRequired[str] + r"""Ivy User ID of user sends the message.""" + text: NotRequired[str] + r"""Text body""" + to: NotRequired[List[AddressTypedDict]] + r"""To email addresses""" + type: NotRequired[UpdateMessageType] + r"""Message type""" + user_read_message: NotRequired[List[str]] + r"""Ivy User ID of user read the message.""" + + +class UpdateMessageResponseBody(BaseModel): + r"""Success""" + + created_at: Annotated[datetime, pydantic.Field(alias="_created_at")] + r"""Created date""" + id: Annotated[str, pydantic.Field(alias="_id")] + r"""Entity ID""" + org: Annotated[str, pydantic.Field(alias="_org")] + r"""Ivy Organization ID the entity belongs to""" + schema_: Annotated[str, pydantic.Field(alias="_schema")] + r"""URL-friendly identifier for the entity schema""" + title: Annotated[str, pydantic.Field(alias="_title")] + r"""Entity title""" + updated_at: Annotated[datetime, pydantic.Field(alias="_updated_at")] + r"""Updated date""" + from_: Annotated[Address, pydantic.Field(alias="from")] + subject: str + r"""Subject""" + tags: Annotated[Optional[List[str]], pydantic.Field(alias="_tags")] = None + r"""Entity tags""" + bcc: Optional[List[Address]] = None + r"""Bcc email addresses""" + cc: Optional[List[Address]] = None + r"""Cc email addresses""" + file: Optional[AttachmentsRelation] = None + r"""Message attachments""" + html: Optional[str] = None + r"""HTML body""" + in_reply_to: Optional[str] = None + r"""In-Reply-To header. Value is the `message_id` of parent message. + + """ + message_id: Optional[str] = None + r"""Message ID which is from email provider. If you provide `message-id`, API overrides by its own value.""" + org_read_message: Optional[List[str]] = None + r"""Ivy Organization ID of organization read the message.""" + references: Optional[str] = None + r"""References header. Value is the series of `message_id` which is reparated by space to indicate that message has parent. The last message ID in references identifies the parent. The first message ID in references identifies the first message in the thread. The basic idea is that sender should copy `references` from the parent and append the parent's `message_id` when replying. + + """ + reply_to: Optional[Address] = None + send_status: Optional[List[UpdateMessageSendStatus]] = None + r"""Sent message status. The array contains sending message status corresponding to all recipients. For more detail, check `send_status` of each recipient in `to`, `cc`, `bcc` Reference at + + """ + sender: Optional[str] = None + r"""Ivy User ID of user sends the message.""" + text: Optional[str] = None + r"""Text body""" + to: Optional[List[Address]] = None + r"""To email addresses""" + type: Optional[UpdateMessageType] = None + r"""Message type""" + user_read_message: Optional[List[str]] = None + r"""Ivy User ID of user read the message.""" + diff --git a/message/src/epilot_message/models/updatethreadop.py b/message/src/epilot_message/models/updatethreadop.py new file mode 100644 index 000000000..9bc986098 --- /dev/null +++ b/message/src/epilot_message/models/updatethreadop.py @@ -0,0 +1,68 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .message import Message, MessageTypedDict +from datetime import datetime +from epilot_message.types import BaseModel +import pydantic +from typing import List, Optional, TypedDict +from typing_extensions import Annotated, NotRequired + + +class UpdateThreadResponseBodyTypedDict(TypedDict): + r"""Thread properties depend on API caller as it's not pre-defined. We do recommend having at least `topic` property for categorizing.""" + + created_at: datetime + r"""Created date""" + id: str + r"""Entity ID""" + org: str + r"""Ivy Organization ID the entity belongs to""" + schema_: str + r"""URL-friendly identifier for the entity schema""" + title: str + r"""Entity title""" + updated_at: datetime + r"""Updated date""" + topic: str + r"""Message topic (e.g. which service sends the message or message category)""" + tags: NotRequired[List[str]] + r"""Entity tags""" + assigned_to: NotRequired[List[str]] + r"""Ivy User ID of who the message is assigned to. Default is the user who sends message.""" + latest_message: NotRequired[MessageTypedDict] + latest_message_at: NotRequired[str] + r"""The date of the latest message time in the thread""" + latest_trash_message: NotRequired[MessageTypedDict] + org_read_message: NotRequired[List[str]] + r"""Ivy Organization ID of organization read the message.""" + + +class UpdateThreadResponseBody(BaseModel): + r"""Thread properties depend on API caller as it's not pre-defined. We do recommend having at least `topic` property for categorizing.""" + + created_at: Annotated[datetime, pydantic.Field(alias="_created_at")] + r"""Created date""" + id: Annotated[str, pydantic.Field(alias="_id")] + r"""Entity ID""" + org: Annotated[str, pydantic.Field(alias="_org")] + r"""Ivy Organization ID the entity belongs to""" + schema_: Annotated[str, pydantic.Field(alias="_schema")] + r"""URL-friendly identifier for the entity schema""" + title: Annotated[str, pydantic.Field(alias="_title")] + r"""Entity title""" + updated_at: Annotated[datetime, pydantic.Field(alias="_updated_at")] + r"""Updated date""" + topic: str + r"""Message topic (e.g. which service sends the message or message category)""" + tags: Annotated[Optional[List[str]], pydantic.Field(alias="_tags")] = None + r"""Entity tags""" + assigned_to: Optional[List[str]] = None + r"""Ivy User ID of who the message is assigned to. Default is the user who sends message.""" + latest_message: Optional[Message] = None + latest_message_at: Optional[str] = None + r"""The date of the latest message time in the thread""" + latest_trash_message: Optional[Message] = None + org_read_message: Optional[List[str]] = None + r"""Ivy Organization ID of organization read the message.""" + diff --git a/message/src/epilot_message/py.typed b/message/src/epilot_message/py.typed new file mode 100644 index 000000000..3e38f1a92 --- /dev/null +++ b/message/src/epilot_message/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561. The package enables type hints. diff --git a/message/src/epilot_message/sdk.py b/message/src/epilot_message/sdk.py new file mode 100644 index 000000000..1e3e48894 --- /dev/null +++ b/message/src/epilot_message/sdk.py @@ -0,0 +1,103 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .basesdk import BaseSDK +from .httpclient import AsyncHttpClient, HttpClient +from .sdkconfiguration import SDKConfiguration +from .utils.logger import Logger, NoOpLogger +from .utils.retries import RetryConfig +from epilot_message import models, utils +from epilot_message._hooks import SDKHooks +from epilot_message.drafts import Drafts +from epilot_message.genai import GenAI +from epilot_message.internal import Internal +from epilot_message.messages import Messages +from epilot_message.threads import Threads +from epilot_message.types import OptionalNullable, UNSET +import httpx +from typing import Callable, Dict, Optional, Union + +class Epilot(BaseSDK): + r"""Message API: Send and receive email messages via your epilot organization + + """ + drafts: Drafts + messages: Messages + gen_ai: GenAI + threads: Threads + internal: Internal + def __init__( + self, + security: Union[models.Security, Callable[[], models.Security]], + server_idx: Optional[int] = None, + server_url: Optional[str] = None, + url_params: Optional[Dict[str, str]] = None, + client: Optional[HttpClient] = None, + async_client: Optional[AsyncHttpClient] = None, + retry_config: OptionalNullable[RetryConfig] = UNSET, + timeout_ms: Optional[int] = None, + debug_logger: Optional[Logger] = None + ) -> None: + r"""Instantiates the SDK configuring it with the provided parameters. + + :param security: The security details required for authentication + :param server_idx: The index of the server to use for all methods + :param server_url: The server URL to use for all methods + :param url_params: Parameters to optionally template the server URL with + :param client: The HTTP client to use for all synchronous methods + :param async_client: The Async HTTP client to use for all asynchronous methods + :param retry_config: The retry configuration to use for all supported methods + :param timeout_ms: Optional request timeout applied to each operation in milliseconds + """ + if client is None: + client = httpx.Client() + + assert issubclass( + type(client), HttpClient + ), "The provided client must implement the HttpClient protocol." + + if async_client is None: + async_client = httpx.AsyncClient() + + if debug_logger is None: + debug_logger = NoOpLogger() + + assert issubclass( + type(async_client), AsyncHttpClient + ), "The provided async_client must implement the AsyncHttpClient protocol." + + if server_url is not None: + if url_params is not None: + server_url = utils.template_url(server_url, url_params) + + + BaseSDK.__init__(self, SDKConfiguration( + client=client, + async_client=async_client, + security=security, + server_url=server_url, + server_idx=server_idx, + retry_config=retry_config, + timeout_ms=timeout_ms, + debug_logger=debug_logger + )) + + hooks = SDKHooks() + + current_server_url, *_ = self.sdk_configuration.get_server_details() + server_url, self.sdk_configuration.client = hooks.sdk_init(current_server_url, self.sdk_configuration.client) + if current_server_url != server_url: + self.sdk_configuration.server_url = server_url + + # pylint: disable=protected-access + self.sdk_configuration.__dict__["_hooks"] = hooks + + self._init_sdks() + + + def _init_sdks(self): + self.drafts = Drafts(self.sdk_configuration) + self.messages = Messages(self.sdk_configuration) + self.gen_ai = GenAI(self.sdk_configuration) + self.threads = Threads(self.sdk_configuration) + self.internal = Internal(self.sdk_configuration) + diff --git a/message/src/epilot_message/sdkconfiguration.py b/message/src/epilot_message/sdkconfiguration.py new file mode 100644 index 000000000..a9b87db08 --- /dev/null +++ b/message/src/epilot_message/sdkconfiguration.py @@ -0,0 +1,48 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + + +from ._hooks import SDKHooks +from .httpclient import AsyncHttpClient, HttpClient +from .utils import Logger, RetryConfig, remove_suffix +from dataclasses import dataclass +from epilot_message import models +from epilot_message.types import OptionalNullable, UNSET +from pydantic import Field +from typing import Callable, Dict, Optional, Tuple, Union + + +SERVERS = [ + "https://message.sls.epilot.io", +] +"""Contains the list of servers available to the SDK""" + +@dataclass +class SDKConfiguration: + client: HttpClient + async_client: AsyncHttpClient + debug_logger: Logger + security: Optional[Union[models.Security,Callable[[], models.Security]]] = None + server_url: Optional[str] = "" + server_idx: Optional[int] = 0 + language: str = "python" + openapi_doc_version: str = "1.0.0" + sdk_version: str = "1.3.0" + gen_version: str = "2.387.0" + user_agent: str = "speakeasy-sdk/python 1.3.0 2.387.0 1.0.0 epilot-message" + retry_config: OptionalNullable[RetryConfig] = Field(default_factory=lambda: UNSET) + timeout_ms: Optional[int] = None + + def __post_init__(self): + self._hooks = SDKHooks() + + def get_server_details(self) -> Tuple[str, Dict[str, str]]: + if self.server_url is not None and self.server_url: + return remove_suffix(self.server_url, "/"), {} + if self.server_idx is None: + self.server_idx = 0 + + return SERVERS[self.server_idx], {} + + + def get_hooks(self) -> SDKHooks: + return self._hooks diff --git a/message/src/epilot_message/threads.py b/message/src/epilot_message/threads.py new file mode 100644 index 000000000..e20be416a --- /dev/null +++ b/message/src/epilot_message/threads.py @@ -0,0 +1,1360 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .basesdk import BaseSDK +from epilot_message import models, utils +from epilot_message._hooks import HookContext +from epilot_message.types import BaseModel, OptionalNullable, UNSET +from typing import List, Optional, Union, cast + +class Threads(BaseSDK): + + + def assign_thread( + self, *, + id: str, + request_body: Union[List[models.RequestBody], List[models.RequestBodyTypedDict]], + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""assignThread + + Assign thread to entities + + :param id: Thread ID + :param request_body: + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.AssignThreadRequest( + id=id, + request_body=utils.get_pydantic_model(request_body, List[models.RequestBody]), + ) + + req = self.build_request( + method="POST", + path="/v1/message/threads/{id}/assign", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body(request.request_body, False, False, "json", List[models.RequestBody]), + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="assignThread", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def assign_thread_async( + self, *, + id: str, + request_body: Union[List[models.RequestBody], List[models.RequestBodyTypedDict]], + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""assignThread + + Assign thread to entities + + :param id: Thread ID + :param request_body: + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.AssignThreadRequest( + id=id, + request_body=utils.get_pydantic_model(request_body, List[models.RequestBody]), + ) + + req = self.build_request( + method="POST", + path="/v1/message/threads/{id}/assign", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body(request.request_body, False, False, "json", List[models.RequestBody]), + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="assignThread", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def assign_users( + self, *, + id: str, + request_body: Union[models.AssignUsersRequestBody, models.AssignUsersRequestBodyTypedDict], + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""assignUsers + + Assign users to thread for receiving notifications. + The operation replaces all existing assigned users in thread. + + + :param id: Thread ID + :param request_body: + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.AssignUsersRequest( + id=id, + request_body=utils.get_pydantic_model(request_body, models.AssignUsersRequestBody), + ) + + req = self.build_request( + method="POST", + path="/v1/message/threads/{id}/assign:users", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body(request.request_body, False, False, "json", models.AssignUsersRequestBody), + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="assignUsers", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def assign_users_async( + self, *, + id: str, + request_body: Union[models.AssignUsersRequestBody, models.AssignUsersRequestBodyTypedDict], + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""assignUsers + + Assign users to thread for receiving notifications. + The operation replaces all existing assigned users in thread. + + + :param id: Thread ID + :param request_body: + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.AssignUsersRequest( + id=id, + request_body=utils.get_pydantic_model(request_body, models.AssignUsersRequestBody), + ) + + req = self.build_request( + method="POST", + path="/v1/message/threads/{id}/assign:users", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body(request.request_body, False, False, "json", models.AssignUsersRequestBody), + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="assignUsers", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def delete_thread( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""deleteThread + + Immediately and permanently delete a thread. This operation cannot be undone. + + :param id: Thread ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.DeleteThreadRequest( + id=id, + ) + + req = self.build_request( + method="DELETE", + path="/v1/message/threads/{id}", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="deleteThread", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def delete_thread_async( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""deleteThread + + Immediately and permanently delete a thread. This operation cannot be undone. + + :param id: Thread ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.DeleteThreadRequest( + id=id, + ) + + req = self.build_request( + method="DELETE", + path="/v1/message/threads/{id}", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="deleteThread", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def mark_read_thread( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""markReadThread + + Mark thread as read + + :param id: Thread ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.MarkReadThreadRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/threads/{id}/read", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="markReadThread", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def mark_read_thread_async( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""markReadThread + + Mark thread as read + + :param id: Thread ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.MarkReadThreadRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/threads/{id}/read", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="markReadThread", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def mark_unread_thread( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""markUnreadThread + + Mark thread as unread + + :param id: Thread ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.MarkUnreadThreadRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/threads/{id}/unread", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="markUnreadThread", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def mark_unread_thread_async( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""markUnreadThread + + Mark thread as unread + + :param id: Thread ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.MarkUnreadThreadRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/threads/{id}/unread", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="markUnreadThread", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def search_threads( + self, *, + request: Optional[Union[models.SearchParams, models.SearchParamsTypedDict]] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.SearchThreadsResponseBody]: + r"""searchThreads + + Search for threads of email messages. + + Messages with no replies yet are treated as threads with single message. + + Lucene syntax supported. + + + :param request: The request object to send. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + if not isinstance(request, BaseModel) and request is not None: + request = utils.unmarshal(request, models.SearchParams) + request = cast(models.SearchParams, request) + + req = self.build_request( + method="POST", + path="/v1/message/threads:search", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body(request, False, True, "json", Optional[models.SearchParams]), + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="searchThreads", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "200", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.SearchThreadsResponseBody]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def search_threads_async( + self, *, + request: Optional[Union[models.SearchParams, models.SearchParamsTypedDict]] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.SearchThreadsResponseBody]: + r"""searchThreads + + Search for threads of email messages. + + Messages with no replies yet are treated as threads with single message. + + Lucene syntax supported. + + + :param request: The request object to send. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + if not isinstance(request, BaseModel) and request is not None: + request = utils.unmarshal(request, models.SearchParams) + request = cast(models.SearchParams, request) + + req = self.build_request( + method="POST", + path="/v1/message/threads:search", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body(request, False, True, "json", Optional[models.SearchParams]), + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="searchThreads", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "200", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.SearchThreadsResponseBody]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def trash_thread( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""trashThread + + Move a thread to trash + + :param id: Thread ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.TrashThreadRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/threads/{id}/trash", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="trashThread", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def trash_thread_async( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""trashThread + + Move a thread to trash + + :param id: Thread ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.TrashThreadRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/threads/{id}/trash", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="trashThread", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def untrash_thread( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""untrashThread + + Restore a trashed thread + + :param id: Thread ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.UntrashThreadRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/threads/{id}/untrash", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="untrashThread", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def untrash_thread_async( + self, *, + id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ): + r"""untrashThread + + Restore a trashed thread + + :param id: Thread ID + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + request = models.UntrashThreadRequest( + id=id, + ) + + req = self.build_request( + method="POST", + path="/v1/message/threads/{id}/untrash", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="*/*", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="untrashThread", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "204", "*"): + return + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + def update_thread( + self, *, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.UpdateThreadResponseBody]: + r"""updateThread + + Modify thread metadata + + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + req = self.build_request( + method="PUT", + path="/v1/message/threads", + base_url=base_url, + url_variables=url_variables, + request=None, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = self.do_request( + hook_ctx=HookContext(operation_id="updateThread", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "201", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.UpdateThreadResponseBody]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + + + async def update_thread_async( + self, *, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + ) -> Optional[models.UpdateThreadResponseBody]: + r"""updateThread + + Modify thread metadata + + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + req = self.build_request( + method="PUT", + path="/v1/message/threads", + base_url=base_url, + url_variables=url_variables, + request=None, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + security=self.sdk_configuration.security, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, [ + "429", + "500", + "502", + "503", + "504" + ]) + + http_res = await self.do_request_async( + hook_ctx=HookContext(operation_id="updateThread", oauth2_scopes=[], security_source=self.sdk_configuration.security), + request=req, + error_status_codes=["403","4XX","5XX"], + retry_config=retry_config + ) + + if utils.match_response(http_res, "201", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[models.UpdateThreadResponseBody]) + if utils.match_response(http_res, ["403","4XX","5XX"], "*"): + raise models.SDKError("API error occurred", http_res.status_code, http_res.text, http_res) + + content_type = http_res.headers.get("Content-Type") + raise models.SDKError(f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", http_res.status_code, http_res.text, http_res) + + diff --git a/message/src/epilot_message/types/__init__.py b/message/src/epilot_message/types/__init__.py new file mode 100644 index 000000000..fc76fe0c5 --- /dev/null +++ b/message/src/epilot_message/types/__init__.py @@ -0,0 +1,21 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .basemodel import ( + BaseModel, + Nullable, + OptionalNullable, + UnrecognizedInt, + UnrecognizedStr, + UNSET, + UNSET_SENTINEL, +) + +__all__ = [ + "BaseModel", + "Nullable", + "OptionalNullable", + "UnrecognizedInt", + "UnrecognizedStr", + "UNSET", + "UNSET_SENTINEL", +] diff --git a/message/src/epilot_message/types/basemodel.py b/message/src/epilot_message/types/basemodel.py new file mode 100644 index 000000000..a6187efa6 --- /dev/null +++ b/message/src/epilot_message/types/basemodel.py @@ -0,0 +1,39 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from pydantic import ConfigDict, model_serializer +from pydantic import BaseModel as PydanticBaseModel +from typing import TYPE_CHECKING, Literal, Optional, TypeVar, Union, NewType +from typing_extensions import TypeAliasType, TypeAlias + + +class BaseModel(PydanticBaseModel): + model_config = ConfigDict( + populate_by_name=True, arbitrary_types_allowed=True, protected_namespaces=() + ) + + +class Unset(BaseModel): + @model_serializer(mode="plain") + def serialize_model(self): + return UNSET_SENTINEL + + def __bool__(self) -> Literal[False]: + return False + + +UNSET = Unset() +UNSET_SENTINEL = "~?~unset~?~sentinel~?~" + + +T = TypeVar("T") +if TYPE_CHECKING: + Nullable: TypeAlias = Union[T, None] + OptionalNullable: TypeAlias = Union[Optional[Nullable[T]], Unset] +else: + Nullable = TypeAliasType("Nullable", Union[T, None], type_params=(T,)) + OptionalNullable = TypeAliasType( + "OptionalNullable", Union[Optional[Nullable[T]], Unset], type_params=(T,) + ) + +UnrecognizedInt = NewType("UnrecognizedInt", int) +UnrecognizedStr = NewType("UnrecognizedStr", str) diff --git a/message/src/epilot_message/utils/__init__.py b/message/src/epilot_message/utils/__init__.py new file mode 100644 index 000000000..95aa1b60c --- /dev/null +++ b/message/src/epilot_message/utils/__init__.py @@ -0,0 +1,84 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from .annotations import get_discriminator +from .enums import OpenEnumMeta +from .headers import get_headers, get_response_headers +from .metadata import ( + FieldMetadata, + find_metadata, + FormMetadata, + HeaderMetadata, + MultipartFormMetadata, + PathParamMetadata, + QueryParamMetadata, + RequestMetadata, + SecurityMetadata, +) +from .queryparams import get_query_params +from .retries import BackoffStrategy, Retries, retry, retry_async, RetryConfig +from .requestbodies import serialize_request_body, SerializedRequestBody +from .security import get_security +from .serializers import ( + get_pydantic_model, + marshal_json, + unmarshal, + unmarshal_json, + serialize_decimal, + serialize_float, + serialize_int, + stream_to_text, + validate_decimal, + validate_float, + validate_int, + validate_open_enum, +) +from .url import generate_url, template_url, remove_suffix +from .values import get_global_from_env, match_content_type, match_status_codes, match_response +from .logger import Logger, get_body_content, NoOpLogger + +__all__ = [ + "BackoffStrategy", + "FieldMetadata", + "find_metadata", + "FormMetadata", + "generate_url", + "get_body_content", + "get_discriminator", + "get_global_from_env", + "get_headers", + "get_pydantic_model", + "get_query_params", + "get_response_headers", + "get_security", + "HeaderMetadata", + "Logger", + "marshal_json", + "match_content_type", + "match_status_codes", + "match_response", + "MultipartFormMetadata", + "NoOpLogger", + "OpenEnumMeta", + "PathParamMetadata", + "QueryParamMetadata", + "remove_suffix", + "Retries", + "retry", + "retry_async", + "RetryConfig", + "RequestMetadata", + "SecurityMetadata", + "serialize_decimal", + "serialize_float", + "serialize_int", + "serialize_request_body", + "SerializedRequestBody", + "stream_to_text", + "template_url", + "unmarshal", + "unmarshal_json", + "validate_decimal", + "validate_float", + "validate_int", + "validate_open_enum", +] diff --git a/message/src/epilot_message/utils/annotations.py b/message/src/epilot_message/utils/annotations.py new file mode 100644 index 000000000..0d17472b3 --- /dev/null +++ b/message/src/epilot_message/utils/annotations.py @@ -0,0 +1,19 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from typing import Any + +def get_discriminator(model: Any, fieldname: str, key: str) -> str: + if isinstance(model, dict): + try: + return f'{model.get(key)}' + except AttributeError as e: + raise ValueError(f'Could not find discriminator key {key} in {model}') from e + + if hasattr(model, fieldname): + return f'{getattr(model, fieldname)}' + + fieldname = fieldname.upper() + if hasattr(model, fieldname): + return f'{getattr(model, fieldname)}' + + raise ValueError(f'Could not find discriminator field {fieldname} in {model}') diff --git a/message/src/epilot_message/utils/enums.py b/message/src/epilot_message/utils/enums.py new file mode 100644 index 000000000..c650b10cb --- /dev/null +++ b/message/src/epilot_message/utils/enums.py @@ -0,0 +1,34 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +import enum + + +class OpenEnumMeta(enum.EnumMeta): + def __call__( + cls, value, names=None, *, module=None, qualname=None, type=None, start=1 + ): + # The `type` kwarg also happens to be a built-in that pylint flags as + # redeclared. Safe to ignore this lint rule with this scope. + # pylint: disable=redefined-builtin + + if names is not None: + return super().__call__( + value, + names=names, + module=module, + qualname=qualname, + type=type, + start=start, + ) + + try: + return super().__call__( + value, + names=names, # pyright: ignore[reportArgumentType] + module=module, + qualname=qualname, + type=type, + start=start, + ) + except ValueError: + return value diff --git a/message/src/epilot_message/utils/eventstreaming.py b/message/src/epilot_message/utils/eventstreaming.py new file mode 100644 index 000000000..553b386b3 --- /dev/null +++ b/message/src/epilot_message/utils/eventstreaming.py @@ -0,0 +1,178 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +import re +import json +from typing import Callable, TypeVar, Optional, Generator, AsyncGenerator, Tuple +import httpx + +T = TypeVar("T") + + +class ServerEvent: + id: Optional[str] = None + event: Optional[str] = None + data: Optional[str] = None + retry: Optional[int] = None + + +MESSAGE_BOUNDARIES = [ + b"\r\n\r\n", + b"\n\n", + b"\r\r", +] + + +async def stream_events_async( + response: httpx.Response, + decoder: Callable[[str], T], + sentinel: Optional[str] = None, +) -> AsyncGenerator[T, None]: + buffer = bytearray() + position = 0 + discard = False + async for chunk in response.aiter_bytes(): + # We've encountered the sentinel value and should no longer process + # incoming data. Instead we throw new data away until the server closes + # the connection. + if discard: + continue + + buffer += chunk + for i in range(position, len(buffer)): + char = buffer[i : i + 1] + seq: Optional[bytes] = None + if char in [b"\r", b"\n"]: + for boundary in MESSAGE_BOUNDARIES: + seq = _peek_sequence(i, buffer, boundary) + if seq is not None: + break + if seq is None: + continue + + block = buffer[position:i] + position = i + len(seq) + event, discard = _parse_event(block, decoder, sentinel) + if event is not None: + yield event + + if position > 0: + buffer = buffer[position:] + position = 0 + + event, discard = _parse_event(buffer, decoder, sentinel) + if event is not None: + yield event + + +def stream_events( + response: httpx.Response, + decoder: Callable[[str], T], + sentinel: Optional[str] = None, +) -> Generator[T, None, None]: + buffer = bytearray() + position = 0 + discard = False + for chunk in response.iter_bytes(): + # We've encountered the sentinel value and should no longer process + # incoming data. Instead we throw new data away until the server closes + # the connection. + if discard: + continue + + buffer += chunk + for i in range(position, len(buffer)): + char = buffer[i : i + 1] + seq: Optional[bytes] = None + if char in [b"\r", b"\n"]: + for boundary in MESSAGE_BOUNDARIES: + seq = _peek_sequence(i, buffer, boundary) + if seq is not None: + break + if seq is None: + continue + + block = buffer[position:i] + position = i + len(seq) + event, discard = _parse_event(block, decoder, sentinel) + if event is not None: + yield event + + if position > 0: + buffer = buffer[position:] + position = 0 + + event, discard = _parse_event(buffer, decoder, sentinel) + if event is not None: + yield event + + +def _parse_event( + raw: bytearray, decoder: Callable[[str], T], sentinel: Optional[str] = None +) -> Tuple[Optional[T], bool]: + block = raw.decode() + lines = re.split(r"\r?\n|\r", block) + publish = False + event = ServerEvent() + data = "" + for line in lines: + if not line: + continue + + delim = line.find(":") + if delim <= 0: + continue + + field = line[0:delim] + value = line[delim + 1 :] if delim < len(line) - 1 else "" + if len(value) and value[0] == " ": + value = value[1:] + + if field == "event": + event.event = value + publish = True + elif field == "data": + data += value + "\n" + publish = True + elif field == "id": + event.id = value + publish = True + elif field == "retry": + event.retry = int(value) if value.isdigit() else None + publish = True + + if sentinel and data == f"{sentinel}\n": + return None, True + + if data: + data = data[:-1] + event.data = data + + data_is_primitive = ( + data.isnumeric() or data == "true" or data == "false" or data == "null" + ) + data_is_json = ( + data.startswith("{") or data.startswith("[") or data.startswith('"') + ) + + if data_is_primitive or data_is_json: + try: + event.data = json.loads(data) + except Exception: + pass + + out = None + if publish: + out = decoder(json.dumps(event.__dict__)) + + return out, False + + +def _peek_sequence(position: int, buffer: bytearray, sequence: bytes): + if len(sequence) > (len(buffer) - position): + return None + + for i, seq in enumerate(sequence): + if buffer[position + i] != seq: + return None + + return sequence diff --git a/message/src/epilot_message/utils/forms.py b/message/src/epilot_message/utils/forms.py new file mode 100644 index 000000000..07f9b2359 --- /dev/null +++ b/message/src/epilot_message/utils/forms.py @@ -0,0 +1,207 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from typing import ( + Any, + Dict, + get_type_hints, + List, + Tuple, +) +from pydantic import BaseModel +from pydantic.fields import FieldInfo + +from .serializers import marshal_json + +from .metadata import ( + FormMetadata, + MultipartFormMetadata, + find_field_metadata, +) +from .values import _val_to_string + + +def _populate_form( + field_name: str, + explode: bool, + obj: Any, + delimiter: str, + form: Dict[str, List[str]], +): + if obj is None: + return form + + if isinstance(obj, BaseModel): + items = [] + + obj_fields: Dict[str, FieldInfo] = obj.__class__.model_fields + for name in obj_fields: + obj_field = obj_fields[name] + obj_field_name = obj_field.alias if obj_field.alias is not None else name + if obj_field_name == "": + continue + + val = getattr(obj, name) + if val is None: + continue + + if explode: + form[obj_field_name] = [_val_to_string(val)] + else: + items.append(f"{obj_field_name}{delimiter}{_val_to_string(val)}") + + if len(items) > 0: + form[field_name] = [delimiter.join(items)] + elif isinstance(obj, Dict): + items = [] + for key, value in obj.items(): + if value is None: + continue + + if explode: + form[key] = [_val_to_string(value)] + else: + items.append(f"{key}{delimiter}{_val_to_string(value)}") + + if len(items) > 0: + form[field_name] = [delimiter.join(items)] + elif isinstance(obj, List): + items = [] + + for value in obj: + if value is None: + continue + + if explode: + if not field_name in form: + form[field_name] = [] + form[field_name].append(_val_to_string(value)) + else: + items.append(_val_to_string(value)) + + if len(items) > 0: + form[field_name] = [delimiter.join([str(item) for item in items])] + else: + form[field_name] = [_val_to_string(obj)] + + return form + + +def serialize_multipart_form( + media_type: str, request: Any +) -> Tuple[str, Dict[str, Any], Dict[str, Any]]: + form: Dict[str, Any] = {} + files: Dict[str, Any] = {} + + if not isinstance(request, BaseModel): + raise TypeError("invalid request body type") + + request_fields: Dict[str, FieldInfo] = request.__class__.model_fields + request_field_types = get_type_hints(request.__class__) + + for name in request_fields: + field = request_fields[name] + + val = getattr(request, name) + if val is None: + continue + + field_metadata = find_field_metadata(field, MultipartFormMetadata) + if not field_metadata: + continue + + f_name = field.alias if field.alias is not None else name + + if field_metadata.file: + file_fields: Dict[str, FieldInfo] = val.__class__.model_fields + + file_name = "" + field_name = "" + content = None + content_type = None + + for file_field_name in file_fields: + file_field = file_fields[file_field_name] + + file_metadata = find_field_metadata(file_field, MultipartFormMetadata) + if file_metadata is None: + continue + + if file_metadata.content: + content = getattr(val, file_field_name, None) + elif file_field_name == "content_type": + content_type = getattr(val, file_field_name, None) + else: + field_name = ( + file_field.alias + if file_field.alias is not None + else file_field_name + ) + file_name = getattr(val, file_field_name) + + if field_name == "" or file_name == "" or content is None: + raise ValueError("invalid multipart/form-data file") + + if content_type is not None: + files[field_name] = (file_name, content, content_type) + else: + files[field_name] = (file_name, content) + elif field_metadata.json: + files[f_name] = ( + None, + marshal_json(val, request_field_types[name]), + "application/json", + ) + else: + if isinstance(val, List): + values = [] + + for value in val: + if value is None: + continue + values.append(_val_to_string(value)) + + form[f_name + "[]"] = values + else: + form[f_name] = _val_to_string(val) + return media_type, form, files + + +def serialize_form_data(data: Any) -> Dict[str, Any]: + form: Dict[str, List[str]] = {} + + if isinstance(data, BaseModel): + data_fields: Dict[str, FieldInfo] = data.__class__.model_fields + data_field_types = get_type_hints(data.__class__) + for name in data_fields: + field = data_fields[name] + + val = getattr(data, name) + if val is None: + continue + + metadata = find_field_metadata(field, FormMetadata) + if metadata is None: + continue + + f_name = field.alias if field.alias is not None else name + + if metadata.json: + form[f_name] = [marshal_json(val, data_field_types[name])] + else: + if metadata.style == "form": + _populate_form( + f_name, + metadata.explode, + val, + ",", + form, + ) + else: + raise ValueError(f"Invalid form style for field {name}") + elif isinstance(data, Dict): + for key, value in data.items(): + form[key] = [_val_to_string(value)] + else: + raise TypeError(f"Invalid request body type {type(data)} for form data") + + return form diff --git a/message/src/epilot_message/utils/headers.py b/message/src/epilot_message/utils/headers.py new file mode 100644 index 000000000..e14a0f4a8 --- /dev/null +++ b/message/src/epilot_message/utils/headers.py @@ -0,0 +1,136 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from typing import ( + Any, + Dict, + List, + Optional, +) +from httpx import Headers +from pydantic import BaseModel +from pydantic.fields import FieldInfo + +from .metadata import ( + HeaderMetadata, + find_field_metadata, +) + +from .values import _populate_from_globals, _val_to_string + + +def get_headers(headers_params: Any, gbls: Optional[Any] = None) -> Dict[str, str]: + headers: Dict[str, str] = {} + + globals_already_populated = [] + if headers_params is not None: + globals_already_populated = _populate_headers(headers_params, gbls, headers, []) + if gbls is not None: + _populate_headers(gbls, None, headers, globals_already_populated) + + return headers + + +def _populate_headers( + headers_params: Any, + gbls: Any, + header_values: Dict[str, str], + skip_fields: List[str], +) -> List[str]: + globals_already_populated: List[str] = [] + + if not isinstance(headers_params, BaseModel): + return globals_already_populated + + param_fields: Dict[str, FieldInfo] = headers_params.__class__.model_fields + for name in param_fields: + if name in skip_fields: + continue + + field = param_fields[name] + f_name = field.alias if field.alias is not None else name + + metadata = find_field_metadata(field, HeaderMetadata) + if metadata is None: + continue + + value, global_found = _populate_from_globals( + name, getattr(headers_params, name), HeaderMetadata, gbls + ) + if global_found: + globals_already_populated.append(name) + value = _serialize_header(metadata.explode, value) + + if value != "": + header_values[f_name] = value + + return globals_already_populated + + +def _serialize_header(explode: bool, obj: Any) -> str: + if obj is None: + return "" + + if isinstance(obj, BaseModel): + items = [] + obj_fields: Dict[str, FieldInfo] = obj.__class__.model_fields + for name in obj_fields: + obj_field = obj_fields[name] + obj_param_metadata = find_field_metadata(obj_field, HeaderMetadata) + + if not obj_param_metadata: + continue + + f_name = obj_field.alias if obj_field.alias is not None else name + + val = getattr(obj, name) + if val is None: + continue + + if explode: + items.append(f"{f_name}={_val_to_string(val)}") + else: + items.append(f_name) + items.append(_val_to_string(val)) + + if len(items) > 0: + return ",".join(items) + elif isinstance(obj, Dict): + items = [] + + for key, value in obj.items(): + if value is None: + continue + + if explode: + items.append(f"{key}={_val_to_string(value)}") + else: + items.append(key) + items.append(_val_to_string(value)) + + if len(items) > 0: + return ",".join([str(item) for item in items]) + elif isinstance(obj, List): + items = [] + + for value in obj: + if value is None: + continue + + items.append(_val_to_string(value)) + + if len(items) > 0: + return ",".join(items) + else: + return f"{_val_to_string(obj)}" + + return "" + + +def get_response_headers(headers: Headers) -> Dict[str, List[str]]: + res: Dict[str, List[str]] = {} + for k, v in headers.items(): + if not k in res: + res[k] = [] + + res[k].append(v) + return res diff --git a/message/src/epilot_message/utils/logger.py b/message/src/epilot_message/utils/logger.py new file mode 100644 index 000000000..7e4bbeac2 --- /dev/null +++ b/message/src/epilot_message/utils/logger.py @@ -0,0 +1,16 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +import httpx +from typing import Any, Protocol + +class Logger(Protocol): + def debug(self, msg: str, *args: Any, **kwargs: Any) -> None: + pass + +class NoOpLogger: + def debug(self, msg: str, *args: Any, **kwargs: Any) -> None: + pass + +def get_body_content(req: httpx.Request) -> str: + return "" if not hasattr(req, "_content") else str(req.content) + diff --git a/message/src/epilot_message/utils/metadata.py b/message/src/epilot_message/utils/metadata.py new file mode 100644 index 000000000..173b3e5ce --- /dev/null +++ b/message/src/epilot_message/utils/metadata.py @@ -0,0 +1,118 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from typing import Optional, Type, TypeVar, Union +from dataclasses import dataclass +from pydantic.fields import FieldInfo + + +T = TypeVar("T") + + +@dataclass +class SecurityMetadata: + option: bool = False + scheme: bool = False + scheme_type: Optional[str] = None + sub_type: Optional[str] = None + field_name: Optional[str] = None + + def get_field_name(self, default: str) -> str: + return self.field_name or default + + +@dataclass +class ParamMetadata: + serialization: Optional[str] = None + style: str = "simple" + explode: bool = False + + +@dataclass +class PathParamMetadata(ParamMetadata): + pass + + +@dataclass +class QueryParamMetadata(ParamMetadata): + style: str = "form" + explode: bool = True + + +@dataclass +class HeaderMetadata(ParamMetadata): + pass + + +@dataclass +class RequestMetadata: + media_type: str = "application/octet-stream" + + +@dataclass +class MultipartFormMetadata: + file: bool = False + content: bool = False + json: bool = False + + +@dataclass +class FormMetadata: + json: bool = False + style: str = "form" + explode: bool = True + + +class FieldMetadata: + security: Optional[SecurityMetadata] = None + path: Optional[PathParamMetadata] = None + query: Optional[QueryParamMetadata] = None + header: Optional[HeaderMetadata] = None + request: Optional[RequestMetadata] = None + form: Optional[FormMetadata] = None + multipart: Optional[MultipartFormMetadata] = None + + def __init__( + self, + security: Optional[SecurityMetadata] = None, + path: Optional[Union[PathParamMetadata, bool]] = None, + query: Optional[Union[QueryParamMetadata, bool]] = None, + header: Optional[Union[HeaderMetadata, bool]] = None, + request: Optional[Union[RequestMetadata, bool]] = None, + form: Optional[Union[FormMetadata, bool]] = None, + multipart: Optional[Union[MultipartFormMetadata, bool]] = None, + ): + self.security = security + self.path = PathParamMetadata() if isinstance(path, bool) else path + self.query = QueryParamMetadata() if isinstance(query, bool) else query + self.header = HeaderMetadata() if isinstance(header, bool) else header + self.request = RequestMetadata() if isinstance(request, bool) else request + self.form = FormMetadata() if isinstance(form, bool) else form + self.multipart = ( + MultipartFormMetadata() if isinstance(multipart, bool) else multipart + ) + + +def find_field_metadata(field_info: FieldInfo, metadata_type: Type[T]) -> Optional[T]: + metadata = find_metadata(field_info, FieldMetadata) + if not metadata: + return None + + fields = metadata.__dict__ + + for field in fields: + if isinstance(fields[field], metadata_type): + return fields[field] + + return None + + +def find_metadata(field_info: FieldInfo, metadata_type: Type[T]) -> Optional[T]: + metadata = field_info.metadata + if not metadata: + return None + + for md in metadata: + if isinstance(md, metadata_type): + return md + + return None diff --git a/message/src/epilot_message/utils/queryparams.py b/message/src/epilot_message/utils/queryparams.py new file mode 100644 index 000000000..1c8c58340 --- /dev/null +++ b/message/src/epilot_message/utils/queryparams.py @@ -0,0 +1,203 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from typing import ( + Any, + Dict, + get_type_hints, + List, + Optional, +) + +from pydantic import BaseModel +from pydantic.fields import FieldInfo + +from .metadata import ( + QueryParamMetadata, + find_field_metadata, +) +from .values import _get_serialized_params, _populate_from_globals, _val_to_string +from .forms import _populate_form + + +def get_query_params( + query_params: Any, + gbls: Optional[Any] = None, +) -> Dict[str, List[str]]: + params: Dict[str, List[str]] = {} + + globals_already_populated = _populate_query_params(query_params, gbls, params, []) + if gbls is not None: + _populate_query_params(gbls, None, params, globals_already_populated) + + return params + + +def _populate_query_params( + query_params: Any, + gbls: Any, + query_param_values: Dict[str, List[str]], + skip_fields: List[str], +) -> List[str]: + globals_already_populated: List[str] = [] + + if not isinstance(query_params, BaseModel): + return globals_already_populated + + param_fields: Dict[str, FieldInfo] = query_params.__class__.model_fields + param_field_types = get_type_hints(query_params.__class__) + for name in param_fields: + if name in skip_fields: + continue + + field = param_fields[name] + + metadata = find_field_metadata(field, QueryParamMetadata) + if not metadata: + continue + + value = getattr(query_params, name) if query_params is not None else None + + value, global_found = _populate_from_globals( + name, value, QueryParamMetadata, gbls + ) + if global_found: + globals_already_populated.append(name) + + f_name = field.alias if field.alias is not None else name + serialization = metadata.serialization + if serialization is not None: + serialized_parms = _get_serialized_params( + metadata, f_name, value, param_field_types[name] + ) + for key, value in serialized_parms.items(): + if key in query_param_values: + query_param_values[key].extend(value) + else: + query_param_values[key] = [value] + else: + style = metadata.style + if style == "deepObject": + _populate_deep_object_query_params(f_name, value, query_param_values) + elif style == "form": + _populate_delimited_query_params( + metadata, f_name, value, ",", query_param_values + ) + elif style == "pipeDelimited": + _populate_delimited_query_params( + metadata, f_name, value, "|", query_param_values + ) + else: + raise NotImplementedError( + f"query param style {style} not yet supported" + ) + + return globals_already_populated + + +def _populate_deep_object_query_params( + field_name: str, + obj: Any, + params: Dict[str, List[str]], +): + if obj is None: + return + + if isinstance(obj, BaseModel): + _populate_deep_object_query_params_basemodel(field_name, obj, params) + elif isinstance(obj, Dict): + _populate_deep_object_query_params_dict(field_name, obj, params) + + +def _populate_deep_object_query_params_basemodel( + prior_params_key: str, + obj: Any, + params: Dict[str, List[str]], +): + if obj is None: + return + + if not isinstance(obj, BaseModel): + return + + obj_fields: Dict[str, FieldInfo] = obj.__class__.model_fields + for name in obj_fields: + obj_field = obj_fields[name] + + f_name = obj_field.alias if obj_field.alias is not None else name + + params_key = f"{prior_params_key}[{f_name}]" + + obj_param_metadata = find_field_metadata(obj_field, QueryParamMetadata) + if obj_param_metadata is None: + continue + + obj_val = getattr(obj, name) + if obj_val is None: + continue + + if isinstance(obj_val, BaseModel): + _populate_deep_object_query_params_basemodel(params_key, obj_val, params) + elif isinstance(obj_val, Dict): + _populate_deep_object_query_params_dict(params_key, obj_val, params) + elif isinstance(obj_val, List): + _populate_deep_object_query_params_list(params_key, obj_val, params) + else: + params[params_key] = [_val_to_string(obj_val)] + + +def _populate_deep_object_query_params_dict( + prior_params_key: str, + value: Dict, + params: Dict[str, List[str]], +): + if value is None: + return + + for key, val in value.items(): + if val is None: + continue + + params_key = f"{prior_params_key}[{key}]" + + if isinstance(val, BaseModel): + _populate_deep_object_query_params_basemodel(params_key, val, params) + elif isinstance(val, Dict): + _populate_deep_object_query_params_dict(params_key, val, params) + elif isinstance(val, List): + _populate_deep_object_query_params_list(params_key, val, params) + else: + params[params_key] = [_val_to_string(val)] + + +def _populate_deep_object_query_params_list( + params_key: str, + value: List, + params: Dict[str, List[str]], +): + if value is None: + return + + for val in value: + if val is None: + continue + + if params.get(params_key) is None: + params[params_key] = [] + + params[params_key].append(_val_to_string(val)) + + +def _populate_delimited_query_params( + metadata: QueryParamMetadata, + field_name: str, + obj: Any, + delimiter: str, + query_param_values: Dict[str, List[str]], +): + _populate_form( + field_name, + metadata.explode, + obj, + delimiter, + query_param_values, + ) diff --git a/message/src/epilot_message/utils/requestbodies.py b/message/src/epilot_message/utils/requestbodies.py new file mode 100644 index 000000000..4f586ae79 --- /dev/null +++ b/message/src/epilot_message/utils/requestbodies.py @@ -0,0 +1,66 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +import io +from dataclasses import dataclass +import re +from typing import ( + Any, + Optional, +) + +from .forms import serialize_form_data, serialize_multipart_form + +from .serializers import marshal_json + +SERIALIZATION_METHOD_TO_CONTENT_TYPE = { + "json": "application/json", + "form": "application/x-www-form-urlencoded", + "multipart": "multipart/form-data", + "raw": "application/octet-stream", + "string": "text/plain", +} + + +@dataclass +class SerializedRequestBody: + media_type: str + content: Optional[Any] = None + data: Optional[Any] = None + files: Optional[Any] = None + + +def serialize_request_body( + request_body: Any, + nullable: bool, + optional: bool, + serialization_method: str, + request_body_type, +) -> Optional[SerializedRequestBody]: + if request_body is None: + if not nullable and optional: + return None + + media_type = SERIALIZATION_METHOD_TO_CONTENT_TYPE[serialization_method] + + serialized_request_body = SerializedRequestBody(media_type) + + if re.match(r"(application|text)\/.*?\+*json.*", media_type) is not None: + serialized_request_body.content = marshal_json(request_body, request_body_type) + elif re.match(r"multipart\/.*", media_type) is not None: + ( + serialized_request_body.media_type, + serialized_request_body.data, + serialized_request_body.files, + ) = serialize_multipart_form(media_type, request_body) + elif re.match(r"application\/x-www-form-urlencoded.*", media_type) is not None: + serialized_request_body.data = serialize_form_data(request_body) + elif isinstance(request_body, (bytes, bytearray, io.BytesIO, io.BufferedReader)): + serialized_request_body.content = request_body + elif isinstance(request_body, str): + serialized_request_body.content = request_body + else: + raise TypeError( + f"invalid request body type {type(request_body)} for mediaType {media_type}" + ) + + return serialized_request_body diff --git a/message/src/epilot_message/utils/retries.py b/message/src/epilot_message/utils/retries.py new file mode 100644 index 000000000..a06f92794 --- /dev/null +++ b/message/src/epilot_message/utils/retries.py @@ -0,0 +1,216 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +import random +import time +from typing import List + +import httpx + + +class BackoffStrategy: + initial_interval: int + max_interval: int + exponent: float + max_elapsed_time: int + + def __init__( + self, + initial_interval: int, + max_interval: int, + exponent: float, + max_elapsed_time: int, + ): + self.initial_interval = initial_interval + self.max_interval = max_interval + self.exponent = exponent + self.max_elapsed_time = max_elapsed_time + + +class RetryConfig: + strategy: str + backoff: BackoffStrategy + retry_connection_errors: bool + + def __init__( + self, strategy: str, backoff: BackoffStrategy, retry_connection_errors: bool + ): + self.strategy = strategy + self.backoff = backoff + self.retry_connection_errors = retry_connection_errors + + +class Retries: + config: RetryConfig + status_codes: List[str] + + def __init__(self, config: RetryConfig, status_codes: List[str]): + self.config = config + self.status_codes = status_codes + + +class TemporaryError(Exception): + response: httpx.Response + + def __init__(self, response: httpx.Response): + self.response = response + + +class PermanentError(Exception): + inner: Exception + + def __init__(self, inner: Exception): + self.inner = inner + + +def retry(func, retries: Retries): + if retries.config.strategy == "backoff": + + def do_request() -> httpx.Response: + res: httpx.Response + try: + res = func() + + for code in retries.status_codes: + if "X" in code.upper(): + code_range = int(code[0]) + + status_major = res.status_code / 100 + + if code_range <= status_major < code_range + 1: + raise TemporaryError(res) + else: + parsed_code = int(code) + + if res.status_code == parsed_code: + raise TemporaryError(res) + except httpx.ConnectError as exception: + if retries.config.retry_connection_errors: + raise + + raise PermanentError(exception) from exception + except httpx.TimeoutException as exception: + if retries.config.retry_connection_errors: + raise + + raise PermanentError(exception) from exception + except TemporaryError: + raise + except Exception as exception: + raise PermanentError(exception) from exception + + return res + + return retry_with_backoff( + do_request, + retries.config.backoff.initial_interval, + retries.config.backoff.max_interval, + retries.config.backoff.exponent, + retries.config.backoff.max_elapsed_time, + ) + + return func() + + +async def retry_async(func, retries: Retries): + if retries.config.strategy == "backoff": + + async def do_request() -> httpx.Response: + res: httpx.Response + try: + res = await func() + + for code in retries.status_codes: + if "X" in code.upper(): + code_range = int(code[0]) + + status_major = res.status_code / 100 + + if code_range <= status_major < code_range + 1: + raise TemporaryError(res) + else: + parsed_code = int(code) + + if res.status_code == parsed_code: + raise TemporaryError(res) + except httpx.ConnectError as exception: + if retries.config.retry_connection_errors: + raise + + raise PermanentError(exception) from exception + except httpx.TimeoutException as exception: + if retries.config.retry_connection_errors: + raise + + raise PermanentError(exception) from exception + except TemporaryError: + raise + except Exception as exception: + raise PermanentError(exception) from exception + + return res + + return await retry_with_backoff_async( + do_request, + retries.config.backoff.initial_interval, + retries.config.backoff.max_interval, + retries.config.backoff.exponent, + retries.config.backoff.max_elapsed_time, + ) + + return await func() + + +def retry_with_backoff( + func, + initial_interval=500, + max_interval=60000, + exponent=1.5, + max_elapsed_time=3600000, +): + start = round(time.time() * 1000) + retries = 0 + + while True: + try: + return func() + except PermanentError as exception: + raise exception.inner + except Exception as exception: # pylint: disable=broad-exception-caught + now = round(time.time() * 1000) + if now - start > max_elapsed_time: + if isinstance(exception, TemporaryError): + return exception.response + + raise + sleep = (initial_interval / 1000) * exponent**retries + random.uniform(0, 1) + sleep = min(sleep, max_interval / 1000) + time.sleep(sleep) + retries += 1 + + +async def retry_with_backoff_async( + func, + initial_interval=500, + max_interval=60000, + exponent=1.5, + max_elapsed_time=3600000, +): + start = round(time.time() * 1000) + retries = 0 + + while True: + try: + return await func() + except PermanentError as exception: + raise exception.inner + except Exception as exception: # pylint: disable=broad-exception-caught + now = round(time.time() * 1000) + if now - start > max_elapsed_time: + if isinstance(exception, TemporaryError): + return exception.response + + raise + sleep = (initial_interval / 1000) * exponent**retries + random.uniform(0, 1) + sleep = min(sleep, max_interval / 1000) + time.sleep(sleep) + retries += 1 diff --git a/message/src/epilot_message/utils/security.py b/message/src/epilot_message/utils/security.py new file mode 100644 index 000000000..aab4cb65c --- /dev/null +++ b/message/src/epilot_message/utils/security.py @@ -0,0 +1,168 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +import base64 +from typing import ( + Any, + Dict, + List, + Tuple, +) +from pydantic import BaseModel +from pydantic.fields import FieldInfo + +from .metadata import ( + SecurityMetadata, + find_field_metadata, +) + + + +def get_security(security: Any) -> Tuple[Dict[str, str], Dict[str, List[str]]]: + headers: Dict[str, str] = {} + query_params: Dict[str, List[str]] = {} + + if security is None: + return headers, query_params + + if not isinstance(security, BaseModel): + raise TypeError("security must be a pydantic model") + + sec_fields: Dict[str, FieldInfo] = security.__class__.model_fields + for name in sec_fields: + sec_field = sec_fields[name] + + value = getattr(security, name) + if value is None: + continue + + metadata = find_field_metadata(sec_field, SecurityMetadata) + if metadata is None: + continue + if metadata.option: + _parse_security_option(headers, query_params, value) + return headers, query_params + if metadata.scheme: + # Special case for basic auth which could be a flattened model + if metadata.sub_type == "basic" and not isinstance(value, BaseModel): + _parse_security_scheme(headers, query_params, metadata, name, security) + else: + _parse_security_scheme(headers, query_params, metadata, name, value) + + return headers, query_params + + +def _parse_security_option( + headers: Dict[str, str], query_params: Dict[str, List[str]], option: Any +): + if not isinstance(option, BaseModel): + raise TypeError("security option must be a pydantic model") + + opt_fields: Dict[str, FieldInfo] = option.__class__.model_fields + for name in opt_fields: + opt_field = opt_fields[name] + + metadata = find_field_metadata(opt_field, SecurityMetadata) + if metadata is None or not metadata.scheme: + continue + _parse_security_scheme( + headers, query_params, metadata, name, getattr(option, name) + ) + + +def _parse_security_scheme( + headers: Dict[str, str], + query_params: Dict[str, List[str]], + scheme_metadata: SecurityMetadata, + field_name: str, + scheme: Any, +): + scheme_type = scheme_metadata.scheme_type + sub_type = scheme_metadata.sub_type + + if isinstance(scheme, BaseModel): + if scheme_type == "http" and sub_type == "basic": + _parse_basic_auth_scheme(headers, scheme) + return + + scheme_fields: Dict[str, FieldInfo] = scheme.__class__.model_fields + for name in scheme_fields: + scheme_field = scheme_fields[name] + + metadata = find_field_metadata(scheme_field, SecurityMetadata) + if metadata is None or metadata.field_name is None: + continue + + value = getattr(scheme, name) + + _parse_security_scheme_value( + headers, query_params, scheme_metadata, metadata, name, value + ) + else: + _parse_security_scheme_value( + headers, query_params, scheme_metadata, scheme_metadata, field_name, scheme + ) + + +def _parse_security_scheme_value( + headers: Dict[str, str], + query_params: Dict[str, List[str]], + scheme_metadata: SecurityMetadata, + security_metadata: SecurityMetadata, + field_name: str, + value: Any, +): + scheme_type = scheme_metadata.scheme_type + sub_type = scheme_metadata.sub_type + + header_name = security_metadata.get_field_name(field_name) + + if scheme_type == "apiKey": + if sub_type == "header": + headers[header_name] = value + elif sub_type == "query": + query_params[header_name] = [value] + else: + raise ValueError("sub type {sub_type} not supported") + elif scheme_type == "openIdConnect": + headers[header_name] = _apply_bearer(value) + elif scheme_type == "oauth2": + if sub_type != "client_credentials": + headers[header_name] = _apply_bearer(value) + elif scheme_type == "http": + if sub_type == "bearer": + headers[header_name] = _apply_bearer(value) + else: + raise ValueError("sub type {sub_type} not supported") + else: + raise ValueError("scheme type {scheme_type} not supported") + + +def _apply_bearer(token: str) -> str: + return token.lower().startswith("bearer ") and token or f"Bearer {token}" + + +def _parse_basic_auth_scheme(headers: Dict[str, str], scheme: Any): + username = "" + password = "" + + if not isinstance(scheme, BaseModel): + raise TypeError("basic auth scheme must be a pydantic model") + + scheme_fields: Dict[str, FieldInfo] = scheme.__class__.model_fields + for name in scheme_fields: + scheme_field = scheme_fields[name] + + metadata = find_field_metadata(scheme_field, SecurityMetadata) + if metadata is None or metadata.field_name is None: + continue + + field_name = metadata.field_name + value = getattr(scheme, name) + + if field_name == "username": + username = value + if field_name == "password": + password = value + + data = f"{username}:{password}".encode() + headers["Authorization"] = f"Basic {base64.b64encode(data).decode()}" diff --git a/message/src/epilot_message/utils/serializers.py b/message/src/epilot_message/utils/serializers.py new file mode 100644 index 000000000..a98998a3f --- /dev/null +++ b/message/src/epilot_message/utils/serializers.py @@ -0,0 +1,181 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from decimal import Decimal +import json +from typing import Any, Dict, List, Union, get_args +import httpx +from typing_extensions import get_origin +from pydantic import ConfigDict, create_model +from pydantic_core import from_json +from typing_inspect import is_optional_type + +from ..types.basemodel import BaseModel, Nullable, OptionalNullable + + +def serialize_decimal(as_str: bool): + def serialize(d): + if is_optional_type(type(d)) and d is None: + return None + + if not isinstance(d, Decimal): + raise ValueError("Expected Decimal object") + + return str(d) if as_str else float(d) + + return serialize + + +def validate_decimal(d): + if d is None: + return None + + if isinstance(d, Decimal): + return d + + if not isinstance(d, (str, int, float)): + raise ValueError("Expected string, int or float") + + return Decimal(str(d)) + + +def serialize_float(as_str: bool): + def serialize(f): + if is_optional_type(type(f)) and f is None: + return None + + if not isinstance(f, float): + raise ValueError("Expected float") + + return str(f) if as_str else f + + return serialize + + +def validate_float(f): + if f is None: + return None + + if isinstance(f, float): + return f + + if not isinstance(f, str): + raise ValueError("Expected string") + + return float(f) + + +def serialize_int(as_str: bool): + def serialize(b): + if is_optional_type(type(b)) and b is None: + return None + + if not isinstance(b, int): + raise ValueError("Expected int") + + return str(b) if as_str else b + + return serialize + + +def validate_int(b): + if b is None: + return None + + if isinstance(b, int): + return b + + if not isinstance(b, str): + raise ValueError("Expected string") + + return int(b) + + +def validate_open_enum(is_int: bool): + def validate(e): + if e is None: + return None + + if is_int: + if not isinstance(e, int): + raise ValueError("Expected int") + else: + if not isinstance(e, str): + raise ValueError("Expected string") + + return e + + return validate + + +def unmarshal_json(raw, typ: Any) -> Any: + return unmarshal(from_json(raw), typ) + + +def unmarshal(val, typ: Any) -> Any: + unmarshaller = create_model( + "Unmarshaller", + body=(typ, ...), + __config__=ConfigDict(populate_by_name=True, arbitrary_types_allowed=True), + ) + + m = unmarshaller(body=val) + + # pyright: ignore[reportAttributeAccessIssue] + return m.body # type: ignore + + +def marshal_json(val, typ): + if is_nullable(typ) and val is None: + return "null" + + marshaller = create_model( + "Marshaller", + body=(typ, ...), + __config__=ConfigDict(populate_by_name=True, arbitrary_types_allowed=True), + ) + + m = marshaller(body=val) + + d = m.model_dump(by_alias=True, mode="json", exclude_none=True) + + if len(d) == 0: + return "" + + return json.dumps(d[next(iter(d))], separators=(",", ":"), sort_keys=True) + + +def is_nullable(field): + origin = get_origin(field) + if origin is Nullable or origin is OptionalNullable: + return True + + if not origin is Union or type(None) not in get_args(field): + return False + + for arg in get_args(field): + if get_origin(arg) is Nullable or get_origin(arg) is OptionalNullable: + return True + + return False + + +def stream_to_text(stream: httpx.Response) -> str: + return "".join(stream.iter_text()) + + +def get_pydantic_model(data: Any, typ: Any) -> Any: + if not _contains_pydantic_model(data): + return unmarshal(data, typ) + + return data + + +def _contains_pydantic_model(data: Any) -> bool: + if isinstance(data, BaseModel): + return True + if isinstance(data, List): + return any(_contains_pydantic_model(item) for item in data) + if isinstance(data, Dict): + return any(_contains_pydantic_model(value) for value in data.values()) + + return False diff --git a/message/src/epilot_message/utils/url.py b/message/src/epilot_message/utils/url.py new file mode 100644 index 000000000..b201bfa49 --- /dev/null +++ b/message/src/epilot_message/utils/url.py @@ -0,0 +1,150 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from decimal import Decimal +from typing import ( + Any, + Dict, + get_type_hints, + List, + Optional, + Union, + get_args, + get_origin, +) +from pydantic import BaseModel +from pydantic.fields import FieldInfo + +from .metadata import ( + PathParamMetadata, + find_field_metadata, +) +from .values import _get_serialized_params, _populate_from_globals, _val_to_string + + +def generate_url( + server_url: str, + path: str, + path_params: Any, + gbls: Optional[Any] = None, +) -> str: + path_param_values: Dict[str, str] = {} + + globals_already_populated = _populate_path_params( + path_params, gbls, path_param_values, [] + ) + if gbls is not None: + _populate_path_params(gbls, None, path_param_values, globals_already_populated) + + for key, value in path_param_values.items(): + path = path.replace("{" + key + "}", value, 1) + + return remove_suffix(server_url, "/") + path + + +def _populate_path_params( + path_params: Any, + gbls: Any, + path_param_values: Dict[str, str], + skip_fields: List[str], +) -> List[str]: + globals_already_populated: List[str] = [] + + if not isinstance(path_params, BaseModel): + return globals_already_populated + + path_param_fields: Dict[str, FieldInfo] = path_params.__class__.model_fields + path_param_field_types = get_type_hints(path_params.__class__) + for name in path_param_fields: + if name in skip_fields: + continue + + field = path_param_fields[name] + + param_metadata = find_field_metadata(field, PathParamMetadata) + if param_metadata is None: + continue + + param = getattr(path_params, name) if path_params is not None else None + param, global_found = _populate_from_globals( + name, param, PathParamMetadata, gbls + ) + if global_found: + globals_already_populated.append(name) + + if param is None: + continue + + f_name = field.alias if field.alias is not None else name + serialization = param_metadata.serialization + if serialization is not None: + serialized_params = _get_serialized_params( + param_metadata, f_name, param, path_param_field_types[name] + ) + for key, value in serialized_params.items(): + path_param_values[key] = value + else: + pp_vals: List[str] = [] + if param_metadata.style == "simple": + if isinstance(param, List): + for pp_val in param: + if pp_val is None: + continue + pp_vals.append(_val_to_string(pp_val)) + path_param_values[f_name] = ",".join(pp_vals) + elif isinstance(param, Dict): + for pp_key in param: + if param[pp_key] is None: + continue + if param_metadata.explode: + pp_vals.append(f"{pp_key}={_val_to_string(param[pp_key])}") + else: + pp_vals.append(f"{pp_key},{_val_to_string(param[pp_key])}") + path_param_values[f_name] = ",".join(pp_vals) + elif not isinstance(param, (str, int, float, complex, bool, Decimal)): + param_fields: Dict[str, FieldInfo] = param.__class__.model_fields + for name in param_fields: + param_field = param_fields[name] + + param_value_metadata = find_field_metadata( + param_field, PathParamMetadata + ) + if param_value_metadata is None: + continue + + param_name = ( + param_field.alias if param_field.alias is not None else name + ) + + param_field_val = getattr(param, name) + if param_field_val is None: + continue + if param_metadata.explode: + pp_vals.append( + f"{param_name}={_val_to_string(param_field_val)}" + ) + else: + pp_vals.append( + f"{param_name},{_val_to_string(param_field_val)}" + ) + path_param_values[f_name] = ",".join(pp_vals) + else: + path_param_values[f_name] = _val_to_string(param) + + return globals_already_populated + + +def is_optional(field): + return get_origin(field) is Union and type(None) in get_args(field) + + +def template_url(url_with_params: str, params: Dict[str, str]) -> str: + for key, value in params.items(): + url_with_params = url_with_params.replace("{" + key + "}", value) + + return url_with_params + + +def remove_suffix(input_string, suffix): + if suffix and input_string.endswith(suffix): + return input_string[: -len(suffix)] + return input_string diff --git a/message/src/epilot_message/utils/values.py b/message/src/epilot_message/utils/values.py new file mode 100644 index 000000000..24ccae3d0 --- /dev/null +++ b/message/src/epilot_message/utils/values.py @@ -0,0 +1,128 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from datetime import datetime +from enum import Enum +from email.message import Message +import os +from typing import Any, Callable, Dict, List, Optional, Tuple, TypeVar, Union + +from httpx import Response +from pydantic import BaseModel +from pydantic.fields import FieldInfo + +from .serializers import marshal_json + +from .metadata import ParamMetadata, find_field_metadata + + +def match_content_type(content_type: str, pattern: str) -> bool: + if pattern in (content_type, "*", "*/*"): + return True + + msg = Message() + msg["content-type"] = content_type + media_type = msg.get_content_type() + + if media_type == pattern: + return True + + parts = media_type.split("/") + if len(parts) == 2: + if pattern in (f"{parts[0]}/*", f"*/{parts[1]}"): + return True + + return False + + +def match_status_codes(status_codes: List[str], status_code: int) -> bool: + if "default" in status_codes: + return True + + for code in status_codes: + if code == str(status_code): + return True + + if code.endswith("XX") and code.startswith(str(status_code)[:1]): + return True + return False + + +T = TypeVar("T") + + +def get_global_from_env( + value: Optional[T], env_key: str, type_cast: Callable[[str], T] +) -> Optional[T]: + if value is not None: + return value + env_value = os.getenv(env_key) + if env_value is not None: + try: + return type_cast(env_value) + except ValueError: + pass + return None + + +def match_response( + response: Response, code: Union[str, List[str]], content_type: str +) -> bool: + codes = code if isinstance(code, list) else [code] + return match_status_codes(codes, response.status_code) and match_content_type( + response.headers.get("content-type", "application/octet-stream"), content_type + ) + + +def _populate_from_globals( + param_name: str, value: Any, param_metadata_type: type, gbls: Any +) -> Tuple[Any, bool]: + if gbls is None: + return value, False + + if not isinstance(gbls, BaseModel): + raise TypeError("globals must be a pydantic model") + + global_fields: Dict[str, FieldInfo] = gbls.__class__.model_fields + found = False + for name in global_fields: + field = global_fields[name] + if name is not param_name: + continue + + found = True + + if value is not None: + return value, True + + global_value = getattr(gbls, name) + + param_metadata = find_field_metadata(field, param_metadata_type) + if param_metadata is None: + return value, True + + return global_value, True + + return value, found + + +def _val_to_string(val) -> str: + if isinstance(val, bool): + return str(val).lower() + if isinstance(val, datetime): + return str(val.isoformat().replace("+00:00", "Z")) + if isinstance(val, Enum): + return str(val.value) + + return str(val) + + +def _get_serialized_params( + metadata: ParamMetadata, field_name: str, obj: Any, typ: type +) -> Dict[str, str]: + params: Dict[str, str] = {} + + serialization = metadata.serialization + if serialization == "json": + params[field_name] = marshal_json(obj, typ) + + return params