From 4b342e897560d387bc3ffbc80b489d32ae1f5eab Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Fri, 26 Jan 2024 14:21:07 +0000 Subject: [PATCH] SDK regeneration --- .fernignore | 8 + .github/ISSUE_TEMPLATE.md | 17 - .github/PULL_REQUEST_TEMPLATE.md | 27 - .github/workflows/ci.yml | 27 + .gitignore | 19 - CHANGELOG.md | 17 +- CONTRIBUTING.md | 14 - LICENSE | 2 +- README.md | 277 +- README.v1.md | 7 +- README.v2.md | 170 + audiences.go | 210 + audiences/client.go | 268 + audit_events.go | 78 + auditevents/client.go | 107 + auth_tokens.go | 43 + authtokens/client.go | 62 + automations.go | 105 + automations/client.go | 101 + brands.go | 186 + brands/client.go | 272 + bulk.go | 171 + bulk/client.go | 288 + client/client.go | 105 + client/client_test.go | 45 + core/core.go | 247 + core/core_test.go | 281 + core/idempotent_request_option.go | 72 + core/request_option.go | 107 + core/stringer.go | 13 + courier.go | 42 - environments.go | 13 + errors.go | 146 + go.mod | 7 +- go.sum | 9 +- lists.go | 214 + lists/client.go | 543 ++ messages.go | 305 +- messages/client.go | 371 + messages_test.go | 219 - notifications.go | 262 + notifications/client.go | 311 + option/idempotent_request_option.go | 24 + option/request_option.go | 41 + pointer.go | 103 + profiles.go | 310 +- profiles/client.go | 440 ++ send.go | 103 - send_test.go | 165 - templates.go | 45 + templates/client.go | 71 + tenants.go | 155 + tenants/client.go | 209 + translations/client.go | 147 + types.go | 6910 +++++++++++++++++ users/client/client.go | 34 + users/preferences.go | 107 + users/preferences/client.go | 206 + users/tenants.go | 151 + users/tenants/client.go | 194 + users/tokens.go | 122 + users/tokens/client.go | 316 + users/types.go | 451 ++ v2/api.go | 118 - v2/audiences.go | 215 - v2/audiences_test.go | 198 - v2/audit_events.go | 92 - v2/audit_events_test.go | 78 - v2/automations.go | 84 - v2/automations_test.go | 174 - v2/brands.go | 202 - v2/brands_test.go | 209 - v2/bulk.go | 152 - v2/bulk_test.go | 177 - v2/courier.go | 26 - v2/examples/audit-events/get_audit_event.go | 19 - v2/examples/audit-events/list_audit_events.go | 21 - v2/examples/automations/invoke.go | 32 - v2/examples/automations/invoke_template.go | 25 - v2/examples/brands/delete_brand.go | 13 - v2/examples/brands/get_brand.go | 19 - v2/examples/brands/get_brands.go | 21 - v2/examples/brands/post_brand.go | 15 - v2/examples/brands/put_brand.go | 15 - v2/examples/bulk/create_job.go | 24 - v2/examples/bulk/get_job.go | 19 - v2/examples/bulk/get_job_users.go | 22 - v2/examples/bulk/ingest_job.go | 25 - v2/examples/bulk/run_job.go | 13 - v2/examples/lists/delete_list.go | 13 - v2/examples/lists/get_list.go | 19 - v2/examples/lists/get_list_subscriptions.go | 19 - v2/examples/lists/get_lists.go | 22 - v2/examples/lists/list_subscribe.go | 13 - v2/examples/lists/list_unsubscribe.go | 13 - v2/examples/lists/post_list_subscriptions.go | 19 - v2/examples/lists/put_list.go | 18 - v2/examples/lists/put_list_subscriptions.go | 19 - v2/examples/lists/restore_list.go | 13 - .../cancel_notification_submission.go | 13 - .../notifications/get_notification_content.go | 19 - .../get_notification_draft_content.go | 19 - .../get_notification_submission_checks.go | 19 - .../notifications/get_notifications.go | 21 - .../post_notification_draft_variations.go | 23 - .../post_notification_varations.go | 23 - .../put_notification_submission_checks.go | 21 - v2/examples/send/send_message.go | 26 - v2/examples/send/send_message_idempotent.go | 38 - v2/examples/send/send_message_timeout.go | 35 - .../send_message_with_granular_metadata.go | 49 - .../send/send_message_with_metadata.go | 33 - v2/go.mod | 5 - v2/go.sum | 12 - v2/lib.go | 18 - v2/lists.go | 288 - v2/lists_test.go | 262 - v2/messages.go | 68 - v2/messages_test.go | 99 - v2/notifications.go | 229 - v2/notifications_test.go | 302 - v2/profiles.go | 23 - v2/profiles_test.go | 102 - v2/send.go | 149 - v2/send_test.go | 568 -- v2/shared.go | 6 - v2/tenants.go | 140 - v2/tenants_test.go | 110 - v2/webhooks.go | 7 - 129 files changed, 15157 insertions(+), 5838 deletions(-) create mode 100644 .fernignore delete mode 100644 .github/ISSUE_TEMPLATE.md delete mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/ci.yml delete mode 100644 .gitignore delete mode 100644 CONTRIBUTING.md create mode 100644 README.v2.md create mode 100644 audiences.go create mode 100644 audiences/client.go create mode 100644 audit_events.go create mode 100644 auditevents/client.go create mode 100644 auth_tokens.go create mode 100644 authtokens/client.go create mode 100644 automations.go create mode 100644 automations/client.go create mode 100644 brands.go create mode 100644 brands/client.go create mode 100644 bulk.go create mode 100644 bulk/client.go create mode 100644 client/client.go create mode 100644 client/client_test.go create mode 100644 core/core.go create mode 100644 core/core_test.go create mode 100644 core/idempotent_request_option.go create mode 100644 core/request_option.go create mode 100644 core/stringer.go delete mode 100644 courier.go create mode 100644 environments.go create mode 100644 errors.go create mode 100644 lists.go create mode 100644 lists/client.go create mode 100644 messages/client.go delete mode 100644 messages_test.go create mode 100644 notifications.go create mode 100644 notifications/client.go create mode 100644 option/idempotent_request_option.go create mode 100644 option/request_option.go create mode 100644 pointer.go create mode 100644 profiles/client.go delete mode 100644 send.go delete mode 100644 send_test.go create mode 100644 templates.go create mode 100644 templates/client.go create mode 100644 tenants.go create mode 100644 tenants/client.go create mode 100644 translations/client.go create mode 100644 types.go create mode 100644 users/client/client.go create mode 100644 users/preferences.go create mode 100644 users/preferences/client.go create mode 100644 users/tenants.go create mode 100644 users/tenants/client.go create mode 100644 users/tokens.go create mode 100644 users/tokens/client.go create mode 100644 users/types.go delete mode 100644 v2/api.go delete mode 100644 v2/audiences.go delete mode 100644 v2/audiences_test.go delete mode 100644 v2/audit_events.go delete mode 100644 v2/audit_events_test.go delete mode 100644 v2/automations.go delete mode 100644 v2/automations_test.go delete mode 100644 v2/brands.go delete mode 100644 v2/brands_test.go delete mode 100644 v2/bulk.go delete mode 100644 v2/bulk_test.go delete mode 100644 v2/courier.go delete mode 100644 v2/examples/audit-events/get_audit_event.go delete mode 100644 v2/examples/audit-events/list_audit_events.go delete mode 100644 v2/examples/automations/invoke.go delete mode 100644 v2/examples/automations/invoke_template.go delete mode 100644 v2/examples/brands/delete_brand.go delete mode 100644 v2/examples/brands/get_brand.go delete mode 100644 v2/examples/brands/get_brands.go delete mode 100644 v2/examples/brands/post_brand.go delete mode 100644 v2/examples/brands/put_brand.go delete mode 100644 v2/examples/bulk/create_job.go delete mode 100644 v2/examples/bulk/get_job.go delete mode 100644 v2/examples/bulk/get_job_users.go delete mode 100644 v2/examples/bulk/ingest_job.go delete mode 100644 v2/examples/bulk/run_job.go delete mode 100644 v2/examples/lists/delete_list.go delete mode 100644 v2/examples/lists/get_list.go delete mode 100644 v2/examples/lists/get_list_subscriptions.go delete mode 100644 v2/examples/lists/get_lists.go delete mode 100644 v2/examples/lists/list_subscribe.go delete mode 100644 v2/examples/lists/list_unsubscribe.go delete mode 100644 v2/examples/lists/post_list_subscriptions.go delete mode 100644 v2/examples/lists/put_list.go delete mode 100644 v2/examples/lists/put_list_subscriptions.go delete mode 100644 v2/examples/lists/restore_list.go delete mode 100644 v2/examples/notifications/cancel_notification_submission.go delete mode 100644 v2/examples/notifications/get_notification_content.go delete mode 100644 v2/examples/notifications/get_notification_draft_content.go delete mode 100644 v2/examples/notifications/get_notification_submission_checks.go delete mode 100644 v2/examples/notifications/get_notifications.go delete mode 100644 v2/examples/notifications/post_notification_draft_variations.go delete mode 100644 v2/examples/notifications/post_notification_varations.go delete mode 100644 v2/examples/notifications/put_notification_submission_checks.go delete mode 100644 v2/examples/send/send_message.go delete mode 100644 v2/examples/send/send_message_idempotent.go delete mode 100644 v2/examples/send/send_message_timeout.go delete mode 100644 v2/examples/send/send_message_with_granular_metadata.go delete mode 100644 v2/examples/send/send_message_with_metadata.go delete mode 100644 v2/go.mod delete mode 100644 v2/go.sum delete mode 100644 v2/lib.go delete mode 100644 v2/lists.go delete mode 100644 v2/lists_test.go delete mode 100644 v2/messages.go delete mode 100644 v2/messages_test.go delete mode 100644 v2/notifications.go delete mode 100644 v2/notifications_test.go delete mode 100644 v2/profiles.go delete mode 100644 v2/profiles_test.go delete mode 100644 v2/send.go delete mode 100644 v2/send_test.go delete mode 100644 v2/shared.go delete mode 100644 v2/tenants.go delete mode 100644 v2/tenants_test.go delete mode 100644 v2/webhooks.go diff --git a/.fernignore b/.fernignore new file mode 100644 index 0000000..20a9713 --- /dev/null +++ b/.fernignore @@ -0,0 +1,8 @@ +# Specify files that shouldn't be modified by Fern + +LICENSE +CHANGELOG.md + +README.v1.md +README.v2.md +README.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index f8b8ed9..0000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,17 +0,0 @@ -## Expected Behavior - - -## Actual Behavior - - -## Steps to Reproduce the Problem - - 1. - 1. - 1. - -## Specifications - - - Version: - - Platform: - - Subsystem: diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 2a08ef8..0000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,27 +0,0 @@ -## Description of the change - -> Description here - -## Type of change -- [ ] Bug fix (non-breaking change that fixes an issue) -- [ ] New feature (non-breaking change that adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - -## Related issues - -> Fix [#1]() - -## Checklists - -### Development - -- [ ] Lint rules pass locally -- [ ] The code changed/added as part of this pull request has been covered with tests -- [ ] All tests related to the changed code pass in development - -### Code review - -- [ ] This pull request has a descriptive title and information useful to a reviewer. There may be a screenshot or screencast attached -- [ ] "Ready for review" label attached to the PR and reviewers mentioned in a comment -- [ ] Changes have been reviewed by at least one other engineer -- [ ] Issue from task tracker has a link to this pull request diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d4c0a5d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,27 @@ +name: ci + +on: [push] + +jobs: + compile: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v3 + + - name: Set up go + uses: actions/setup-go@v4 + + - name: Compile + run: go build ./... + test: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v3 + + - name: Set up go + uses: actions/setup-go@v4 + + - name: Test + run: go test ./... diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 813faea..0000000 --- a/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Test binary, built with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Dependency directories (remove the comment below to include it) -# vendor/ - -# Editor directories -.idea/ -.vscode/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 685e797..297d6cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,21 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased][unreleased] +## [v3.0.0] +We now use :herb: [Fern](https://buildwithfern.com/) to generate our Go +SDK. WHile this releasing has breaking changes, it comes with several +quality of life upgrades: +- **Endpoint coverage**: All endpoints that are supported in our Node SDK are + now also supported in Go. +- **Resource-scoped SDK methods**: Endpoints are scoped under their resource. For + example, instead of `courier.DeleteBrands` the SDK now reads `courier.Brands.Delete(...)` +- **Docs on Hover**: All endpoint and parameter level documentation that you see + on our docs website are now embedded directly within the SDKs. +- **Strongly Typed**: The SDK now contains types for all of our modles -- including + complex unions like `ContentMessage` and `TemplateMessage`. +- **Retries with Exponential Backoffs**: The SDK now supports retries with exponential + backoff. + ## [v2.12.0] - Adds support for the cancel message endpoint (@BenAlderfer) @@ -116,4 +131,4 @@ This project adheres to [Semantic Versioning](http://semver.org/). - `GetProfile` now requires a `context` argument - `GetProfile` now returns a `map[string]json.RawMessage{}` instead of hydrating a struct reference - removed `MergeProfile`; use `client.API.SendRequestWithBytes(context.Background(), "PUT", "/profiles/"+recipientID, profile)` instead -- removed `UpdateProfile`; use `client.API.SendRequestWithBytes(context.Background(), "PUT", "/profiles/"+recipientID, profile)` instead +- removed `UpdateProfile`; use `client.API.SendRequestWithBytes(context.Background(), "PUT", "/profiles/"+recipientID, profile)` instead \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 9077905..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,14 +0,0 @@ -# Contributing - -PR's welcome: - -https://github.com/trycourier/courier-go - -## Releasing New Versions - -Make sure you have incremented the version string in `courier.go` to your new version string, hereafter referred to as `` and merged that commit. Then: - -```bash -git tag -a v -m v -git push origin v -``` \ No newline at end of file diff --git a/LICENSE b/LICENSE index 8868e84..d82d2ea 100644 --- a/LICENSE +++ b/LICENSE @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 16600aa..f5ee7cd 100644 --- a/README.md +++ b/README.md @@ -1,170 +1,205 @@ -# Courier Go SDK +# Courier Go Library -This Go package helps you send notifications through Courier, the smartest way to design & deliver notifications. Design your notifications once using our drag & drop editor, then deliver to any channel through one API. Email, mobile push, SMS, Slack — you name it! +[![Courier: Your Complete Communication Stack](https://marketing-assets-public.s3.us-west-1.amazonaws.com/github_nodejs.png)](https://courier.com) -!["Golang Gopher"](https://blog.golang.org/gopher/gopher.png) +[![go shield](https://img.shields.io/badge/go-docs-blue)](https://pkg.go.dev/github.com/merge-api/merge-go-client) +[![fern shield](https://img.shields.io/badge/%F0%9F%8C%BF-SDK%20generated%20by%20Fern-brightgreen)](https://buildwithfern.com/?utm_source=trycourier/courier-go/readme) -APIs supported: +This is the official Go library for sending notifications with the [Courier](https://courier.com) REST API. -- Accounts API -- Audiences API -- Audit Events API -- Automations API -- Brand API -- Messages API -- Profiles API -- Send API -- List API +## Documentation -## Official Courier API docs +For a full description of request and response payloads and properties, please see the +[official Courier API docs](https://www.courier.com/docs/reference/). -For a full description of request and response payloads and properties, please see the [official Courier API docs](https://docs.courier.com/reference). +## Requirements + +This module requires Go version >= 1.13. ## Installation -Download the package using `go get`: +Run the following command to use the Go library in your Go module: -```bash -go get -u github.com/trycourier/courier-go/v2 +```sh +go get github.com/trycourier/courier-go/v3 ``` -## Usage +## Instantiation ```go -package main - import ( - "context" - "fmt" + "context" + "fmt" - "github.com/trycourier/courier-go/v2" + courier "github.com/trycourier/courier-go/v3" + courierclient "github.com/trycourier/courier-go/v3" ) -func main() { - client := courier.CourierClient("", nil) - message := courier.SendMessageRequestBody{ - "template": "", - "to": map[string]string{ - "email": "test@email.com" - } - } - - reqID, err := client.SendMessage(context.Background(), message) - if err != nil { - panic(err) - } - - fmt.Println(reqID) -} +client := courierclient.NewClient( + courierclient.ClientWithAuthorizationToken(""), +) ``` -If you would like to send an idempotent message then be sure to use the SendMessageWithOptions method as shown below: +## Usage ```go -package main - import ( - "fmt" - "time" - "context" + "context" + "fmt" - "github.com/trycourier/courier-go/v2" + courier "github.com/trycourier/courier-go/v3" + courierclient "github.com/trycourier/courier-go/v3" ) -func main() { - client := courier.CourierClient("", nil) - message := map[string]interface{}{ - "template": "", - "to": map[string]string{ - "email": "test@email.com" - } - } - - reqID, err := client.SendMessageWithOptions( - context.Background(), - message, - courier.WithIdempotencyKey("fake-key"), - courier.WithIdempotencyKeyExpiration(time.Now().Add(time.Hour * 30)) - ) - if err != nil { - panic(err) - } - - fmt.Println(reqID) +client := courierclient.NewClient( + mergeclient.ClientWithAuthorizationToken(""), +) +sendResponse, err := client.Send( + context.TODO(), + &courier.SendMessageRequest{ + Message: courier.Message.NewMessageFromTemplateMessage({ + Template: "" + }), + }, +) +if err != nil { + return err } +fmt.Printf("Sent message %s\n", sendResponse.RequestId) ``` -If you need to use a base url other than the default https://api.courier.com, you can pass it in as the second paramter to the `CourierClient`: +## Unions +Our API, particularly the send method, uses several unions. Our Go SDK provides +strongly typed factories to construct these unions `courier.Message.NewMessageFromTemplateMessage(...)`. ```go -client := courier.CourierClient("", "") -``` - -## APIs - -For a full description of request and response payloads and properties, please see the [official Courier API docs](https://docs.courier.com/reference). - -### Send API - -- `SendMessage(ctx context.Context, body SendMessageRequestBody) (string, error)` [[?]](https://www.courier.com/docs/reference/send/message/) -- `Send(ctx context.Context, eventID, recipientID string, body interface{}) (string, error): object` [[?]](https://www.courier.com/docs/reference/send/message/) -- `SendMessageWithOptions(ctx context.Context, body map[string]interface{}, method string, opts ...Option) (string, error)` [[?]](https://www.courier.com/docs/reference/idempotent-requests/) +import ( + courier "github.com/trycourier/courier-go/v3" +) -### Messages API +courier.SendMessageRequest{ + // Construct a template message + Message: courier.Message.NewMessageFromTemplateMessage({ + // Construct a single recepient + To: courier.MessageRecipient.NewMessageRecipientFromRecipient( + // Construct a single recepient that is a user recepient + courier.Recipient.NewRecipientFromUserRecipient(&courier.UserRecipient{ + Email: courier.String("marty_mcfly@email.com"), + Data: &map[string]interface{}{ + "name": "Marty" + } + })) + Template: &map[string]interface{}{ + "name": "Marty" + } + }), + // Construct content from elemental content sugar + Content: courier.Content.NewContentFromElementalContentSugar({ + Title: "Back to the Future" + Body: "Oh my {{name}}, we need 1.21 Gigawatts!" + }) +} +``` -- `CancelMessage(ctx context.Context, messageID string) (*CancelMessageResponse, error)` [[?]](https://www.courier.com/docs/reference/logs/cancel/) -- `GetMessage(ctx context.Context, messageID string) (*MessageResponse, error)` [[?]](https://www.courier.com/docs/reference/messages/by-id/) +## Timeouts -### Audiences API +Setting a timeout for each individual request is as simple as using the standard +`context` library. Setting a one second timeout for an individual API call looks +like the following: -- `PutAudience(ctx context.Context, audienceId string, audience Audience) (*AudienceResponse, error)` [[?]](https://www.courier.com/docs/reference/audiences/put/) -- `GetAudience(ctx context.Context, audienceId string) (*AudienceResponseBody, error)` [[?]](https://www.courier.com/docs/reference/audiences/by-id/) -- `GetAudienceMembers(ctx context.Context, audienceId string, cursor string) (*GetAudienceMembersResponse, error)` [[?]](https://www.courier.com/docs/reference/audiences/list-audience-members/) -- `GetAudiences(ctx context.Context, cursor string) (*GetAudiencesResponse, error)` [[?]](https://www.courier.com/docs/reference/audiences/list-audiences/) -- `DeleteAudience(ctx context.Context, audienceId string) error ` [[?]](https://www.courier.com/docs/reference/audiences/delete/) +```go +ctx, cancel := context.WithTimeout(context.TODO(), time.Second) +defer cancel() + +response, err := client.send( + context.TODO(), + &courier.SendMessageRequest{ + Message: ... + }, +) +``` -### Brand API +## Client Options -- `GetBrands(ctx context.Context, cursor string) (*BrandsResponse, error)` [[?]](https://www.courier.com/docs/reference/brands/list/) -- `GetBrand(ctx context.Context, brandID string) (*BrandResponse, error)` [[?]](https://www.courier.com/docs/reference/brands/by-id/) -- `PostBrand(ctx context.Context, body PostBrandBody) (*BrandResponse, error)` [[?]](https://www.courier.com/docs/reference/brands/create/) -- `PutBrand(ctx context.Context, brandID string, body PutBrandBody) (*BrandResponse, error)` [[?]](https://www.courier.com/docs/reference/brands/replace/) -- `DeleteBrand(ctx context.Context, brandID string) error` [[?]](https://www.courier.com/docs/reference/brands/delete/) +A variety of client options are included to adapt the behavior of the library, which includes configuring authorization tokens to be sent on every request, or providing your own instrumented *http.Client. Both of these options are shown below: -### Profiles API +```go +client := courierclient.NewClient( + cohereclient.WithToken(""), + cohereclient.WithHTTPClient( + &http.Client{ + Timeout: 5 * time.Second, + }, + ), +) +``` -- `GetProfile(ctx context.Context, id string) (map[string]json.RawMessage, error): object` [[?]](https://docs.courier.com/reference/profiles-api#getprofilebyrecipientid) -- `MergeProfileBytes(ctx context.Context, id string, profile []byte) error` [[?]](https://docs.courier.com/reference/profiles-api#mergeprofilebyrecipientid) -- `UpdateProfileBytes(ctx context.Context, id string, profile []byte) error` [[?]](https://docs.courier.com/reference/profiles-api#patchprofilebyrecipientid) +> Providing your own `*http.Client` is recommended. Otherwise, the `http.DefaultClient` will be used, +> and your client will wait indefinitely for a response (unless the per-request, context-based timeout +> is used). -### Lists API +## Errors -- `GetLists(ctx context.Context, cursor string, pattern string) (*ListsResponse, error)` [[?]](https://www.courier.com/docs/reference/lists/list/) -- `GetList(ctx context.Context, listID string) (*ListResponse, error)` [[?]](https://www.courier.com/docs/reference/lists/by-id/) -- `PutList(ctx context.Context, listID string, body interface{}) error` [[?]](https://www.courier.com/docs/reference/lists/replace/) -- `DeleteList(ctx context.Context, listID string) error` [[?]](https://www.courier.com/docs/reference/lists/delete/) -- `RestoreList(ctx context.Context, listID string) error` [[?]](https://www.courier.com/docs/reference/lists/restore/) -- `GetListSubscriptions(ctx context.Context, listID string, cursor string) (*ListSubscriptionsResponse, error)` [[?]](https://www.courier.com/docs/reference/lists/subscriptions/) -- `PutListSubscriptions(ctx context.Context, listID string, body interface{}) error` [[?]](https://www.courier.com/docs/reference/lists/put-subscribe/) -- `PostListSubscriptions(ctx context.Context, listID string, body interface{}) error` [[?]](https://www.courier.com/docs/reference/lists/post-subscribe/) -- `ListSubscribe(ctx context.Context, listID string, recipientID string, body interface{}) error` [[?]](https://www.courier.com/docs/reference/lists/recipient-subscribe/) -- `ListUnsubscribe(ctx context.Context, listID string, recipientID string) error` [[?]](https://www.courier.com/docs/reference/lists/delete-subscription/) +Structured error types are returned from API calls that return non-success status codes. For example, +you can check if the error was due to a bad request (i.e. status code 400) with the following: -### Automations API +```go +response, err := client.send( + context.TODO(), + &courier.SendMessageRequest{ + Message: &{} + }, +) +if err != nil { + if apiErr, ok := err.(*core.APIError); ok && apiErr.StatusCode == http.StatusBadRequest { + // Do something with the bad request ... + } + return err +} +``` -- `InvokeAutomation(ctx context.Context, body interface{}) (string, error)`[[?]](https://www.courier.com/docs/reference/automation/invoke/) -- `InvokeAutomationTemplate(ctx context.Context, templateId string, body interface{}) (string, error)` [[?]](https://www.courier.com/docs/reference/automation/invoke-template/) +These errors are also compatible with the `errors.Is` and `errors.As` APIs, so you can access the error +like so: -### Audit Events API +```go +response, err := client.send( + context.TODO(), + &courier.SendMessageRequest{ + Message: &{} + }, +) +if err != nil { + var apiErr *core.APIError + if errors.As(err, apiError); ok { + switch apiErr.StatusCode { + case http.StatusBadRequest: + // Do something with the bad request ... + } + } + return err +} +``` -- `GetAuditEvent(ctx context.Context, auditEventID string) (*AuditEvent, error)` [[?]](https://www.courier.com/docs/reference/audit-events/by-id/) -- `ListAuditEvents(ctx context.Context, cursor string) (*ListAuditEventsResponse, error)` [[?]](https://www.courier.com/docs/reference/audit-events/list/) +If you'd like to wrap the errors with additional information and still retain the ability to access the type +with `errors.Is` and `errors.As`, you can use the `%w` directive: -## Staying Updated +```go +response, err := client.send( + context.TODO(), + &courier.SendMessageRequest{ + Message: &{} + }, +) +if err != nil { + return fmt.Errorf("failed to list employees: %w", err) +} +``` -To update this SDK to the latest version, use `go get -u github.com/trycourier/courier-go`. +## Contributing -## License +While we value open-source contributions to this SDK, this library is generated programmatically. Additions +made directly to this library would have to be moved over to our generation code, otherwise they would be +overwritten upon the next generated release. Feel free to open a PR as a proof of concept, but know that we +will not be able to merge it as-is. We suggest opening an issue first to discuss with us! -The package is available as open source under the terms of the MIT License. -[MIT License](http://www.opensource.org/licenses/mit-license.php) +On the other hand, contributions to the README are always very welcome! diff --git a/README.v1.md b/README.v1.md index 02a0053..b03fa67 100644 --- a/README.v1.md +++ b/README.v1.md @@ -20,29 +20,24 @@ package main import ( "context "log" - "github.com/trycourier/courier-go" ) - type profile struct { Email string `json:"email"` } type data struct { Foo string `json:"foo"` } - func send() { var authToken = "" var eventID = "" var recipientID = "" - profile := &profile{ email: "foo@example.com", } data := &data{ foo: "bar", } - client := courier.CourierClient(authToken, "https://api.trycourier.app") messageID, err := client.Send(context.Background(), eventID, recipientID, profile, data) if err != nil { @@ -111,4 +106,4 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/trycou ## License The package is available as open source under the terms of the MIT License. -[MIT License](http://www.opensource.org/licenses/mit-license.php) +[MIT License](http://www.opensource.org/licenses/mit-license.php) \ No newline at end of file diff --git a/README.v2.md b/README.v2.md new file mode 100644 index 0000000..944768e --- /dev/null +++ b/README.v2.md @@ -0,0 +1,170 @@ +# Courier Go SDK + +This Go package helps you send notifications through Courier, the smartest way to design & deliver notifications. Design your notifications once using our drag & drop editor, then deliver to any channel through one API. Email, mobile push, SMS, Slack — you name it! + +!["Golang Gopher"](https://blog.golang.org/gopher/gopher.png) + +APIs supported: + +- Accounts API +- Audiences API +- Audit Events API +- Automations API +- Brand API +- Messages API +- Profiles API +- Send API +- List API + +## Official Courier API docs + +For a full description of request and response payloads and properties, please see the [official Courier API docs](https://docs.courier.com/reference). + +## Installation + +Download the package using `go get`: + +```bash +go get -u github.com/trycourier/courier-go/v2 +``` + +## Usage + +```go +package main + +import ( + "context" + "fmt" + + "github.com/trycourier/courier-go/v2" +) + +func main() { + client := courier.CourierClient("", nil) + message := courier.SendMessageRequestBody{ + "template": "", + "to": map[string]string{ + "email": "test@email.com" + } + } + + reqID, err := client.SendMessage(context.Background(), message) + if err != nil { + panic(err) + } + + fmt.Println(reqID) +} +``` + +If you would like to send an idempotent message then be sure to use the SendMessageWithOptions method as shown below: + +```go +package main + +import ( + "fmt" + "time" + "context" + + "github.com/trycourier/courier-go/v2" +) + +func main() { + client := courier.CourierClient("", nil) + message := map[string]interface{}{ + "template": "", + "to": map[string]string{ + "email": "test@email.com" + } + } + + reqID, err := client.SendMessageWithOptions( + context.Background(), + message, + courier.WithIdempotencyKey("fake-key"), + courier.WithIdempotencyKeyExpiration(time.Now().Add(time.Hour * 30)) + ) + if err != nil { + panic(err) + } + + fmt.Println(reqID) +} +``` + +If you need to use a base url other than the default https://api.courier.com, you can pass it in as the second paramter to the `CourierClient`: + +```go +client := courier.CourierClient("", "") +``` + +## APIs + +For a full description of request and response payloads and properties, please see the [official Courier API docs](https://docs.courier.com/reference). + +### Send API + +- `SendMessage(ctx context.Context, body SendMessageRequestBody) (string, error)` [[?]](https://www.courier.com/docs/reference/send/message/) +- `Send(ctx context.Context, eventID, recipientID string, body interface{}) (string, error): object` [[?]](https://www.courier.com/docs/reference/send/message/) +- `SendMessageWithOptions(ctx context.Context, body map[string]interface{}, method string, opts ...Option) (string, error)` [[?]](https://www.courier.com/docs/reference/idempotent-requests/) + +### Messages API + +- `CancelMessage(ctx context.Context, messageID string) (*CancelMessageResponse, error)` [[?]](https://www.courier.com/docs/reference/logs/cancel/) +- `GetMessage(ctx context.Context, messageID string) (*MessageResponse, error)` [[?]](https://www.courier.com/docs/reference/messages/by-id/) + +### Audiences API + +- `PutAudience(ctx context.Context, audienceId string, audience Audience) (*AudienceResponse, error)` [[?]](https://www.courier.com/docs/reference/audiences/put/) +- `GetAudience(ctx context.Context, audienceId string) (*AudienceResponseBody, error)` [[?]](https://www.courier.com/docs/reference/audiences/by-id/) +- `GetAudienceMembers(ctx context.Context, audienceId string, cursor string) (*GetAudienceMembersResponse, error)` [[?]](https://www.courier.com/docs/reference/audiences/list-audience-members/) +- `GetAudiences(ctx context.Context, cursor string) (*GetAudiencesResponse, error)` [[?]](https://www.courier.com/docs/reference/audiences/list-audiences/) +- `DeleteAudience(ctx context.Context, audienceId string) error ` [[?]](https://www.courier.com/docs/reference/audiences/delete/) + +### Brand API + +- `GetBrands(ctx context.Context, cursor string) (*BrandsResponse, error)` [[?]](https://www.courier.com/docs/reference/brands/list/) +- `GetBrand(ctx context.Context, brandID string) (*BrandResponse, error)` [[?]](https://www.courier.com/docs/reference/brands/by-id/) +- `PostBrand(ctx context.Context, body PostBrandBody) (*BrandResponse, error)` [[?]](https://www.courier.com/docs/reference/brands/create/) +- `PutBrand(ctx context.Context, brandID string, body PutBrandBody) (*BrandResponse, error)` [[?]](https://www.courier.com/docs/reference/brands/replace/) +- `DeleteBrand(ctx context.Context, brandID string) error` [[?]](https://www.courier.com/docs/reference/brands/delete/) + +### Profiles API + +- `GetProfile(ctx context.Context, id string) (map[string]json.RawMessage, error): object` [[?]](https://docs.courier.com/reference/profiles-api#getprofilebyrecipientid) +- `MergeProfileBytes(ctx context.Context, id string, profile []byte) error` [[?]](https://docs.courier.com/reference/profiles-api#mergeprofilebyrecipientid) +- `UpdateProfileBytes(ctx context.Context, id string, profile []byte) error` [[?]](https://docs.courier.com/reference/profiles-api#patchprofilebyrecipientid) + +### Lists API + +- `GetLists(ctx context.Context, cursor string, pattern string) (*ListsResponse, error)` [[?]](https://www.courier.com/docs/reference/lists/list/) +- `GetList(ctx context.Context, listID string) (*ListResponse, error)` [[?]](https://www.courier.com/docs/reference/lists/by-id/) +- `PutList(ctx context.Context, listID string, body interface{}) error` [[?]](https://www.courier.com/docs/reference/lists/replace/) +- `DeleteList(ctx context.Context, listID string) error` [[?]](https://www.courier.com/docs/reference/lists/delete/) +- `RestoreList(ctx context.Context, listID string) error` [[?]](https://www.courier.com/docs/reference/lists/restore/) +- `GetListSubscriptions(ctx context.Context, listID string, cursor string) (*ListSubscriptionsResponse, error)` [[?]](https://www.courier.com/docs/reference/lists/subscriptions/) +- `PutListSubscriptions(ctx context.Context, listID string, body interface{}) error` [[?]](https://www.courier.com/docs/reference/lists/put-subscribe/) +- `PostListSubscriptions(ctx context.Context, listID string, body interface{}) error` [[?]](https://www.courier.com/docs/reference/lists/post-subscribe/) +- `ListSubscribe(ctx context.Context, listID string, recipientID string, body interface{}) error` [[?]](https://www.courier.com/docs/reference/lists/recipient-subscribe/) +- `ListUnsubscribe(ctx context.Context, listID string, recipientID string) error` [[?]](https://www.courier.com/docs/reference/lists/delete-subscription/) + +### Automations API + +- `InvokeAutomation(ctx context.Context, body interface{}) (string, error)`[[?]](https://www.courier.com/docs/reference/automation/invoke/) +- `InvokeAutomationTemplate(ctx context.Context, templateId string, body interface{}) (string, error)` [[?]](https://www.courier.com/docs/reference/automation/invoke-template/) + +### Audit Events API + +- `GetAuditEvent(ctx context.Context, auditEventID string) (*AuditEvent, error)` [[?]](https://www.courier.com/docs/reference/audit-events/by-id/) +- `ListAuditEvents(ctx context.Context, cursor string) (*ListAuditEventsResponse, error)` [[?]](https://www.courier.com/docs/reference/audit-events/list/) + +## Staying Updated + +To update this SDK to the latest version, use `go get -u github.com/trycourier/courier-go`. + +## License + +The package is available as open source under the terms of the MIT License. +[MIT License](http://www.opensource.org/licenses/mit-license.php) \ No newline at end of file diff --git a/audiences.go b/audiences.go new file mode 100644 index 0000000..a5492cb --- /dev/null +++ b/audiences.go @@ -0,0 +1,210 @@ +// This file was auto-generated by Fern from our API Definition. + +package api + +import ( + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" +) + +type AudiencesListParams struct { + // A unique identifier that allows for fetching the next set of audiences + Cursor *string `json:"-"` +} + +type AudienceMembersListParams struct { + // A unique identifier that allows for fetching the next set of members + Cursor *string `json:"-"` +} + +type Audience struct { + // A unique identifier representing the audience_id + Id string `json:"id"` + // The name of the audience + Name string `json:"name"` + // A description of the audience + Description string `json:"description"` + Filter *Filter `json:"filter,omitempty"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + + _rawJSON json.RawMessage +} + +func (a *Audience) UnmarshalJSON(data []byte) error { + type unmarshaler Audience + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = Audience(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *Audience) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AudienceListResponse struct { + Items []*Audience `json:"items,omitempty"` + Paging *Paging `json:"paging,omitempty"` + + _rawJSON json.RawMessage +} + +func (a *AudienceListResponse) UnmarshalJSON(data []byte) error { + type unmarshaler AudienceListResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AudienceListResponse(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AudienceListResponse) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AudienceMemberListResponse struct { + Items []*AudienceMember `json:"items,omitempty"` + Paging *Paging `json:"paging,omitempty"` + + _rawJSON json.RawMessage +} + +func (a *AudienceMemberListResponse) UnmarshalJSON(data []byte) error { + type unmarshaler AudienceMemberListResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AudienceMemberListResponse(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AudienceMemberListResponse) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AudienceUpdateResponse struct { + Audience *Audience `json:"audience,omitempty"` + + _rawJSON json.RawMessage +} + +func (a *AudienceUpdateResponse) UnmarshalJSON(data []byte) error { + type unmarshaler AudienceUpdateResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AudienceUpdateResponse(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AudienceUpdateResponse) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type Filter struct { + typeName string + SingleFilterConfig *SingleFilterConfig + NestedFilterConfig *NestedFilterConfig +} + +func NewFilterFromSingleFilterConfig(value *SingleFilterConfig) *Filter { + return &Filter{typeName: "singleFilterConfig", SingleFilterConfig: value} +} + +func NewFilterFromNestedFilterConfig(value *NestedFilterConfig) *Filter { + return &Filter{typeName: "nestedFilterConfig", NestedFilterConfig: value} +} + +func (f *Filter) UnmarshalJSON(data []byte) error { + valueSingleFilterConfig := new(SingleFilterConfig) + if err := json.Unmarshal(data, &valueSingleFilterConfig); err == nil { + f.typeName = "singleFilterConfig" + f.SingleFilterConfig = valueSingleFilterConfig + return nil + } + valueNestedFilterConfig := new(NestedFilterConfig) + if err := json.Unmarshal(data, &valueNestedFilterConfig); err == nil { + f.typeName = "nestedFilterConfig" + f.NestedFilterConfig = valueNestedFilterConfig + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, f) +} + +func (f Filter) MarshalJSON() ([]byte, error) { + switch f.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", f.typeName, f) + case "singleFilterConfig": + return json.Marshal(f.SingleFilterConfig) + case "nestedFilterConfig": + return json.Marshal(f.NestedFilterConfig) + } +} + +type FilterVisitor interface { + VisitSingleFilterConfig(*SingleFilterConfig) error + VisitNestedFilterConfig(*NestedFilterConfig) error +} + +func (f *Filter) Accept(visitor FilterVisitor) error { + switch f.typeName { + default: + return fmt.Errorf("invalid type %s in %T", f.typeName, f) + case "singleFilterConfig": + return visitor.VisitSingleFilterConfig(f.SingleFilterConfig) + case "nestedFilterConfig": + return visitor.VisitNestedFilterConfig(f.NestedFilterConfig) + } +} + +type AudienceUpdateParams struct { + // The name of the audience + Name *string `json:"name,omitempty"` + // A description of the audience + Description *string `json:"description,omitempty"` + Filter *Filter `json:"filter,omitempty"` +} diff --git a/audiences/client.go b/audiences/client.go new file mode 100644 index 0000000..83af49b --- /dev/null +++ b/audiences/client.go @@ -0,0 +1,268 @@ +// This file was auto-generated by Fern from our API Definition. + +package audiences + +import ( + bytes "bytes" + context "context" + json "encoding/json" + errors "errors" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + io "io" + http "net/http" + url "net/url" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +// Returns the specified audience by id. +func (c *Client) Get( + ctx context.Context, + // A unique identifier representing the audience_id + audienceId string, + opts ...option.RequestOption, +) (*v3.Audience, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"audiences/%v", audienceId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.Audience + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Creates or updates audience. +func (c *Client) Update( + ctx context.Context, + // A unique identifier representing the audience id + audienceId string, + request *v3.AudienceUpdateParams, + opts ...option.RequestOption, +) (*v3.AudienceUpdateResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"audiences/%v", audienceId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.AudienceUpdateResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Deletes the specified audience. +func (c *Client) Delete( + ctx context.Context, + // A unique identifier representing the audience id + audienceId string, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"audiences/%v", audienceId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodDelete, + Headers: headers, + Client: options.HTTPClient, + }, + ); err != nil { + return err + } + return nil +} + +// Get list of members of an audience. +func (c *Client) ListMembers( + ctx context.Context, + // A unique identifier representing the audience id + audienceId string, + request *v3.AudienceMembersListParams, + opts ...option.RequestOption, +) (*v3.AudienceMemberListResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"audiences/%v/members", audienceId) + + queryParams := make(url.Values) + if request.Cursor != nil { + queryParams.Add("cursor", fmt.Sprintf("%v", *request.Cursor)) + } + if len(queryParams) > 0 { + endpointURL += "?" + queryParams.Encode() + } + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.AudienceMemberListResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Get the audiences associated with the authorization token. +func (c *Client) ListAudiences( + ctx context.Context, + request *v3.AudiencesListParams, + opts ...option.RequestOption, +) (*v3.AudienceListResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := baseURL + "/" + "audiences" + + queryParams := make(url.Values) + if request.Cursor != nil { + queryParams.Add("cursor", fmt.Sprintf("%v", *request.Cursor)) + } + if len(queryParams) > 0 { + endpointURL += "?" + queryParams.Encode() + } + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.AudienceListResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} diff --git a/audit_events.go b/audit_events.go new file mode 100644 index 0000000..0d60b94 --- /dev/null +++ b/audit_events.go @@ -0,0 +1,78 @@ +// This file was auto-generated by Fern from our API Definition. + +package api + +import ( + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" +) + +type ListAuditEventsRequest struct { + // A unique identifier that allows for fetching the next set of audit events. + Cursor *string `json:"-"` +} + +type AuditEvent struct { + Actor *Actor `json:"actor,omitempty"` + Target *Target `json:"target,omitempty"` + AuditEventId string `json:"auditEventId"` + Source string `json:"source"` + Timestamp string `json:"timestamp"` + Type string `json:"type"` + + _rawJSON json.RawMessage +} + +func (a *AuditEvent) UnmarshalJSON(data []byte) error { + type unmarshaler AuditEvent + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AuditEvent(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AuditEvent) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type ListAuditEventsResponse struct { + Paging *Paging `json:"paging,omitempty"` + Results []*AuditEvent `json:"results,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *ListAuditEventsResponse) UnmarshalJSON(data []byte) error { + type unmarshaler ListAuditEventsResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListAuditEventsResponse(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListAuditEventsResponse) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} diff --git a/auditevents/client.go b/auditevents/client.go new file mode 100644 index 0000000..c518d52 --- /dev/null +++ b/auditevents/client.go @@ -0,0 +1,107 @@ +// This file was auto-generated by Fern from our API Definition. + +package auditevents + +import ( + context "context" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + http "net/http" + url "net/url" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +// Fetch the list of audit events +func (c *Client) List( + ctx context.Context, + request *v3.ListAuditEventsRequest, + opts ...option.RequestOption, +) (*v3.ListAuditEventsResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := baseURL + "/" + "audit-events" + + queryParams := make(url.Values) + if request.Cursor != nil { + queryParams.Add("cursor", fmt.Sprintf("%v", *request.Cursor)) + } + if len(queryParams) > 0 { + endpointURL += "?" + queryParams.Encode() + } + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.ListAuditEventsResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Fetch a specific audit event by ID. +func (c *Client) Get( + ctx context.Context, + // A unique identifier associated with the audit event you wish to retrieve + auditEventId string, + opts ...option.RequestOption, +) (*v3.AuditEvent, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"audit-events/%v", auditEventId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.AuditEvent + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} diff --git a/auth_tokens.go b/auth_tokens.go new file mode 100644 index 0000000..47beab2 --- /dev/null +++ b/auth_tokens.go @@ -0,0 +1,43 @@ +// This file was auto-generated by Fern from our API Definition. + +package api + +import ( + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" +) + +type IssueTokenParams struct { + Scope string `json:"scope"` + ExpiresIn string `json:"expires_in"` +} + +type IssueTokenResponse struct { + Token *string `json:"token,omitempty"` + + _rawJSON json.RawMessage +} + +func (i *IssueTokenResponse) UnmarshalJSON(data []byte) error { + type unmarshaler IssueTokenResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *i = IssueTokenResponse(value) + i._rawJSON = json.RawMessage(data) + return nil +} + +func (i *IssueTokenResponse) String() string { + if len(i._rawJSON) > 0 { + if value, err := core.StringifyJSON(i._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(i); err == nil { + return value + } + return fmt.Sprintf("%#v", i) +} diff --git a/authtokens/client.go b/authtokens/client.go new file mode 100644 index 0000000..d8e3c95 --- /dev/null +++ b/authtokens/client.go @@ -0,0 +1,62 @@ +// This file was auto-generated by Fern from our API Definition. + +package authtokens + +import ( + context "context" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + http "net/http" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +// Returns a new access token. +func (c *Client) IssueToken( + ctx context.Context, + request *v3.IssueTokenParams, + opts ...option.IdempotentRequestOption, +) (*v3.IssueTokenResponse, error) { + options := core.NewIdempotentRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := baseURL + "/" + "auth/issue-token" + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.IssueTokenResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPost, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} diff --git a/automations.go b/automations.go new file mode 100644 index 0000000..e7304f6 --- /dev/null +++ b/automations.go @@ -0,0 +1,105 @@ +// This file was auto-generated by Fern from our API Definition. + +package api + +import ( + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" +) + +type AutomationAdHocInvokeParams struct { + Brand *string `json:"brand,omitempty"` + Data map[string]interface{} `json:"data,omitempty"` + Profile *Profile `json:"profile,omitempty"` + Recipient *string `json:"recipient,omitempty"` + Template *string `json:"template,omitempty"` + Automation *Automation `json:"automation,omitempty"` + + _rawJSON json.RawMessage +} + +func (a *AutomationAdHocInvokeParams) UnmarshalJSON(data []byte) error { + type unmarshaler AutomationAdHocInvokeParams + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AutomationAdHocInvokeParams(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AutomationAdHocInvokeParams) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AutomationInvokeParams struct { + Brand *string `json:"brand,omitempty"` + Data map[string]interface{} `json:"data,omitempty"` + Profile *Profile `json:"profile,omitempty"` + Recipient *string `json:"recipient,omitempty"` + Template *string `json:"template,omitempty"` + + _rawJSON json.RawMessage +} + +func (a *AutomationInvokeParams) UnmarshalJSON(data []byte) error { + type unmarshaler AutomationInvokeParams + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AutomationInvokeParams(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AutomationInvokeParams) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AutomationInvokeResponse struct { + RunId string `json:"runId"` + + _rawJSON json.RawMessage +} + +func (a *AutomationInvokeResponse) UnmarshalJSON(data []byte) error { + type unmarshaler AutomationInvokeResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AutomationInvokeResponse(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AutomationInvokeResponse) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} diff --git a/automations/client.go b/automations/client.go new file mode 100644 index 0000000..b6f15c5 --- /dev/null +++ b/automations/client.go @@ -0,0 +1,101 @@ +// This file was auto-generated by Fern from our API Definition. + +package automations + +import ( + context "context" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + http "net/http" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +// Invoke an automation run from an automation template. +func (c *Client) InvokeAutomationTemplate( + ctx context.Context, + // A unique identifier representing the automation template to be invoked. This could be the Automation Template ID or the Automation Template Alias. + templateId string, + request *v3.AutomationInvokeParams, + opts ...option.IdempotentRequestOption, +) (*v3.AutomationInvokeResponse, error) { + options := core.NewIdempotentRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"automations/%v/invoke", templateId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.AutomationInvokeResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPost, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Invoke an ad hoc automation run. This endpoint accepts a JSON payload with a series of automation steps. For information about what steps are available, checkout the ad hoc automation guide [here](https://www.courier.com/docs/automations/steps/). +func (c *Client) InvokeAdHocAutomation( + ctx context.Context, + request *v3.AutomationAdHocInvokeParams, + opts ...option.IdempotentRequestOption, +) (*v3.AutomationInvokeResponse, error) { + options := core.NewIdempotentRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := baseURL + "/" + "automations/invoke" + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.AutomationInvokeResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPost, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} diff --git a/brands.go b/brands.go new file mode 100644 index 0000000..ecbe5c9 --- /dev/null +++ b/brands.go @@ -0,0 +1,186 @@ +// This file was auto-generated by Fern from our API Definition. + +package api + +import ( + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" +) + +type ListBrandsRequest struct { + // A unique identifier that allows for fetching the next set of brands. + Cursor *string `json:"-"` +} + +type BrandUpdateParameters struct { + // The name of the brand. + Name string `json:"name"` + Settings *BrandSettings `json:"settings,omitempty"` + Snippets *BrandSnippets `json:"snippets,omitempty"` +} + +type Brand struct { + // The date/time of when the brand was created. Represented in milliseconds since Unix epoch. + Created int `json:"created"` + // Brand Identifier + Id *string `json:"id,omitempty"` + // Brand name + Name string `json:"name"` + // The date/time of when the brand was published. Represented in milliseconds since Unix epoch. + Published int `json:"published"` + Settings *BrandSettings `json:"settings,omitempty"` + // The date/time of when the brand was updated. Represented in milliseconds since Unix epoch. + Updated int `json:"updated"` + Snippets *BrandSnippets `json:"snippets,omitempty"` + // The version identifier for the brand + Version string `json:"version"` + + _rawJSON json.RawMessage +} + +func (b *Brand) UnmarshalJSON(data []byte) error { + type unmarshaler Brand + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = Brand(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *Brand) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BrandParameters struct { + Id *string `json:"id,omitempty"` + // The name of the brand. + Name string `json:"name"` + Settings *BrandSettings `json:"settings,omitempty"` + Snippets *BrandSnippets `json:"snippets,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BrandParameters) UnmarshalJSON(data []byte) error { + type unmarshaler BrandParameters + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BrandParameters(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BrandParameters) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BrandSettings struct { + Colors *BrandColors `json:"colors,omitempty"` + Inapp interface{} `json:"inapp,omitempty"` + Email *Email `json:"email,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BrandSettings) UnmarshalJSON(data []byte) error { + type unmarshaler BrandSettings + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BrandSettings(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BrandSettings) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BrandSnippets struct { + Items []*BrandSnippet `json:"items,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BrandSnippets) UnmarshalJSON(data []byte) error { + type unmarshaler BrandSnippets + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BrandSnippets(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BrandSnippets) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BrandsResponse struct { + Paging *Paging `json:"paging,omitempty"` + Results []*Brand `json:"results,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BrandsResponse) UnmarshalJSON(data []byte) error { + type unmarshaler BrandsResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BrandsResponse(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BrandsResponse) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} diff --git a/brands/client.go b/brands/client.go new file mode 100644 index 0000000..09bae41 --- /dev/null +++ b/brands/client.go @@ -0,0 +1,272 @@ +// This file was auto-generated by Fern from our API Definition. + +package brands + +import ( + bytes "bytes" + context "context" + json "encoding/json" + errors "errors" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + io "io" + http "net/http" + url "net/url" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +func (c *Client) Create( + ctx context.Context, + request *v3.BrandParameters, + opts ...option.IdempotentRequestOption, +) (*v3.Brand, error) { + options := core.NewIdempotentRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := baseURL + "/" + "brands" + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + case 402: + value := new(v3.PaymentRequiredError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + case 409: + value := new(v3.AlreadyExistsError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.Brand + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPost, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Fetch a specific brand by brand ID. +func (c *Client) Get( + ctx context.Context, + // A unique identifier associated with the brand you wish to retrieve. + brandId string, + opts ...option.RequestOption, +) (*v3.Brand, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"brands/%v", brandId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.Brand + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Get the list of brands. +func (c *Client) List( + ctx context.Context, + request *v3.ListBrandsRequest, + opts ...option.RequestOption, +) (*v3.BrandsResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := baseURL + "/" + "brands" + + queryParams := make(url.Values) + if request.Cursor != nil { + queryParams.Add("cursor", fmt.Sprintf("%v", *request.Cursor)) + } + if len(queryParams) > 0 { + endpointURL += "?" + queryParams.Encode() + } + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.BrandsResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Delete a brand by brand ID. +func (c *Client) Delete( + ctx context.Context, + // A unique identifier associated with the brand you wish to retrieve. + brandId string, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"brands/%v", brandId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 409: + value := new(v3.ConflictError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodDelete, + Headers: headers, + Client: options.HTTPClient, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return err + } + return nil +} + +// Replace an existing brand with the supplied values. +func (c *Client) Replace( + ctx context.Context, + // A unique identifier associated with the brand you wish to update. + brandId string, + request *v3.BrandUpdateParameters, + opts ...option.RequestOption, +) (*v3.Brand, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"brands/%v", brandId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.Brand + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} diff --git a/bulk.go b/bulk.go new file mode 100644 index 0000000..1be31c5 --- /dev/null +++ b/bulk.go @@ -0,0 +1,171 @@ +// This file was auto-generated by Fern from our API Definition. + +package api + +import ( + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" +) + +type BulkCreateJobParams struct { + Message *InboundBulkMessage `json:"message,omitempty"` +} + +type BulkCreateJobResponse struct { + JobId string `json:"jobId"` + + _rawJSON json.RawMessage +} + +func (b *BulkCreateJobResponse) UnmarshalJSON(data []byte) error { + type unmarshaler BulkCreateJobResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BulkCreateJobResponse(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BulkCreateJobResponse) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BulkGetJobResponse struct { + Job *JobDetails `json:"job,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BulkGetJobResponse) UnmarshalJSON(data []byte) error { + type unmarshaler BulkGetJobResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BulkGetJobResponse(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BulkGetJobResponse) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BulkGetJobUsersResponse struct { + Items []*BulkMessageUserResponse `json:"items,omitempty"` + Paging *Paging `json:"paging,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BulkGetJobUsersResponse) UnmarshalJSON(data []byte) error { + type unmarshaler BulkGetJobUsersResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BulkGetJobUsersResponse(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BulkGetJobUsersResponse) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BulkIngestUsersParams struct { + Users []*InboundBulkMessageUser `json:"users,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BulkIngestUsersParams) UnmarshalJSON(data []byte) error { + type unmarshaler BulkIngestUsersParams + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BulkIngestUsersParams(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BulkIngestUsersParams) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type InboundBulkMessage struct { + // A unique identifier that represents the brand that should be used + // for rendering the notification. + Brand *string `json:"brand,omitempty"` + // JSON that includes any data you want to pass to a message template. + // The data will populate the corresponding template variables. + Data map[string]interface{} `json:"data,omitempty"` + Event *string `json:"event,omitempty"` + Locale map[string]interface{} `json:"locale,omitempty"` + // JSON that is merged into the request sent by Courier to the provider + // to override properties or to gain access to features in the provider + // API that are not natively supported by Courier. + Override interface{} `json:"override,omitempty"` + Message *InboundBulkMessageV2 `json:"message,omitempty"` + + _rawJSON json.RawMessage +} + +func (i *InboundBulkMessage) UnmarshalJSON(data []byte) error { + type unmarshaler InboundBulkMessage + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *i = InboundBulkMessage(value) + i._rawJSON = json.RawMessage(data) + return nil +} + +func (i *InboundBulkMessage) String() string { + if len(i._rawJSON) > 0 { + if value, err := core.StringifyJSON(i._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(i); err == nil { + return value + } + return fmt.Sprintf("%#v", i) +} diff --git a/bulk/client.go b/bulk/client.go new file mode 100644 index 0000000..f5f68f4 --- /dev/null +++ b/bulk/client.go @@ -0,0 +1,288 @@ +// This file was auto-generated by Fern from our API Definition. + +package bulk + +import ( + bytes "bytes" + context "context" + json "encoding/json" + errors "errors" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + io "io" + http "net/http" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +func (c *Client) CreateJob( + ctx context.Context, + request *v3.BulkCreateJobParams, + opts ...option.IdempotentRequestOption, +) (*v3.BulkCreateJobResponse, error) { + options := core.NewIdempotentRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := baseURL + "/" + "bulk" + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.BulkCreateJobResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPost, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Ingest user data into a Bulk Job +func (c *Client) IngestUsers( + ctx context.Context, + // A unique identifier representing the bulk job + jobId string, + request *v3.BulkIngestUsersParams, + opts ...option.IdempotentRequestOption, +) error { + options := core.NewIdempotentRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"bulk/%v", jobId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPost, + Headers: headers, + Client: options.HTTPClient, + Request: request, + }, + ); err != nil { + return err + } + return nil +} + +// Run a bulk job +func (c *Client) RunJob( + ctx context.Context, + // A unique identifier representing the bulk job + jobId string, + opts ...option.IdempotentRequestOption, +) error { + options := core.NewIdempotentRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"bulk/%v/run", jobId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPost, + Headers: headers, + Client: options.HTTPClient, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return err + } + return nil +} + +// Get a bulk job +func (c *Client) GetJob( + ctx context.Context, + // A unique identifier representing the bulk job + jobId string, + opts ...option.RequestOption, +) (*v3.BulkGetJobResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"bulk/%v", jobId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.BulkGetJobResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Get Bulk Job Users +func (c *Client) GetUsers( + ctx context.Context, + // A unique identifier representing the bulk job + jobId string, + opts ...option.RequestOption, +) (*v3.BulkGetJobUsersResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"bulk/%v/users", jobId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.BulkGetJobUsersResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} diff --git a/client/client.go b/client/client.go new file mode 100644 index 0000000..38e1df7 --- /dev/null +++ b/client/client.go @@ -0,0 +1,105 @@ +// This file was auto-generated by Fern from our API Definition. + +package client + +import ( + context "context" + v3 "github.com/trycourier/courier-go/v3" + audiences "github.com/trycourier/courier-go/v3/audiences" + auditevents "github.com/trycourier/courier-go/v3/auditevents" + authtokens "github.com/trycourier/courier-go/v3/authtokens" + automations "github.com/trycourier/courier-go/v3/automations" + brands "github.com/trycourier/courier-go/v3/brands" + bulk "github.com/trycourier/courier-go/v3/bulk" + core "github.com/trycourier/courier-go/v3/core" + lists "github.com/trycourier/courier-go/v3/lists" + messages "github.com/trycourier/courier-go/v3/messages" + notifications "github.com/trycourier/courier-go/v3/notifications" + option "github.com/trycourier/courier-go/v3/option" + profiles "github.com/trycourier/courier-go/v3/profiles" + templates "github.com/trycourier/courier-go/v3/templates" + tenants "github.com/trycourier/courier-go/v3/tenants" + translations "github.com/trycourier/courier-go/v3/translations" + usersclient "github.com/trycourier/courier-go/v3/users/client" + http "net/http" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header + + Audiences *audiences.Client + AuditEvents *auditevents.Client + AuthTokens *authtokens.Client + Automations *automations.Client + Brands *brands.Client + Bulk *bulk.Client + Lists *lists.Client + Messages *messages.Client + Notifications *notifications.Client + Profiles *profiles.Client + Templates *templates.Client + Tenants *tenants.Client + Translations *translations.Client + Users *usersclient.Client +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + Audiences: audiences.NewClient(opts...), + AuditEvents: auditevents.NewClient(opts...), + AuthTokens: authtokens.NewClient(opts...), + Automations: automations.NewClient(opts...), + Brands: brands.NewClient(opts...), + Bulk: bulk.NewClient(opts...), + Lists: lists.NewClient(opts...), + Messages: messages.NewClient(opts...), + Notifications: notifications.NewClient(opts...), + Profiles: profiles.NewClient(opts...), + Templates: templates.NewClient(opts...), + Tenants: tenants.NewClient(opts...), + Translations: translations.NewClient(opts...), + Users: usersclient.NewClient(opts...), + } +} + +// Use the send API to send a message to one or more recipients. +func (c *Client) Send( + ctx context.Context, + request *v3.SendMessageRequest, + opts ...option.IdempotentRequestOption, +) (*v3.SendMessageResponse, error) { + options := core.NewIdempotentRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := baseURL + "/" + "send" + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.SendMessageResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPost, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} diff --git a/client/client_test.go b/client/client_test.go new file mode 100644 index 0000000..e93a027 --- /dev/null +++ b/client/client_test.go @@ -0,0 +1,45 @@ +// This file was auto-generated by Fern from our API Definition. + +package client + +import ( + assert "github.com/stretchr/testify/assert" + option "github.com/trycourier/courier-go/v3/option" + http "net/http" + testing "testing" + time "time" +) + +func TestNewClient(t *testing.T) { + t.Run("default", func(t *testing.T) { + c := NewClient() + assert.Empty(t, c.baseURL) + }) + + t.Run("base url", func(t *testing.T) { + c := NewClient( + option.WithBaseURL("test.co"), + ) + assert.Equal(t, "test.co", c.baseURL) + }) + + t.Run("http client", func(t *testing.T) { + httpClient := &http.Client{ + Timeout: 5 * time.Second, + } + c := NewClient( + option.WithHTTPClient(httpClient), + ) + assert.Empty(t, c.baseURL) + }) + + t.Run("http header", func(t *testing.T) { + header := make(http.Header) + header.Set("X-API-Tenancy", "test") + c := NewClient( + option.WithHTTPHeader(header), + ) + assert.Empty(t, c.baseURL) + assert.Equal(t, "test", c.header.Get("X-API-Tenancy")) + }) +} diff --git a/core/core.go b/core/core.go new file mode 100644 index 0000000..1023d53 --- /dev/null +++ b/core/core.go @@ -0,0 +1,247 @@ +package core + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "mime/multipart" + "net/http" +) + +const ( + // contentType specifies the JSON Content-Type header value. + contentType = "application/json" + contentTypeHeader = "Content-Type" +) + +// HTTPClient is an interface for a subset of the *http.Client. +type HTTPClient interface { + Do(*http.Request) (*http.Response, error) +} + +// MergeHeaders merges the given headers together, where the right +// takes precedence over the left. +func MergeHeaders(left, right http.Header) http.Header { + for key, values := range right { + if len(values) > 1 { + left[key] = values + continue + } + if value := right.Get(key); value != "" { + left.Set(key, value) + } + } + return left +} + +// WriteMultipartJSON writes the given value as a JSON part. +// This is used to serialize non-primitive multipart properties +// (i.e. lists, objects, etc). +func WriteMultipartJSON(writer *multipart.Writer, field string, value interface{}) error { + bytes, err := json.Marshal(value) + if err != nil { + return err + } + return writer.WriteField(field, string(bytes)) +} + +// APIError is a lightweight wrapper around the standard error +// interface that preserves the status code from the RPC, if any. +type APIError struct { + err error + + StatusCode int `json:"-"` +} + +// NewAPIError constructs a new API error. +func NewAPIError(statusCode int, err error) *APIError { + return &APIError{ + err: err, + StatusCode: statusCode, + } +} + +// Unwrap returns the underlying error. This also makes the error compatible +// with errors.As and errors.Is. +func (a *APIError) Unwrap() error { + if a == nil { + return nil + } + return a.err +} + +// Error returns the API error's message. +func (a *APIError) Error() string { + if a == nil || (a.err == nil && a.StatusCode == 0) { + return "" + } + if a.err == nil { + return fmt.Sprintf("%d", a.StatusCode) + } + if a.StatusCode == 0 { + return a.err.Error() + } + return fmt.Sprintf("%d: %s", a.StatusCode, a.err.Error()) +} + +// ErrorDecoder decodes *http.Response errors and returns a +// typed API error (e.g. *APIError). +type ErrorDecoder func(statusCode int, body io.Reader) error + +// Caller calls APIs and deserializes their response, if any. +type Caller struct { + client HTTPClient +} + +// NewCaller returns a new *Caller backed by the given HTTP client. +func NewCaller(client HTTPClient) *Caller { + if client == nil { + return &Caller{ + client: http.DefaultClient, + } + } + return &Caller{ + client: client, + } +} + +// CallParams represents the parameters used to issue an API call. +type CallParams struct { + URL string + Method string + Headers http.Header + Client HTTPClient + Request interface{} + Response interface{} + ResponseIsOptional bool + ErrorDecoder ErrorDecoder +} + +// Call issues an API call according to the given call parameters. +func (c *Caller) Call(ctx context.Context, params *CallParams) error { + req, err := newRequest(ctx, params.URL, params.Method, params.Headers, params.Request) + if err != nil { + return err + } + + // If the call has been cancelled, don't issue the request. + if err := ctx.Err(); err != nil { + return err + } + + client := c.client + if params.Client != nil { + // Use the HTTP client scoped to the request. + client = params.Client + } + + resp, err := client.Do(req) + if err != nil { + return err + } + + // Close the response body after we're done. + defer resp.Body.Close() + + // Check if the call was cancelled before we return the error + // associated with the call and/or unmarshal the response data. + if err := ctx.Err(); err != nil { + return err + } + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return decodeError(resp, params.ErrorDecoder) + } + + // Mutate the response parameter in-place. + if params.Response != nil { + if writer, ok := params.Response.(io.Writer); ok { + _, err = io.Copy(writer, resp.Body) + } else { + err = json.NewDecoder(resp.Body).Decode(params.Response) + } + if err != nil { + if err == io.EOF { + if params.ResponseIsOptional { + // The response is optional, so we should ignore the + // io.EOF error + return nil + } + return fmt.Errorf("expected a %T response, but the server responded with nothing", params.Response) + } + return err + } + } + + return nil +} + +// newRequest returns a new *http.Request with all of the fields +// required to issue the call. +func newRequest( + ctx context.Context, + url string, + method string, + endpointHeaders http.Header, + request interface{}, +) (*http.Request, error) { + requestBody, err := newRequestBody(request) + if err != nil { + return nil, err + } + req, err := http.NewRequestWithContext(ctx, method, url, requestBody) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + req.Header.Set(contentTypeHeader, contentType) + for name, values := range endpointHeaders { + req.Header[name] = values + } + return req, nil +} + +// newRequestBody returns a new io.Reader that represents the HTTP request body. +func newRequestBody(request interface{}) (io.Reader, error) { + var requestBody io.Reader + if request != nil { + if body, ok := request.(io.Reader); ok { + requestBody = body + } else { + requestBytes, err := json.Marshal(request) + if err != nil { + return nil, err + } + requestBody = bytes.NewReader(requestBytes) + } + } + return requestBody, nil +} + +// decodeError decodes the error from the given HTTP response. Note that +// it's the caller's responsibility to close the response body. +func decodeError(response *http.Response, errorDecoder ErrorDecoder) error { + if errorDecoder != nil { + // This endpoint has custom errors, so we'll + // attempt to unmarshal the error into a structured + // type based on the status code. + return errorDecoder(response.StatusCode, response.Body) + } + // This endpoint doesn't have any custom error + // types, so we just read the body as-is, and + // put it into a normal error. + bytes, err := io.ReadAll(response.Body) + if err != nil && err != io.EOF { + return err + } + if err == io.EOF { + // The error didn't have a response body, + // so all we can do is return an error + // with the status code. + return NewAPIError(response.StatusCode, nil) + } + return NewAPIError(response.StatusCode, errors.New(string(bytes))) +} diff --git a/core/core_test.go b/core/core_test.go new file mode 100644 index 0000000..535e635 --- /dev/null +++ b/core/core_test.go @@ -0,0 +1,281 @@ +package core + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/http/httptest" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestCase represents a single test case. +type TestCase struct { + description string + + // Server-side assertions. + giveMethod string + giveResponseIsOptional bool + giveHeader http.Header + giveErrorDecoder ErrorDecoder + giveRequest *Request + + // Client-side assertions. + wantResponse *Response + wantError error +} + +// Request a simple request body. +type Request struct { + Id string `json:"id"` +} + +// Response a simple response body. +type Response struct { + Id string `json:"id"` +} + +// NotFoundError represents a 404. +type NotFoundError struct { + *APIError + + Message string `json:"message"` +} + +func TestCall(t *testing.T) { + tests := []*TestCase{ + { + description: "GET success", + giveMethod: http.MethodGet, + giveHeader: http.Header{ + "X-API-Status": []string{"success"}, + }, + giveRequest: &Request{ + Id: "123", + }, + wantResponse: &Response{ + Id: "123", + }, + }, + { + description: "GET not found", + giveMethod: http.MethodGet, + giveHeader: http.Header{ + "X-API-Status": []string{"fail"}, + }, + giveRequest: &Request{ + Id: strconv.Itoa(http.StatusNotFound), + }, + giveErrorDecoder: newTestErrorDecoder(t), + wantError: &NotFoundError{ + APIError: NewAPIError( + http.StatusNotFound, + errors.New(`{"message":"ID \"404\" not found"}`), + ), + }, + }, + { + description: "POST optional response", + giveMethod: http.MethodPost, + giveHeader: http.Header{ + "X-API-Status": []string{"success"}, + }, + giveRequest: &Request{ + Id: "123", + }, + giveResponseIsOptional: true, + }, + { + description: "POST API error", + giveMethod: http.MethodPost, + giveHeader: http.Header{ + "X-API-Status": []string{"fail"}, + }, + giveRequest: &Request{ + Id: strconv.Itoa(http.StatusInternalServerError), + }, + wantError: NewAPIError( + http.StatusInternalServerError, + errors.New("failed to process request"), + ), + }, + } + for _, test := range tests { + t.Run(test.description, func(t *testing.T) { + var ( + server = newTestServer(t, test) + client = server.Client() + ) + caller := NewCaller(client) + var response *Response + err := caller.Call( + context.Background(), + &CallParams{ + URL: server.URL, + Method: test.giveMethod, + Headers: test.giveHeader, + Request: test.giveRequest, + Response: &response, + ResponseIsOptional: test.giveResponseIsOptional, + ErrorDecoder: test.giveErrorDecoder, + }, + ) + if test.wantError != nil { + assert.EqualError(t, err, test.wantError.Error()) + return + } + require.NoError(t, err) + assert.Equal(t, test.wantResponse, response) + }) + } +} + +func TestMergeHeaders(t *testing.T) { + t.Run("both empty", func(t *testing.T) { + merged := MergeHeaders(make(http.Header), make(http.Header)) + assert.Empty(t, merged) + }) + + t.Run("empty left", func(t *testing.T) { + left := make(http.Header) + + right := make(http.Header) + right.Set("X-API-Version", "0.0.1") + + merged := MergeHeaders(left, right) + assert.Equal(t, "0.0.1", merged.Get("X-API-Version")) + }) + + t.Run("empty right", func(t *testing.T) { + left := make(http.Header) + left.Set("X-API-Version", "0.0.1") + + right := make(http.Header) + + merged := MergeHeaders(left, right) + assert.Equal(t, "0.0.1", merged.Get("X-API-Version")) + }) + + t.Run("single value override", func(t *testing.T) { + left := make(http.Header) + left.Set("X-API-Version", "0.0.0") + + right := make(http.Header) + right.Set("X-API-Version", "0.0.1") + + merged := MergeHeaders(left, right) + assert.Equal(t, []string{"0.0.1"}, merged.Values("X-API-Version")) + }) + + t.Run("multiple value override", func(t *testing.T) { + left := make(http.Header) + left.Set("X-API-Versions", "0.0.0") + + right := make(http.Header) + right.Add("X-API-Versions", "0.0.1") + right.Add("X-API-Versions", "0.0.2") + + merged := MergeHeaders(left, right) + assert.Equal(t, []string{"0.0.1", "0.0.2"}, merged.Values("X-API-Versions")) + }) + + t.Run("disjoint merge", func(t *testing.T) { + left := make(http.Header) + left.Set("X-API-Tenancy", "test") + + right := make(http.Header) + right.Set("X-API-Version", "0.0.1") + + merged := MergeHeaders(left, right) + assert.Equal(t, []string{"test"}, merged.Values("X-API-Tenancy")) + assert.Equal(t, []string{"0.0.1"}, merged.Values("X-API-Version")) + }) +} + +// newTestServer returns a new *httptest.Server configured with the +// given test parameters. +func newTestServer(t *testing.T, tc *TestCase) *httptest.Server { + return httptest.NewServer( + http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, tc.giveMethod, r.Method) + assert.Equal(t, contentType, r.Header.Get(contentTypeHeader)) + for header, value := range tc.giveHeader { + assert.Equal(t, value, r.Header.Values(header)) + } + + bytes, err := io.ReadAll(r.Body) + require.NoError(t, err) + + request := new(Request) + require.NoError(t, json.Unmarshal(bytes, request)) + + switch request.Id { + case strconv.Itoa(http.StatusNotFound): + notFoundError := &NotFoundError{ + APIError: &APIError{ + StatusCode: http.StatusNotFound, + }, + Message: fmt.Sprintf("ID %q not found", request.Id), + } + bytes, err = json.Marshal(notFoundError) + require.NoError(t, err) + + w.WriteHeader(http.StatusNotFound) + _, err = w.Write(bytes) + require.NoError(t, err) + return + + case strconv.Itoa(http.StatusInternalServerError): + w.WriteHeader(http.StatusInternalServerError) + _, err = w.Write([]byte("failed to process request")) + require.NoError(t, err) + return + } + + if tc.giveResponseIsOptional { + w.WriteHeader(http.StatusOK) + return + } + + response := &Response{ + Id: request.Id, + } + bytes, err = json.Marshal(response) + require.NoError(t, err) + + _, err = w.Write(bytes) + require.NoError(t, err) + }, + ), + ) +} + +// newTestErrorDecoder returns an error decoder suitable for tests. +func newTestErrorDecoder(t *testing.T) func(int, io.Reader) error { + return func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + require.NoError(t, err) + + var ( + apiError = NewAPIError(statusCode, errors.New(string(raw))) + decoder = json.NewDecoder(bytes.NewReader(raw)) + ) + switch statusCode { + case 404: + value := new(NotFoundError) + value.APIError = apiError + require.NoError(t, decoder.Decode(value)) + + return value + } + return apiError + } +} diff --git a/core/idempotent_request_option.go b/core/idempotent_request_option.go new file mode 100644 index 0000000..d396091 --- /dev/null +++ b/core/idempotent_request_option.go @@ -0,0 +1,72 @@ +// This file was auto-generated by Fern from our API Definition. + +package core + +import ( + fmt "fmt" + http "net/http" +) + +// IdempotentRequestOption adapts the behavior of an individual request. +type IdempotentRequestOption interface { + applyIdempotentRequestOptions(*IdempotentRequestOptions) +} + +// IdempotentRequestOptions defines all of the possible idempotent request options. +// +// This type is primarily used by the generated code and is not meant +// to be used directly; use the option package instead. +type IdempotentRequestOptions struct { + *RequestOptions + + IdempotencyKey *string + IdempotencyExpiry *int +} + +// NewIdempotentRequestOptions returns a new *IdempotentRequestOptions value. +// +// This function is primarily used by the generated code and is not meant +// to be used directly; use IdempotentRequestOption instead. +func NewIdempotentRequestOptions(opts ...IdempotentRequestOption) *IdempotentRequestOptions { + options := &IdempotentRequestOptions{ + RequestOptions: NewRequestOptions(), + } + for _, opt := range opts { + if requestOption, ok := opt.(RequestOption); ok { + requestOption.applyRequestOptions(options.RequestOptions) + } + opt.applyIdempotentRequestOptions(options) + } + return options +} + +// IdempotencyKeyOption implements the RequestOption interface. +type IdempotencyKeyOption struct { + IdempotencyKey *string +} + +func (i *IdempotencyKeyOption) applyIdempotentRequestOptions(opts *IdempotentRequestOptions) { + opts.IdempotencyKey = i.IdempotencyKey +} + +// IdempotencyExpiryOption implements the RequestOption interface. +type IdempotencyExpiryOption struct { + IdempotencyExpiry *int +} + +func (i *IdempotencyExpiryOption) applyIdempotentRequestOptions(opts *IdempotentRequestOptions) { + opts.IdempotencyExpiry = i.IdempotencyExpiry +} + +// ToHeader maps the configured request options into a http.Header used +// for the request. +func (i *IdempotentRequestOptions) ToHeader() http.Header { + header := i.RequestOptions.ToHeader() + if i.IdempotencyKey != nil { + header.Set("Idempotency-Key", fmt.Sprintf("*%v", *i.IdempotencyKey)) + } + if i.IdempotencyExpiry != nil { + header.Set("X-Idempotency-Expiration", fmt.Sprintf("*%v", *i.IdempotencyExpiry)) + } + return header +} diff --git a/core/request_option.go b/core/request_option.go new file mode 100644 index 0000000..d97aac6 --- /dev/null +++ b/core/request_option.go @@ -0,0 +1,107 @@ +// This file was auto-generated by Fern from our API Definition. + +package core + +import ( + http "net/http" +) + +// RequestOption adapts the behavior of the client or an individual request. +type RequestOption interface { + applyRequestOptions(*RequestOptions) +} + +// RequestOptions defines all of the possible request options. +// +// This type is primarily used by the generated code and is not meant +// to be used directly; use the option package instead. +type RequestOptions struct { + BaseURL string + HTTPClient HTTPClient + HTTPHeader http.Header + AuthorizationToken string +} + +// NewRequestOptions returns a new *RequestOptions value. +// +// This function is primarily used by the generated code and is not meant +// to be used directly; use RequestOption instead. +func NewRequestOptions(opts ...RequestOption) *RequestOptions { + options := &RequestOptions{ + HTTPHeader: make(http.Header), + } + for _, opt := range opts { + opt.applyRequestOptions(options) + } + return options +} + +// ToHeader maps the configured request options into a http.Header used +// for the request(s). +func (r *RequestOptions) ToHeader() http.Header { + header := r.cloneHeader() + if r.AuthorizationToken != "" { + header.Set("Authorization", "Bearer "+r.AuthorizationToken) + } + return header +} + +func (r *RequestOptions) cloneHeader() http.Header { + headers := r.HTTPHeader.Clone() + headers.Set("X-Fern-Language", "Go") + headers.Set("X-Fern-SDK-Name", "github.com/trycourier/courier-go/v3") + headers.Set("X-Fern-SDK-Version", "v3.0.0") + return headers +} + +// BaseURLOption implements the RequestOption interface. +type BaseURLOption struct { + BaseURL string +} + +func (b *BaseURLOption) applyRequestOptions(opts *RequestOptions) { + opts.BaseURL = b.BaseURL +} + +func (b *BaseURLOption) applyIdempotentRequestOptions(opts *IdempotentRequestOptions) { + opts.BaseURL = b.BaseURL +} + +// HTTPClientOption implements the RequestOption interface. +type HTTPClientOption struct { + HTTPClient HTTPClient +} + +func (h *HTTPClientOption) applyRequestOptions(opts *RequestOptions) { + opts.HTTPClient = h.HTTPClient +} + +func (h *HTTPClientOption) applyIdempotentRequestOptions(opts *IdempotentRequestOptions) { + opts.HTTPClient = h.HTTPClient +} + +// HTTPHeaderOption implements the RequestOption interface. +type HTTPHeaderOption struct { + HTTPHeader http.Header +} + +func (h *HTTPHeaderOption) applyRequestOptions(opts *RequestOptions) { + opts.HTTPHeader = h.HTTPHeader +} + +func (h *HTTPHeaderOption) applyIdempotentRequestOptions(opts *IdempotentRequestOptions) { + opts.HTTPHeader = h.HTTPHeader +} + +// AuthorizationTokenOption implements the RequestOption interface. +type AuthorizationTokenOption struct { + AuthorizationToken string +} + +func (a *AuthorizationTokenOption) applyRequestOptions(opts *RequestOptions) { + opts.AuthorizationToken = a.AuthorizationToken +} + +func (a *AuthorizationTokenOption) applyIdempotentRequestOptions(opts *IdempotentRequestOptions) { + opts.AuthorizationToken = a.AuthorizationToken +} diff --git a/core/stringer.go b/core/stringer.go new file mode 100644 index 0000000..000cf44 --- /dev/null +++ b/core/stringer.go @@ -0,0 +1,13 @@ +package core + +import "encoding/json" + +// StringifyJSON returns a pretty JSON string representation of +// the given value. +func StringifyJSON(value interface{}) (string, error) { + bytes, err := json.MarshalIndent(value, "", " ") + if err != nil { + return "", err + } + return string(bytes), nil +} diff --git a/courier.go b/courier.go deleted file mode 100644 index e0f8ecb..0000000 --- a/courier.go +++ /dev/null @@ -1,42 +0,0 @@ -package courier - -import ( - "fmt" - "io/ioutil" - "net/http" -) - -type Client struct { - ApiKey string - BaseUrl string -} - -func CourierClient(apiKey string, baseUrl string) *Client { - if baseUrl == "" { - baseUrl = "https://api.courier.com" - } - return &Client{ - ApiKey: apiKey, - BaseUrl: baseUrl, - } -} - -func (s *Client) doRequest(req *http.Request) ([]byte, error) { - req.Header.Set("Authorization", "Bearer "+s.ApiKey) - req.Header.Set("Content-Type", "application/json") - req.Header.Set("User-Agent", "courier-go/0.0.1") - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - if http.StatusOK != resp.StatusCode { - return nil, fmt.Errorf("%s", body) - } - return body, nil -} diff --git a/environments.go b/environments.go new file mode 100644 index 0000000..44774dc --- /dev/null +++ b/environments.go @@ -0,0 +1,13 @@ +// This file was auto-generated by Fern from our API Definition. + +package api + +// Environments defines all of the API environments. +// These values can be used with the WithBaseURL +// RequestOption to override the client's default environment, +// if any. +var Environments = struct { + Production string +}{ + Production: "https://api.courier.com", +} diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..d637900 --- /dev/null +++ b/errors.go @@ -0,0 +1,146 @@ +// This file was auto-generated by Fern from our API Definition. + +package api + +import ( + json "encoding/json" + core "github.com/trycourier/courier-go/v3/core" +) + +type AlreadyExistsError struct { + *core.APIError + Body *AlreadyExists +} + +func (a *AlreadyExistsError) UnmarshalJSON(data []byte) error { + var body *AlreadyExists + if err := json.Unmarshal(data, &body); err != nil { + return err + } + a.StatusCode = 409 + a.Body = body + return nil +} + +func (a *AlreadyExistsError) MarshalJSON() ([]byte, error) { + return json.Marshal(a.Body) +} + +func (a *AlreadyExistsError) Unwrap() error { + return a.APIError +} + +type BadRequestError struct { + *core.APIError + Body *BadRequest +} + +func (b *BadRequestError) UnmarshalJSON(data []byte) error { + var body *BadRequest + if err := json.Unmarshal(data, &body); err != nil { + return err + } + b.StatusCode = 400 + b.Body = body + return nil +} + +func (b *BadRequestError) MarshalJSON() ([]byte, error) { + return json.Marshal(b.Body) +} + +func (b *BadRequestError) Unwrap() error { + return b.APIError +} + +type ConflictError struct { + *core.APIError + Body *Conflict +} + +func (c *ConflictError) UnmarshalJSON(data []byte) error { + var body *Conflict + if err := json.Unmarshal(data, &body); err != nil { + return err + } + c.StatusCode = 409 + c.Body = body + return nil +} + +func (c *ConflictError) MarshalJSON() ([]byte, error) { + return json.Marshal(c.Body) +} + +func (c *ConflictError) Unwrap() error { + return c.APIError +} + +type MessageNotFoundError struct { + *core.APIError + Body *MessageNotFound +} + +func (m *MessageNotFoundError) UnmarshalJSON(data []byte) error { + var body *MessageNotFound + if err := json.Unmarshal(data, &body); err != nil { + return err + } + m.StatusCode = 404 + m.Body = body + return nil +} + +func (m *MessageNotFoundError) MarshalJSON() ([]byte, error) { + return json.Marshal(m.Body) +} + +func (m *MessageNotFoundError) Unwrap() error { + return m.APIError +} + +type NotFoundError struct { + *core.APIError + Body *NotFound +} + +func (n *NotFoundError) UnmarshalJSON(data []byte) error { + var body *NotFound + if err := json.Unmarshal(data, &body); err != nil { + return err + } + n.StatusCode = 404 + n.Body = body + return nil +} + +func (n *NotFoundError) MarshalJSON() ([]byte, error) { + return json.Marshal(n.Body) +} + +func (n *NotFoundError) Unwrap() error { + return n.APIError +} + +type PaymentRequiredError struct { + *core.APIError + Body *PaymentRequired +} + +func (p *PaymentRequiredError) UnmarshalJSON(data []byte) error { + var body *PaymentRequired + if err := json.Unmarshal(data, &body); err != nil { + return err + } + p.StatusCode = 402 + p.Body = body + return nil +} + +func (p *PaymentRequiredError) MarshalJSON() ([]byte, error) { + return json.Marshal(p.Body) +} + +func (p *PaymentRequiredError) Unwrap() error { + return p.APIError +} diff --git a/go.mod b/go.mod index c5e8dde..558e4ef 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,8 @@ -module github.com/trycourier/courier-go +module github.com/trycourier/courier-go/v3 go 1.13 -require github.com/stretchr/testify v1.5.1 +require ( + github.com/stretchr/testify v1.7.0 + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum index 331fa69..fc3dd9e 100644 --- a/go.sum +++ b/go.sum @@ -3,9 +3,10 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/lists.go b/lists.go new file mode 100644 index 0000000..b98539c --- /dev/null +++ b/lists.go @@ -0,0 +1,214 @@ +// This file was auto-generated by Fern from our API Definition. + +package api + +import ( + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" +) + +type GetListRequest struct { + // A unique identifier that allows for fetching the next page of lists. + Cursor *string `json:"-"` + // "A pattern used to filter the list items returned. Pattern types supported: exact match on `list_id` or a pattern of one or more pattern parts. you may replace a part with either: `*` to match all parts in that position, or `**` to signify a wildcard `endsWith` pattern match." + Pattern *string `json:"-"` +} + +type GetSubscriptionForListRequest struct { + // A unique identifier that allows for fetching the next set of list subscriptions + Cursor *string `json:"-"` +} + +type GetAllListsRequest struct { + // A unique identifier that allows for fetching the next page of lists. + Cursor *string `json:"-"` + // "A pattern used to filter the list items returned. Pattern types supported: exact match on `list_id` or a pattern of one or more pattern parts. you may replace a part with either: `*` to match all parts in that position, or `**` to signify a wildcard `endsWith` pattern match." + Pattern *string `json:"-"` +} + +type SubscribeUserToListRequest struct { + Preferences *RecipientPreferences `json:"preferences,omitempty"` +} + +type RecipientPreferences struct { + Categories *NotificationPreferences `json:"categories,omitempty"` + Notifications *NotificationPreferences `json:"notifications,omitempty"` + + _rawJSON json.RawMessage +} + +func (r *RecipientPreferences) UnmarshalJSON(data []byte) error { + type unmarshaler RecipientPreferences + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *r = RecipientPreferences(value) + r._rawJSON = json.RawMessage(data) + return nil +} + +func (r *RecipientPreferences) String() string { + if len(r._rawJSON) > 0 { + if value, err := core.StringifyJSON(r._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(r); err == nil { + return value + } + return fmt.Sprintf("%#v", r) +} + +type List struct { + Id string `json:"id"` + Name string `json:"name"` + Created *int `json:"created,omitempty"` + Updated *int `json:"updated,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *List) UnmarshalJSON(data []byte) error { + type unmarshaler List + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = List(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *List) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type ListGetAllResponse struct { + Paging *Paging `json:"paging,omitempty"` + Items []*List `json:"items,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *ListGetAllResponse) UnmarshalJSON(data []byte) error { + type unmarshaler ListGetAllResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListGetAllResponse(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListGetAllResponse) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type ListGetSubscriptionsResponse struct { + Paging *Paging `json:"paging,omitempty"` + Items []*ListSubscriptionRecipient `json:"items,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *ListGetSubscriptionsResponse) UnmarshalJSON(data []byte) error { + type unmarshaler ListGetSubscriptionsResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListGetSubscriptionsResponse(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListGetSubscriptionsResponse) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type ListPutParams struct { + Name string `json:"name"` + Preferences *RecipientPreferences `json:"preferences,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *ListPutParams) UnmarshalJSON(data []byte) error { + type unmarshaler ListPutParams + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListPutParams(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListPutParams) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type PutSubscriptionsRecipient struct { + RecipientId string `json:"recipientId"` + Preferences *RecipientPreferences `json:"preferences,omitempty"` + + _rawJSON json.RawMessage +} + +func (p *PutSubscriptionsRecipient) UnmarshalJSON(data []byte) error { + type unmarshaler PutSubscriptionsRecipient + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *p = PutSubscriptionsRecipient(value) + p._rawJSON = json.RawMessage(data) + return nil +} + +func (p *PutSubscriptionsRecipient) String() string { + if len(p._rawJSON) > 0 { + if value, err := core.StringifyJSON(p._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(p); err == nil { + return value + } + return fmt.Sprintf("%#v", p) +} diff --git a/lists/client.go b/lists/client.go new file mode 100644 index 0000000..6aa03ff --- /dev/null +++ b/lists/client.go @@ -0,0 +1,543 @@ +// This file was auto-generated by Fern from our API Definition. + +package lists + +import ( + bytes "bytes" + context "context" + json "encoding/json" + errors "errors" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + io "io" + http "net/http" + url "net/url" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +// Returns all of the lists, with the ability to filter based on a pattern. +func (c *Client) List( + ctx context.Context, + request *v3.GetAllListsRequest, + opts ...option.RequestOption, +) (*v3.ListGetAllResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := baseURL + "/" + "lists" + + queryParams := make(url.Values) + if request.Cursor != nil { + queryParams.Add("cursor", fmt.Sprintf("%v", *request.Cursor)) + } + if request.Pattern != nil { + queryParams.Add("pattern", fmt.Sprintf("%v", *request.Pattern)) + } + if len(queryParams) > 0 { + endpointURL += "?" + queryParams.Encode() + } + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.ListGetAllResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Returns a list based on the list ID provided. +func (c *Client) Get( + ctx context.Context, + // A unique identifier representing the list you wish to retrieve. + listId string, + request *v3.GetListRequest, + opts ...option.RequestOption, +) (*v3.List, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"lists/%v", listId) + + queryParams := make(url.Values) + if request.Cursor != nil { + queryParams.Add("cursor", fmt.Sprintf("%v", *request.Cursor)) + } + if request.Pattern != nil { + queryParams.Add("pattern", fmt.Sprintf("%v", *request.Pattern)) + } + if len(queryParams) > 0 { + endpointURL += "?" + queryParams.Encode() + } + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 404: + value := new(v3.NotFoundError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.List + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Create or replace an existing list with the supplied values. +func (c *Client) Update( + ctx context.Context, + // A unique identifier representing the list you wish to retrieve. + listId string, + request *v3.ListPutParams, + opts ...option.RequestOption, +) (*v3.List, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"lists/%v", listId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.List + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Delete a list by list ID. +func (c *Client) Delete( + ctx context.Context, + // A unique identifier representing the list you wish to retrieve. + listId string, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"lists/%v", listId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodDelete, + Headers: headers, + Client: options.HTTPClient, + }, + ); err != nil { + return err + } + return nil +} + +// Restore a previously deleted list. +func (c *Client) Restore( + ctx context.Context, + // A unique identifier representing the list you wish to retrieve. + listId string, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"lists/%v/restore", listId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + }, + ); err != nil { + return err + } + return nil +} + +// Get the list's subscriptions. +func (c *Client) GetSubscribers( + ctx context.Context, + // A unique identifier representing the list you wish to retrieve. + listId string, + request *v3.GetSubscriptionForListRequest, + opts ...option.RequestOption, +) (*v3.ListGetSubscriptionsResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"lists/%v/subscriptions", listId) + + queryParams := make(url.Values) + if request.Cursor != nil { + queryParams.Add("cursor", fmt.Sprintf("%v", *request.Cursor)) + } + if len(queryParams) > 0 { + endpointURL += "?" + queryParams.Encode() + } + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 404: + value := new(v3.NotFoundError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.ListGetSubscriptionsResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Subscribes the users to the list, overwriting existing subscriptions. If the list does not exist, it will be automatically created. +func (c *Client) UpdateSubscribers( + ctx context.Context, + // A unique identifier representing the list you wish to retrieve. + listId string, + request []*v3.PutSubscriptionsRecipient, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"lists/%v/subscriptions", listId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + Request: request, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return err + } + return nil +} + +// Subscribes additional users to the list, without modifying existing subscriptions. If the list does not exist, it will be automatically created. +func (c *Client) AddSubscribers( + ctx context.Context, + // A unique identifier representing the list you wish to retrieve. + listId string, + request []*v3.PutSubscriptionsRecipient, + opts ...option.IdempotentRequestOption, +) error { + options := core.NewIdempotentRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"lists/%v/subscriptions", listId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPost, + Headers: headers, + Client: options.HTTPClient, + Request: request, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return err + } + return nil +} + +// Subscribe a user to an existing list (note: if the List does not exist, it will be automatically created). +func (c *Client) Subscribe( + ctx context.Context, + // A unique identifier representing the list you wish to retrieve. + listId string, + // A unique identifier representing the recipient associated with the list + userId string, + request *v3.SubscribeUserToListRequest, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"lists/%v/subscriptions/%v", listId, userId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + Request: request, + }, + ); err != nil { + return err + } + return nil +} + +// Delete a subscription to a list by list ID and user ID. +func (c *Client) Unsubscribe( + ctx context.Context, + // A unique identifier representing the list you wish to retrieve. + listId string, + // A unique identifier representing the recipient associated with the list + userId string, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"lists/%v/subscriptions/%v", listId, userId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 404: + value := new(v3.NotFoundError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodDelete, + Headers: headers, + Client: options.HTTPClient, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return err + } + return nil +} diff --git a/messages.go b/messages.go index 7a51551..03ae4eb 100644 --- a/messages.go +++ b/messages.go @@ -1,201 +1,182 @@ -package courier +// This file was auto-generated by Fern from our API Definition. + +package api import ( - "context" - "encoding/json" - "errors" - "fmt" - "net/http" - "net/url" + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" ) -type ProvidersChannelResponse struct { - Key string - Name string - Template string -} -type ProvidersResponse struct { - Channel *ProvidersChannelResponse - Error string - Status string - Delivered int64 - Sent int64 - Clicked int64 - Opened int64 - Provider string - Reference interface{} // provider specific response -} - -type MessageResponse struct { - Id string - Event string - Notification string - Status string - Error string - Reason string - Recipient string - Enqueued int64 - Delivered int64 - Sent int64 - Clicked int64 - Opened int64 - Providers []*ProvidersResponse -} - -type CancelMessageResponse struct { - CanceledAt int64 - Event string - Id string - Recipient string - Status string - // optional - Clicked int64 - Delivered int64 - Enqueued int64 - Error string - JobId string - ListId string - ListMessageId string - Notification string - Opened int64 - RunId string - Sent int64 +type GetMessageHistoryRequest struct { + // A supported Message History type that will filter the events returned. + Type *string `json:"-"` } -type PagingResponse struct { - Cursor string - More bool +type ListMessagesRequest struct { + // A boolean value that indicates whether archived messages should be included in the response. + Archived *bool `json:"-"` + // A unique identifier that allows for fetching the next set of message statuses. + Cursor *string `json:"-"` + // A unique identifier representing the event that was used to send the event. + Event *string `json:"-"` + // A unique identifier representing the list the message was sent to. + List *string `json:"-"` + // A unique identifier representing the message_id returned from either /send or /send/list. + MessageId *string `json:"-"` + // A unique identifier representing the notification that was used to send the event. + Notification *string `json:"-"` + // A unique identifier representing the recipient associated with the requested profile. + Recipient *string `json:"-"` + // An indicator of the current status of the message. Multiple status values can be passed in. + Status *string `json:"-"` + // A comma delimited list of 'tags'. Messages will be returned if they match any of the tags passed in. + Tags *string `json:"-"` + // The enqueued datetime of a message to filter out messages received before. + EnqueuedAfter *string `json:"-"` + // The unique identifier used to trace the requests + TraceId *string `json:"-"` } -type MessagesResponse struct { - Paging *PagingResponse - Results []*MessageResponse -} +type ListMessagesResponse struct { + // Paging information for the result set. + Paging *Paging `json:"paging,omitempty"` + // An array of messages with their details. + Results []*MessageDetails `json:"results,omitempty"` -type MessageHistoryResponse struct { - Results []interface{} + _rawJSON json.RawMessage } -func (c *Client) GetMessage(ctx context.Context, messageID string) (*MessageResponse, error) { - if messageID == "" { - return nil, errors.New("messageID is required") - } - - url := fmt.Sprintf(c.BaseUrl+"/messages/%s", messageID) - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err +func (l *ListMessagesResponse) UnmarshalJSON(data []byte) error { + type unmarshaler ListMessagesResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err } + *l = ListMessagesResponse(value) + l._rawJSON = json.RawMessage(data) + return nil +} - bytes, err := c.doRequest(req) - if err != nil { - return nil, err +func (l *ListMessagesResponse) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } } - - var data MessageResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err + if value, err := core.StringifyJSON(l); err == nil { + return value } - - return &data, nil + return fmt.Sprintf("%#v", l) } -func (c *Client) CancelMessage(ctx context.Context, messageID string) (*CancelMessageResponse, error) { - if messageID == "" { - return nil, errors.New("messageID is required") - } - - url := fmt.Sprintf(c.BaseUrl+"/messages/%s/cancel", messageID) +type MessageDetails struct { + // A unique identifier associated with the message you wish to retrieve (results from a send). + Id string `json:"id"` + // The current status of the message. + Status MessageStatus `json:"status,omitempty"` + // A UTC timestamp at which Courier received the message request. Stored as a millisecond representation of the Unix epoch. + Enqueued int `json:"enqueued"` + // A UTC timestamp at which Courier passed the message to the Integration provider. Stored as a millisecond representation of the Unix epoch. + Sent int `json:"sent"` + // A UTC timestamp at which the Integration provider delivered the message. Stored as a millisecond representation of the Unix epoch. + Delivered int `json:"delivered"` + // A UTC timestamp at which the recipient opened a message for the first time. Stored as a millisecond representation of the Unix epoch. + Opened int `json:"opened"` + // A UTC timestamp at which the recipient clicked on a tracked link for the first time. Stored as a millisecond representation of the Unix epoch. + Clicked int `json:"clicked"` + // A unique identifier associated with the recipient of the delivered message. + Recipient string `json:"recipient"` + // A unique identifier associated with the event of the delivered message. + Event string `json:"event"` + // A unique identifier associated with the notification of the delivered message. + Notification string `json:"notification"` + // A message describing the error that occurred. + Error *string `json:"error,omitempty"` + // The reason for the current status of the message. + Reason *Reason `json:"reason,omitempty"` + + _rawJSON json.RawMessage +} - req, err := http.NewRequestWithContext(ctx, "POST", url, nil) - if err != nil { - return nil, err +func (m *MessageDetails) UnmarshalJSON(data []byte) error { + type unmarshaler MessageDetails + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err } + *m = MessageDetails(value) + m._rawJSON = json.RawMessage(data) + return nil +} - bytes, err := c.doRequest(req) - if err != nil { - return nil, err +func (m *MessageDetails) String() string { + if len(m._rawJSON) > 0 { + if value, err := core.StringifyJSON(m._rawJSON); err == nil { + return value + } } - - var data CancelMessageResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err + if value, err := core.StringifyJSON(m); err == nil { + return value } - - return &data, nil + return fmt.Sprintf("%#v", m) } -func (c *Client) GetMessages(ctx context.Context, cursor string, event string, list string, messageId string, notification string, recipient string) (*MessagesResponse, error) { - params := url.Values{} - if cursor != "" { - params.Add("cursor", cursor) - } - if event != "" { - params.Add("event", event) - } - if list != "" { - params.Add("list", list) - } - if messageId != "" { - params.Add("messageId", messageId) - } - if notification != "" { - params.Add("notification", notification) - } - if recipient != "" { - params.Add("recipient", recipient) - } +type MessageHistoryResponse struct { + Results []*MessageDetails `json:"results,omitempty"` - url := fmt.Sprintf(c.BaseUrl+"/messages?%s", params.Encode()) + _rawJSON json.RawMessage +} - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err +func (m *MessageHistoryResponse) UnmarshalJSON(data []byte) error { + type unmarshaler MessageHistoryResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err } + *m = MessageHistoryResponse(value) + m._rawJSON = json.RawMessage(data) + return nil +} - bytes, err := c.doRequest(req) - if err != nil { - return nil, err +func (m *MessageHistoryResponse) String() string { + if len(m._rawJSON) > 0 { + if value, err := core.StringifyJSON(m._rawJSON); err == nil { + return value + } } - - var data MessagesResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err + if value, err := core.StringifyJSON(m); err == nil { + return value } - - return &data, nil + return fmt.Sprintf("%#v", m) } -func (c *Client) GetMessageHistory(ctx context.Context, messageID string, _type string) (*MessageHistoryResponse, error) { - if messageID == "" { - return nil, errors.New("messageID is required") - } +type RenderOutputResponse struct { + // An array of render output of a previously sent message. + Results []*RenderOutput `json:"results,omitempty"` - requestURL := fmt.Sprintf(c.BaseUrl+"/messages/%s/history", messageID) - - if _type != "" { - requestURL = requestURL + "?type=" + _type - } + _rawJSON json.RawMessage +} - req, err := http.NewRequestWithContext(ctx, "GET", requestURL, nil) - if err != nil { - return nil, err +func (r *RenderOutputResponse) UnmarshalJSON(data []byte) error { + type unmarshaler RenderOutputResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err } + *r = RenderOutputResponse(value) + r._rawJSON = json.RawMessage(data) + return nil +} - bytes, err := c.doRequest(req) - if err != nil { - return nil, err +func (r *RenderOutputResponse) String() string { + if len(r._rawJSON) > 0 { + if value, err := core.StringifyJSON(r._rawJSON); err == nil { + return value + } } - - var data MessageHistoryResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err + if value, err := core.StringifyJSON(r); err == nil { + return value } - - return &data, nil + return fmt.Sprintf("%#v", r) } diff --git a/messages/client.go b/messages/client.go new file mode 100644 index 0000000..d922343 --- /dev/null +++ b/messages/client.go @@ -0,0 +1,371 @@ +// This file was auto-generated by Fern from our API Definition. + +package messages + +import ( + bytes "bytes" + context "context" + json "encoding/json" + errors "errors" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + io "io" + http "net/http" + url "net/url" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +// Fetch the statuses of messages you've previously sent. +func (c *Client) List( + ctx context.Context, + request *v3.ListMessagesRequest, + opts ...option.RequestOption, +) (*v3.ListMessagesResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := baseURL + "/" + "messages" + + queryParams := make(url.Values) + if request.Archived != nil { + queryParams.Add("archived", fmt.Sprintf("%v", *request.Archived)) + } + if request.Cursor != nil { + queryParams.Add("cursor", fmt.Sprintf("%v", *request.Cursor)) + } + if request.Event != nil { + queryParams.Add("event", fmt.Sprintf("%v", *request.Event)) + } + if request.List != nil { + queryParams.Add("list", fmt.Sprintf("%v", *request.List)) + } + if request.MessageId != nil { + queryParams.Add("messageId", fmt.Sprintf("%v", *request.MessageId)) + } + if request.Notification != nil { + queryParams.Add("notification", fmt.Sprintf("%v", *request.Notification)) + } + if request.Recipient != nil { + queryParams.Add("recipient", fmt.Sprintf("%v", *request.Recipient)) + } + if request.Status != nil { + queryParams.Add("status", fmt.Sprintf("%v", *request.Status)) + } + if request.Tags != nil { + queryParams.Add("tags", fmt.Sprintf("%v", *request.Tags)) + } + if request.EnqueuedAfter != nil { + queryParams.Add("enqueued_after", fmt.Sprintf("%v", *request.EnqueuedAfter)) + } + if request.TraceId != nil { + queryParams.Add("traceId", fmt.Sprintf("%v", *request.TraceId)) + } + if len(queryParams) > 0 { + endpointURL += "?" + queryParams.Encode() + } + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.ListMessagesResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Fetch the status of a message you've previously sent. +func (c *Client) Get( + ctx context.Context, + // A unique identifier associated with the message you wish to retrieve (results from a send). + messageId string, + opts ...option.RequestOption, +) (*v3.MessageDetails, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"messages/%v", messageId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + case 404: + value := new(v3.MessageNotFoundError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.MessageDetails + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Cancel a message that is currently in the process of being delivered. A well-formatted API call to the cancel message API will return either `200` status code for a successful cancellation or `409` status code for an unsuccessful cancellation. Both cases will include the actual message record in the response body (see details below). +func (c *Client) Cancel( + ctx context.Context, + // A unique identifier representing the message ID + messageId string, + opts ...option.IdempotentRequestOption, +) (*v3.MessageDetails, error) { + options := core.NewIdempotentRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"messages/%v/cancel", messageId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.MessageDetails + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPost, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Fetch the array of events of a message you've previously sent. +func (c *Client) GetHistory( + ctx context.Context, + // A unique identifier representing the message ID + messageId string, + request *v3.GetMessageHistoryRequest, + opts ...option.RequestOption, +) (*v3.MessageHistoryResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"messages/%v/history", messageId) + + queryParams := make(url.Values) + if request.Type != nil { + queryParams.Add("type", fmt.Sprintf("%v", *request.Type)) + } + if len(queryParams) > 0 { + endpointURL += "?" + queryParams.Encode() + } + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + case 404: + value := new(v3.MessageNotFoundError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.MessageHistoryResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +func (c *Client) GetContent( + ctx context.Context, + // A unique identifier associated with the message you wish to retrieve (results from a send). + messageId string, + opts ...option.RequestOption, +) (*v3.RenderOutputResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"messages/%v/output", messageId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + case 404: + value := new(v3.MessageNotFoundError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.RenderOutputResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +func (c *Client) Archive( + ctx context.Context, + // A unique identifier representing the request ID + requestId string, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"requests/%v/archive", requestId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + }, + ); err != nil { + return err + } + return nil +} diff --git a/messages_test.go b/messages_test.go deleted file mode 100644 index c1e8d18..0000000 --- a/messages_test.go +++ /dev/null @@ -1,219 +0,0 @@ -package courier_test - -import ( - "context" - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/trycourier/courier-go" -) - -func TestClient_GetMessage(t *testing.T) { - - requestMessageID := "1-23456789" - status := "CLICKED" - sent := int64(1589563865697) - - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/messages/"+requestMessageID, req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "id": "%s", - "clicked": 1589563890843, - "delivered": 1589563972000, - "enqueued": 1589563863773, - "event": "GEFGNB2GNQ4MZVHW4WV4R8Q8ZVN5", - "notification": "GEFGNB2GNQ4MZVHW4WV4R8Q8ZVN5", - "providers": [ - { - "channel": { - "key": "sendgrid", - "template": "5e95b992-3505-4f66-8808-f91d5d0fe8c9" - }, - "clicked": 1589563890843, - "delivered": 1589563972000, - "provider": "sendgrid", - "reference": { - "message_id": "Xx14o44jToS8StSTPLGsTw.filterdrecv-p3iad2-8ddf98858-7qsdm-19-5EBED1D9-D3.0", - "x-message-id": "Xx14o44jToS8StSTPLGsTw" - }, - "sent": 1589563865697, - "status": "DELIVERED" - } - ], - "recipient": "tony@trycourier.com", - "sent": %d, - "status": "%s" - }` - _, _ = rw.Write([]byte(fmt.Sprintf(rsp, requestMessageID, sent, status))) - - })) - defer server.Close() - - t.Run("makes request for message ID", func(t *testing.T) { - client := courier.CourierClient("key", server.URL) - rsp, err := client.GetMessage(context.Background(), requestMessageID) - assert.Nil(t, err) - assert.Equal(t, requestMessageID, rsp.Id) - assert.Equal(t, sent, rsp.Sent) - assert.Equal(t, status, rsp.Status) - }) -} - -func TestClient_CancelMessage(t *testing.T) { - - requestMessageID := "1-23456789" - status := "CLICKED" - sent := int64(1589563865697) - - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/messages/"+requestMessageID+"/cancel", req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "id": "%s", - "clicked": 1589563890843, - "delivered": 1589563972000, - "enqueued": 1589563863773, - "event": "GEFGNB2GNQ4MZVHW4WV4R8Q8ZVN5", - "notification": "GEFGNB2GNQ4MZVHW4WV4R8Q8ZVN5", - "providers": [ - { - "channel": { - "key": "sendgrid", - "template": "5e95b992-3505-4f66-8808-f91d5d0fe8c9" - }, - "clicked": 1589563890843, - "delivered": 1589563972000, - "provider": "sendgrid", - "reference": { - "message_id": "Xx14o44jToS8StSTPLGsTw.filterdrecv-p3iad2-8ddf98858-7qsdm-19-5EBED1D9-D3.0", - "x-message-id": "Xx14o44jToS8StSTPLGsTw" - }, - "sent": 1589563865697, - "status": "DELIVERED" - } - ], - "recipient": "tony@trycourier.com", - "sent": %d, - "status": "%s" - }` - _, _ = rw.Write([]byte(fmt.Sprintf(rsp, requestMessageID, sent, status))) - - })) - defer server.Close() - - t.Run("makes request to cancel message", func(t *testing.T) { - client := courier.CourierClient("key", server.URL) - rsp, err := client.GetMessage(context.Background(), requestMessageID) - assert.Nil(t, err) - assert.Equal(t, requestMessageID, rsp.Id) - assert.Equal(t, sent, rsp.Sent) - assert.Equal(t, status, rsp.Status) - }) -} - -func TestClient_GetMessages(t *testing.T) { - - event := "courier-quickstart" - recipient := "Github_6154318" - - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/messages?event="+event+"&recipient="+recipient, req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "Paging":{ - "Cursor":"", - "More":false - }, - "Results":[ - { - "Id":"1-60122b54-7e5d45d35b820ace1c0ffc49", - "Event":"%s", - "Notification":"", - "Status":"UNMAPPED", - "Error":"", - "Reason":"", - "Recipient":"%s", - "Enqueued":1611803477021, - "Delivered":0, - "Sent":0, - "Clicked":0, - "Opened":0, - "Providers":null - } - ] - }` - _, _ = rw.Write([]byte(fmt.Sprintf(rsp, event, recipient))) - - })) - defer server.Close() - - t.Run("makes request for messages", func(t *testing.T) { - client := courier.CourierClient("key", server.URL) - rsp, err := client.GetMessages(context.Background(), "", event, "", "", "", recipient) - - assert.Nil(t, err) - assert.Equal(t, event, rsp.Results[0].Event) - assert.Equal(t, recipient, rsp.Results[0].Recipient) - }) -} - -func TestClient_GetMessageHistory(t *testing.T) { - messageId := "1-60136482-4f3e07390677c06e2e248de6" - _type := "ENQUEUED" - - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/messages/"+messageId+"/history?type="+_type, req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "Results": [ - { - "data": { - "favoriteAdjective": "awesomeness" - }, - "event": "courier-quickstart", - "profile": { - "email": "foo@example.com" - }, - "recipient": "Github_6154318", - "ts": 1611883650743, - "type": "%s" - } - ] - }` - _, _ = rw.Write([]byte(fmt.Sprintf(rsp, _type))) - - })) - defer server.Close() - - t.Run("makes request for message history", func(t *testing.T) { - client := courier.CourierClient("key", server.URL) - rsp, err := client.GetMessageHistory(context.Background(), "1-60136482-4f3e07390677c06e2e248de6", _type) - - assert.Nil(t, err) - assert.Equal(t, 1, len(rsp.Results)) - }) -} diff --git a/notifications.go b/notifications.go new file mode 100644 index 0000000..d02b0e7 --- /dev/null +++ b/notifications.go @@ -0,0 +1,262 @@ +// This file was auto-generated by Fern from our API Definition. + +package api + +import ( + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" +) + +type NotificationListParams struct { + Cursor *string `json:"-"` +} + +type SubmissionChecksReplaceParams struct { + Checks []*BaseCheck `json:"checks,omitempty"` +} + +type BaseCheck struct { + Id string `json:"id"` + Status CheckStatus `json:"status,omitempty"` + type_ string + + _rawJSON json.RawMessage +} + +func (b *BaseCheck) Type() string { + return b.type_ +} + +func (b *BaseCheck) UnmarshalJSON(data []byte) error { + type unmarshaler BaseCheck + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BaseCheck(value) + b.type_ = "custom" + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BaseCheck) MarshalJSON() ([]byte, error) { + type embed BaseCheck + var marshaler = struct { + embed + Type string `json:"type"` + }{ + embed: embed(*b), + Type: "custom", + } + return json.Marshal(marshaler) +} + +func (b *BaseCheck) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type NotificationBlock struct { + Alias *string `json:"alias,omitempty"` + Context *string `json:"context,omitempty"` + Id string `json:"id"` + Type BlockType `json:"type,omitempty"` + Content *NotificationContent `json:"content,omitempty"` + Locales map[string]*NotificationContent `json:"locales,omitempty"` + Checksum *string `json:"checksum,omitempty"` + + _rawJSON json.RawMessage +} + +func (n *NotificationBlock) UnmarshalJSON(data []byte) error { + type unmarshaler NotificationBlock + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *n = NotificationBlock(value) + n._rawJSON = json.RawMessage(data) + return nil +} + +func (n *NotificationBlock) String() string { + if len(n._rawJSON) > 0 { + if value, err := core.StringifyJSON(n._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(n); err == nil { + return value + } + return fmt.Sprintf("%#v", n) +} + +type NotificationChannel struct { + Id string `json:"id"` + Type *string `json:"type,omitempty"` + Content *NotificationChannelContent `json:"content,omitempty"` + Locales map[string]*NotificationChannelContent `json:"locales,omitempty"` + Checksum *string `json:"checksum,omitempty"` + + _rawJSON json.RawMessage +} + +func (n *NotificationChannel) UnmarshalJSON(data []byte) error { + type unmarshaler NotificationChannel + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *n = NotificationChannel(value) + n._rawJSON = json.RawMessage(data) + return nil +} + +func (n *NotificationChannel) String() string { + if len(n._rawJSON) > 0 { + if value, err := core.StringifyJSON(n._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(n); err == nil { + return value + } + return fmt.Sprintf("%#v", n) +} + +type NotificationGetContentResponse struct { + Blocks []*NotificationBlock `json:"blocks,omitempty"` + Channels []*NotificationChannel `json:"channels,omitempty"` + Checksum *string `json:"checksum,omitempty"` + + _rawJSON json.RawMessage +} + +func (n *NotificationGetContentResponse) UnmarshalJSON(data []byte) error { + type unmarshaler NotificationGetContentResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *n = NotificationGetContentResponse(value) + n._rawJSON = json.RawMessage(data) + return nil +} + +func (n *NotificationGetContentResponse) String() string { + if len(n._rawJSON) > 0 { + if value, err := core.StringifyJSON(n._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(n); err == nil { + return value + } + return fmt.Sprintf("%#v", n) +} + +type NotificationListResponse struct { + Paging *Paging `json:"paging,omitempty"` + Results []*Notification `json:"results,omitempty"` + + _rawJSON json.RawMessage +} + +func (n *NotificationListResponse) UnmarshalJSON(data []byte) error { + type unmarshaler NotificationListResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *n = NotificationListResponse(value) + n._rawJSON = json.RawMessage(data) + return nil +} + +func (n *NotificationListResponse) String() string { + if len(n._rawJSON) > 0 { + if value, err := core.StringifyJSON(n._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(n); err == nil { + return value + } + return fmt.Sprintf("%#v", n) +} + +type SubmissionChecksGetResponse struct { + Checks []*Check `json:"checks,omitempty"` + + _rawJSON json.RawMessage +} + +func (s *SubmissionChecksGetResponse) UnmarshalJSON(data []byte) error { + type unmarshaler SubmissionChecksGetResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *s = SubmissionChecksGetResponse(value) + s._rawJSON = json.RawMessage(data) + return nil +} + +func (s *SubmissionChecksGetResponse) String() string { + if len(s._rawJSON) > 0 { + if value, err := core.StringifyJSON(s._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(s); err == nil { + return value + } + return fmt.Sprintf("%#v", s) +} + +type SubmissionChecksReplaceResponse struct { + Checks []*Check `json:"checks,omitempty"` + + _rawJSON json.RawMessage +} + +func (s *SubmissionChecksReplaceResponse) UnmarshalJSON(data []byte) error { + type unmarshaler SubmissionChecksReplaceResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *s = SubmissionChecksReplaceResponse(value) + s._rawJSON = json.RawMessage(data) + return nil +} + +func (s *SubmissionChecksReplaceResponse) String() string { + if len(s._rawJSON) > 0 { + if value, err := core.StringifyJSON(s._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(s); err == nil { + return value + } + return fmt.Sprintf("%#v", s) +} + +type NotificationDraftUpdateVariationsParams struct { + Blocks []*NotificationBlock `json:"blocks,omitempty"` + Channels []*NotificationChannel `json:"channels,omitempty"` +} + +type NotificationUpdateVariationsParams struct { + Blocks []*NotificationBlock `json:"blocks,omitempty"` + Channels []*NotificationChannel `json:"channels,omitempty"` +} diff --git a/notifications/client.go b/notifications/client.go new file mode 100644 index 0000000..2c59419 --- /dev/null +++ b/notifications/client.go @@ -0,0 +1,311 @@ +// This file was auto-generated by Fern from our API Definition. + +package notifications + +import ( + context "context" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + http "net/http" + url "net/url" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +func (c *Client) List( + ctx context.Context, + request *v3.NotificationListParams, + opts ...option.RequestOption, +) (*v3.NotificationListResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := baseURL + "/" + "notifications" + + queryParams := make(url.Values) + if request.Cursor != nil { + queryParams.Add("cursor", fmt.Sprintf("%v", *request.Cursor)) + } + if len(queryParams) > 0 { + endpointURL += "?" + queryParams.Encode() + } + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.NotificationListResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +func (c *Client) GetContent( + ctx context.Context, + id string, + opts ...option.RequestOption, +) (*v3.NotificationGetContentResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"notifications/%v/content", id) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.NotificationGetContentResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +func (c *Client) GetDraftContent( + ctx context.Context, + id string, + opts ...option.RequestOption, +) (*v3.NotificationGetContentResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"notifications/%v/draft/content", id) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.NotificationGetContentResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +func (c *Client) UpdateVariations( + ctx context.Context, + id string, + request *v3.NotificationUpdateVariationsParams, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"notifications/%v/variations", id) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPost, + Headers: headers, + Client: options.HTTPClient, + Request: request, + }, + ); err != nil { + return err + } + return nil +} + +func (c *Client) UpdateDraftVariations( + ctx context.Context, + id string, + request *v3.NotificationDraftUpdateVariationsParams, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"notifications/%v/draft/variations", id) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPost, + Headers: headers, + Client: options.HTTPClient, + Request: request, + }, + ); err != nil { + return err + } + return nil +} + +func (c *Client) GetSubmissionChecks( + ctx context.Context, + id string, + submissionId string, + opts ...option.RequestOption, +) (*v3.SubmissionChecksGetResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"notifications/%v/%v/checks", id, submissionId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.SubmissionChecksGetResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +func (c *Client) ReplaceSubmissionChecks( + ctx context.Context, + id string, + submissionId string, + request *v3.SubmissionChecksReplaceParams, + opts ...option.RequestOption, +) (*v3.SubmissionChecksReplaceResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"notifications/%v/%v/checks", id, submissionId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.SubmissionChecksReplaceResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +func (c *Client) CancelSubmission( + ctx context.Context, + id string, + submissionId string, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"notifications/%v/%v/checks", id, submissionId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodDelete, + Headers: headers, + Client: options.HTTPClient, + }, + ); err != nil { + return err + } + return nil +} diff --git a/option/idempotent_request_option.go b/option/idempotent_request_option.go new file mode 100644 index 0000000..8a21de8 --- /dev/null +++ b/option/idempotent_request_option.go @@ -0,0 +1,24 @@ +// This file was auto-generated by Fern from our API Definition. + +package option + +import ( + core "github.com/trycourier/courier-go/v3/core" +) + +// IdempotentRequestOption adapts the behavior of an indivdual request. +type IdempotentRequestOption = core.IdempotentRequestOption + +// WithIdempotencyKey sets the idempotencyKey request header. +func WithIdempotencyKey(idempotencyKey *string) *core.IdempotencyKeyOption { + return &core.IdempotencyKeyOption{ + IdempotencyKey: idempotencyKey, + } +} + +// WithIdempotencyExpiry sets the idempotencyExpiry request header. +func WithIdempotencyExpiry(idempotencyExpiry *int) *core.IdempotencyExpiryOption { + return &core.IdempotencyExpiryOption{ + IdempotencyExpiry: idempotencyExpiry, + } +} diff --git a/option/request_option.go b/option/request_option.go new file mode 100644 index 0000000..f94b521 --- /dev/null +++ b/option/request_option.go @@ -0,0 +1,41 @@ +// This file was auto-generated by Fern from our API Definition. + +package option + +import ( + core "github.com/trycourier/courier-go/v3/core" + http "net/http" +) + +// RequestOption adapts the behavior of an indivdual request. +type RequestOption = core.RequestOption + +// WithBaseURL sets the base URL, overriding the default +// environment, if any. +func WithBaseURL(baseURL string) *core.BaseURLOption { + return &core.BaseURLOption{ + BaseURL: baseURL, + } +} + +// WithHTTPClient uses the given HTTPClient to issue the request. +func WithHTTPClient(httpClient core.HTTPClient) *core.HTTPClientOption { + return &core.HTTPClientOption{ + HTTPClient: httpClient, + } +} + +// WithHTTPHeader adds the given http.Header to the request. +func WithHTTPHeader(httpHeader http.Header) *core.HTTPHeaderOption { + return &core.HTTPHeaderOption{ + // Clone the headers so they can't be modified after the option call. + HTTPHeader: httpHeader.Clone(), + } +} + +// WithAuthorizationToken sets the 'Authorization: Bearer ' request header. +func WithAuthorizationToken(authorizationToken string) *core.AuthorizationTokenOption { + return &core.AuthorizationTokenOption{ + AuthorizationToken: authorizationToken, + } +} diff --git a/pointer.go b/pointer.go new file mode 100644 index 0000000..82fb917 --- /dev/null +++ b/pointer.go @@ -0,0 +1,103 @@ +package api + +import "time" + +// Bool returns a pointer to the given bool value. +func Bool(b bool) *bool { + return &b +} + +// Byte returns a pointer to the given byte value. +func Byte(b byte) *byte { + return &b +} + +// Complex64 returns a pointer to the given complex64 value. +func Complex64(c complex64) *complex64 { + return &c +} + +// Complex128 returns a pointer to the given complex128 value. +func Complex128(c complex128) *complex128 { + return &c +} + +// Float32 returns a pointer to the given float32 value. +func Float32(f float32) *float32 { + return &f +} + +// Float64 returns a pointer to the given float64 value. +func Float64(f float64) *float64 { + return &f +} + +// Int returns a pointer to the given int value. +func Int(i int) *int { + return &i +} + +// Int8 returns a pointer to the given int8 value. +func Int8(i int8) *int8 { + return &i +} + +// Int16 returns a pointer to the given int16 value. +func Int16(i int16) *int16 { + return &i +} + +// Int32 returns a pointer to the given int32 value. +func Int32(i int32) *int32 { + return &i +} + +// Int64 returns a pointer to the given int64 value. +func Int64(i int64) *int64 { + return &i +} + +// Rune returns a pointer to the given rune value. +func Rune(r rune) *rune { + return &r +} + +// String returns a pointer to the given string value. +func String(s string) *string { + return &s +} + +// Uint returns a pointer to the given uint value. +func Uint(u uint) *uint { + return &u +} + +// Uint8 returns a pointer to the given uint8 value. +func Uint8(u uint8) *uint8 { + return &u +} + +// Uint16 returns a pointer to the given uint16 value. +func Uint16(u uint16) *uint16 { + return &u +} + +// Uint32 returns a pointer to the given uint32 value. +func Uint32(u uint32) *uint32 { + return &u +} + +// Uint64 returns a pointer to the given uint64 value. +func Uint64(u uint64) *uint64 { + return &u +} + +// Uintptr returns a pointer to the given uintptr value. +func Uintptr(u uintptr) *uintptr { + return &u +} + +// Time returns a pointer to the given time.Time value. +func Time(t time.Time) *time.Time { + return &t +} diff --git a/profiles.go b/profiles.go index b25e47c..10e95c9 100644 --- a/profiles.go +++ b/profiles.go @@ -1,50 +1,296 @@ -package courier +// This file was auto-generated by Fern from our API Definition. + +package api import ( - "bytes" - "encoding/json" - "fmt" - "net/http" + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" ) -type Profile struct { - Profile interface{} `json:"profile"` +type MergeProfileRequest struct { + Profile map[string]interface{} `json:"profile,omitempty"` +} + +type GetListSubscriptionsRequest struct { + // A unique identifier that allows for fetching the next set of message statuses. + Cursor *string `json:"-"` +} + +type ReplaceProfileRequest struct { + Profile map[string]interface{} `json:"profile,omitempty"` +} + +type DeleteListSubscriptionResponse struct { + status string + + _rawJSON json.RawMessage +} + +func (d *DeleteListSubscriptionResponse) Status() string { + return d.status } -func (s *Client) GetProfile(id string) (*Profile, error) { - url := fmt.Sprintf(s.BaseUrl+"/profiles/%s", id) - req, err := http.NewRequest("GET", url, nil) - if err != nil { - return nil, err +func (d *DeleteListSubscriptionResponse) UnmarshalJSON(data []byte) error { + type unmarshaler DeleteListSubscriptionResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err } - bytes, err := s.doRequest(req) - if err != nil { - return nil, err + *d = DeleteListSubscriptionResponse(value) + d.status = "SUCCESS" + d._rawJSON = json.RawMessage(data) + return nil +} + +func (d *DeleteListSubscriptionResponse) MarshalJSON() ([]byte, error) { + type embed DeleteListSubscriptionResponse + var marshaler = struct { + embed + Status string `json:"status"` + }{ + embed: embed(*d), + Status: "SUCCESS", + } + return json.Marshal(marshaler) +} + +func (d *DeleteListSubscriptionResponse) String() string { + if len(d._rawJSON) > 0 { + if value, err := core.StringifyJSON(d._rawJSON); err == nil { + return value + } } - var data Profile - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err + if value, err := core.StringifyJSON(d); err == nil { + return value } - return &data, nil + return fmt.Sprintf("%#v", d) } -func (s *Client) MergeProfile(id string, profile []byte) error { - url := fmt.Sprintf(s.BaseUrl+"/profiles/%s", id) - req, err := http.NewRequest("POST", url, bytes.NewBuffer(profile)) - if err != nil { +type GetListSubscriptionsResponse struct { + Paging *Paging `json:"paging,omitempty"` + // An array of lists + Results []*GetListSubscriptionsList `json:"results,omitempty"` + + _rawJSON json.RawMessage +} + +func (g *GetListSubscriptionsResponse) UnmarshalJSON(data []byte) error { + type unmarshaler GetListSubscriptionsResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { return err } - _, err = s.doRequest(req) - return err + *g = GetListSubscriptionsResponse(value) + g._rawJSON = json.RawMessage(data) + return nil +} + +func (g *GetListSubscriptionsResponse) String() string { + if len(g._rawJSON) > 0 { + if value, err := core.StringifyJSON(g._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(g); err == nil { + return value + } + return fmt.Sprintf("%#v", g) } -func (s *Client) UpdateProfile(id string, profile []byte) error { - url := fmt.Sprintf(s.BaseUrl+"/profiles/%s", id) - req, err := http.NewRequest("PUT", url, bytes.NewBuffer(profile)) - if err != nil { +type MergeProfileResponse struct { + status string + + _rawJSON json.RawMessage +} + +func (m *MergeProfileResponse) Status() string { + return m.status +} + +func (m *MergeProfileResponse) UnmarshalJSON(data []byte) error { + type unmarshaler MergeProfileResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *m = MergeProfileResponse(value) + m.status = "SUCCESS" + m._rawJSON = json.RawMessage(data) + return nil +} + +func (m *MergeProfileResponse) MarshalJSON() ([]byte, error) { + type embed MergeProfileResponse + var marshaler = struct { + embed + Status string `json:"status"` + }{ + embed: embed(*m), + Status: "SUCCESS", + } + return json.Marshal(marshaler) +} + +func (m *MergeProfileResponse) String() string { + if len(m._rawJSON) > 0 { + if value, err := core.StringifyJSON(m._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(m); err == nil { + return value + } + return fmt.Sprintf("%#v", m) +} + +type ProfileGetResponse struct { + Profile map[string]interface{} `json:"profile,omitempty"` + Preferences *RecipientPreferences `json:"preferences,omitempty"` + + _rawJSON json.RawMessage +} + +func (p *ProfileGetResponse) UnmarshalJSON(data []byte) error { + type unmarshaler ProfileGetResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { return err } - _, err = s.doRequest(req) - return err + *p = ProfileGetResponse(value) + p._rawJSON = json.RawMessage(data) + return nil +} + +func (p *ProfileGetResponse) String() string { + if len(p._rawJSON) > 0 { + if value, err := core.StringifyJSON(p._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(p); err == nil { + return value + } + return fmt.Sprintf("%#v", p) +} + +type ReplaceProfileResponse struct { + status string + + _rawJSON json.RawMessage +} + +func (r *ReplaceProfileResponse) Status() string { + return r.status +} + +func (r *ReplaceProfileResponse) UnmarshalJSON(data []byte) error { + type unmarshaler ReplaceProfileResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *r = ReplaceProfileResponse(value) + r.status = "SUCCESS" + r._rawJSON = json.RawMessage(data) + return nil +} + +func (r *ReplaceProfileResponse) MarshalJSON() ([]byte, error) { + type embed ReplaceProfileResponse + var marshaler = struct { + embed + Status string `json:"status"` + }{ + embed: embed(*r), + Status: "SUCCESS", + } + return json.Marshal(marshaler) +} + +func (r *ReplaceProfileResponse) String() string { + if len(r._rawJSON) > 0 { + if value, err := core.StringifyJSON(r._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(r); err == nil { + return value + } + return fmt.Sprintf("%#v", r) +} + +type SubscribeToListsRequest struct { + Lists []*SubscribeToListsRequestListObject `json:"lists,omitempty"` + + _rawJSON json.RawMessage +} + +func (s *SubscribeToListsRequest) UnmarshalJSON(data []byte) error { + type unmarshaler SubscribeToListsRequest + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *s = SubscribeToListsRequest(value) + s._rawJSON = json.RawMessage(data) + return nil +} + +func (s *SubscribeToListsRequest) String() string { + if len(s._rawJSON) > 0 { + if value, err := core.StringifyJSON(s._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(s); err == nil { + return value + } + return fmt.Sprintf("%#v", s) +} + +type SubscribeToListsResponse struct { + status string + + _rawJSON json.RawMessage +} + +func (s *SubscribeToListsResponse) Status() string { + return s.status +} + +func (s *SubscribeToListsResponse) UnmarshalJSON(data []byte) error { + type unmarshaler SubscribeToListsResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *s = SubscribeToListsResponse(value) + s.status = "SUCCESS" + s._rawJSON = json.RawMessage(data) + return nil +} + +func (s *SubscribeToListsResponse) MarshalJSON() ([]byte, error) { + type embed SubscribeToListsResponse + var marshaler = struct { + embed + Status string `json:"status"` + }{ + embed: embed(*s), + Status: "SUCCESS", + } + return json.Marshal(marshaler) +} + +func (s *SubscribeToListsResponse) String() string { + if len(s._rawJSON) > 0 { + if value, err := core.StringifyJSON(s._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(s); err == nil { + return value + } + return fmt.Sprintf("%#v", s) } diff --git a/profiles/client.go b/profiles/client.go new file mode 100644 index 0000000..b94eb50 --- /dev/null +++ b/profiles/client.go @@ -0,0 +1,440 @@ +// This file was auto-generated by Fern from our API Definition. + +package profiles + +import ( + bytes "bytes" + context "context" + json "encoding/json" + errors "errors" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + io "io" + http "net/http" + url "net/url" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +// Returns the specified user profile. +func (c *Client) Get( + ctx context.Context, + // A unique identifier representing the user associated with the requested profile. + userId string, + opts ...option.RequestOption, +) (*v3.ProfileGetResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"profiles/%v", userId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.ProfileGetResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Merge the supplied values with an existing profile or create a new profile if one doesn't already exist. +func (c *Client) Create( + ctx context.Context, + // A unique identifier representing the user associated with the requested profile. + userId string, + request *v3.MergeProfileRequest, + opts ...option.IdempotentRequestOption, +) (*v3.MergeProfileResponse, error) { + options := core.NewIdempotentRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"profiles/%v", userId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.MergeProfileResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPost, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// When using `PUT`, be sure to include all the key-value pairs required by the recipient's profile. +// Any key-value pairs that exist in the profile but fail to be included in the `PUT` request will be +// removed from the profile. Remember, a `PUT` update is a full replacement of the data. For partial updates, +// use the [Patch](https://www.courier.com/docs/reference/profiles/patch/) request. +func (c *Client) Replace( + ctx context.Context, + // A unique identifier representing the user associated with the requested profile. + userId string, + request *v3.ReplaceProfileRequest, + opts ...option.RequestOption, +) (*v3.ReplaceProfileResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"profiles/%v", userId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.ReplaceProfileResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Deletes the specified user profile. +func (c *Client) Delete( + ctx context.Context, + // A unique identifier representing the user associated with the requested profile. + userId string, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"profiles/%v", userId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodDelete, + Headers: headers, + Client: options.HTTPClient, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return err + } + return nil +} + +// Returns the subscribed lists for a specified user. +func (c *Client) GetListSubscriptions( + ctx context.Context, + // A unique identifier representing the user associated with the requested profile. + userId string, + request *v3.GetListSubscriptionsRequest, + opts ...option.RequestOption, +) (*v3.GetListSubscriptionsResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"profiles/%v/lists", userId) + + queryParams := make(url.Values) + if request.Cursor != nil { + queryParams.Add("cursor", fmt.Sprintf("%v", *request.Cursor)) + } + if len(queryParams) > 0 { + endpointURL += "?" + queryParams.Encode() + } + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.GetListSubscriptionsResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Subscribes the given user to one or more lists. If the list does not exist, it will be created. +func (c *Client) SubscribeToLists( + ctx context.Context, + // A unique identifier representing the user associated with the requested profile. + userId string, + request *v3.SubscribeToListsRequest, + opts ...option.IdempotentRequestOption, +) (*v3.SubscribeToListsResponse, error) { + options := core.NewIdempotentRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"profiles/%v/lists", userId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.SubscribeToListsResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPost, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Removes all list subscriptions for given user. +func (c *Client) DeleteListSubscription( + ctx context.Context, + // A unique identifier representing the user associated with the requested profile. + userId string, + opts ...option.RequestOption, +) (*v3.DeleteListSubscriptionResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"profiles/%v/lists", userId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.DeleteListSubscriptionResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodDelete, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} diff --git a/send.go b/send.go deleted file mode 100644 index 437ae0c..0000000 --- a/send.go +++ /dev/null @@ -1,103 +0,0 @@ -package courier - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "net/http" -) - -type SendResponse struct { - MessageId string -} - -type sendRequest struct { - EventID string `json:"event"` - Recipient string `json:"recipient"` - Profile interface{} `json:"profile,omitempty"` - Data interface{} `json:"data,omitempty"` - Brand string `json:"brand,omitempty"` - Override interface{} `json:"override,omitempty"` - Preferences interface{} `json:"preferences,omitempty"` -} - -type sendToListRequest struct { - EventID string `json:"event"` - ListID string `json:"list,omitempty"` - Pattern string `json:"pattern,omitempty"` - Data interface{} `json:"data,omitempty"` - Brand string `json:"brand,omitempty"` - Override interface{} `json:"override,omitempty"` -} - -func (c *Client) Send(ctx context.Context, eventID string, recipientID string, profile interface{}, data interface{}, brand string, override interface{}, preferences interface{}) (string, error) { - payload := sendRequest{ - EventID: eventID, - Recipient: recipientID, - Profile: profile, - Data: data, - Brand: brand, - Override: override, - Preferences: preferences, - } - - body, err := json.Marshal(payload) - if err != nil { - return "", err - } - - req, err := http.NewRequestWithContext(ctx, "POST", c.BaseUrl+"/send", bytes.NewReader(body)) - if err != nil { - return "", err - } - - bytes, err := c.doRequest(req) - if err != nil { - return "", err - } - var responseData SendResponse - err = json.Unmarshal(bytes, &responseData) - if err != nil { - return "", err - } - - return responseData.MessageId, nil -} - -func (c *Client) SendToList(ctx context.Context, eventID string, listID string, pattern string, data interface{}, brand string, override interface{}) (string, error) { - if (listID == "" && pattern == "") || (listID != "" && pattern != "") { - return "", errors.New("list.send requires a listID or a pattern") - } - - payload := sendToListRequest{ - EventID: eventID, - ListID: listID, - Pattern: pattern, - Data: data, - Brand: brand, - Override: override, - } - - body, err := json.Marshal(payload) - if err != nil { - return "", err - } - - req, err := http.NewRequestWithContext(ctx, "POST", c.BaseUrl+"/send/list", bytes.NewReader(body)) - if err != nil { - return "", err - } - - bytes, err := c.doRequest(req) - if err != nil { - return "", err - } - var responseData SendResponse - err = json.Unmarshal(bytes, &responseData) - if err != nil { - return "", err - } - - return responseData.MessageId, nil -} diff --git a/send_test.go b/send_test.go deleted file mode 100644 index b515d42..0000000 --- a/send_test.go +++ /dev/null @@ -1,165 +0,0 @@ -package courier_test - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "github.com/trycourier/courier-go" - - "github.com/stretchr/testify/assert" -) - -func TestSend(t *testing.T) { - - type Data struct { - Foo string - } - type Profile struct { - Email string - } - type Override struct { - Bar string - } - type Preferences struct { - Fizz string - } - type RequestBody struct { - Event string - Recipient string - Profile Profile - Data Data - Brand string - Override Override - Preferences Preferences - } - - var requestBody RequestBody - - expectedResponseID := "123456789" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/send", req.URL.String()) - - decoder := json.NewDecoder(req.Body) - err := decoder.Decode(&requestBody) - if err != nil { - t.Error(err) - } - - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"MessageId\" : \"%s\" }", expectedResponseID))) - if writeErr != nil { - t.Error(writeErr) - } - - })) - defer server.Close() - - t.Run("sends request", func(t *testing.T) { - - client := courier.CourierClient("key", server.URL) - - data := &Data{ - Foo: "bar", - } - profile := &Profile{ - Email: "foo@bar.com", - } - eventID := "event-id" - recipientID := "recpient-id" - brand := "brand-id" - override := &Override{ - Bar: "bar", - } - preferences := &Preferences{ - Fizz: "fizz", - } - messageID, err := client.Send(context.Background(), eventID, recipientID, profile, data, brand, override, preferences) - - assert.Nil(t, err) - assert.Equal(t, expectedResponseID, messageID) - assert.Equal(t, eventID, requestBody.Event) - assert.Equal(t, recipientID, requestBody.Recipient) - assert.Equal(t, data.Foo, requestBody.Data.Foo) - assert.Equal(t, profile.Email, requestBody.Profile.Email) - assert.Equal(t, brand, requestBody.Brand) - assert.Equal(t, override.Bar, requestBody.Override.Bar) - assert.Equal(t, preferences.Fizz, requestBody.Preferences.Fizz) - }) - -} - -func TestSendToList(t *testing.T) { - - type Data struct { - Foo string - } - - type Override struct { - Bar string - } - - type RequestBody struct { - Event string - List string - Pattern string - Data Data - Brand string - Override Override - } - - var requestBody RequestBody - - expectedResponseID := "123456789" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/send/list", req.URL.String()) - - decoder := json.NewDecoder(req.Body) - err := decoder.Decode(&requestBody) - if err != nil { - t.Error(err) - } - - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"MessageId\" : \"%s\" }", expectedResponseID))) - if writeErr != nil { - t.Error(writeErr) - } - - })) - defer server.Close() - - t.Run("sends request", func(t *testing.T) { - - client := courier.CourierClient("key", server.URL) - - data := &Data{ - Foo: "bar", - } - eventID := "event-id" - listID := "list-id" - brand := "brand-id" - override := &Override{ - Bar: "bar", - } - messageID, err := client.SendToList(context.Background(), eventID, listID, "", data, brand, override) - - assert.Nil(t, err) - assert.Equal(t, expectedResponseID, messageID) - assert.Equal(t, eventID, requestBody.Event) - assert.Equal(t, listID, requestBody.List) - assert.Equal(t, data.Foo, requestBody.Data.Foo) - assert.Equal(t, brand, requestBody.Brand) - assert.Equal(t, override.Bar, requestBody.Override.Bar) - }) - -} diff --git a/templates.go b/templates.go new file mode 100644 index 0000000..2cb564f --- /dev/null +++ b/templates.go @@ -0,0 +1,45 @@ +// This file was auto-generated by Fern from our API Definition. + +package api + +import ( + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" +) + +type ListTemplatesRequest struct { + // A unique identifier that allows for fetching the next set of templates + Cursor *string `json:"-"` +} + +type ListTemplatesResponse struct { + Paging *Paging `json:"paging,omitempty"` + // An array of Notification Templates + Results []*NotificationTemplates `json:"results,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *ListTemplatesResponse) UnmarshalJSON(data []byte) error { + type unmarshaler ListTemplatesResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListTemplatesResponse(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListTemplatesResponse) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} diff --git a/templates/client.go b/templates/client.go new file mode 100644 index 0000000..7515a09 --- /dev/null +++ b/templates/client.go @@ -0,0 +1,71 @@ +// This file was auto-generated by Fern from our API Definition. + +package templates + +import ( + context "context" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + http "net/http" + url "net/url" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +// Returns a list of notification templates +func (c *Client) List( + ctx context.Context, + request *v3.ListTemplatesRequest, + opts ...option.RequestOption, +) (*v3.ListTemplatesResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := baseURL + "/" + "notifications" + + queryParams := make(url.Values) + if request.Cursor != nil { + queryParams.Add("cursor", fmt.Sprintf("%v", *request.Cursor)) + } + if len(queryParams) > 0 { + endpointURL += "?" + queryParams.Encode() + } + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.ListTemplatesResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} diff --git a/tenants.go b/tenants.go new file mode 100644 index 0000000..f4fd988 --- /dev/null +++ b/tenants.go @@ -0,0 +1,155 @@ +// This file was auto-generated by Fern from our API Definition. + +package api + +import ( + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" +) + +type TenantCreateOrReplaceParams struct { + // Name of the tenant. + Name string `json:"name"` + // Tenant's parent id (if any). + ParentTenantId *string `json:"parent_tenant_id,omitempty"` + // Defines the preferences used for the tenant when the user hasn't specified their own. + DefaultPreferences *DefaultPreferences `json:"default_preferences,omitempty"` + // Arbitrary properties accessible to a template. + Properties []TemplateProperty `json:"properties,omitempty"` + // A user profile object merged with user profile on send. + UserProfile map[string]interface{} `json:"user_profile,omitempty"` + // Brand to be used for the account when one is not specified by the send call. + BrandId *string `json:"brand_id,omitempty"` +} + +type DefaultPreferences struct { + Items []*SubscriptionTopic `json:"items,omitempty"` + + _rawJSON json.RawMessage +} + +func (d *DefaultPreferences) UnmarshalJSON(data []byte) error { + type unmarshaler DefaultPreferences + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *d = DefaultPreferences(value) + d._rawJSON = json.RawMessage(data) + return nil +} + +func (d *DefaultPreferences) String() string { + if len(d._rawJSON) > 0 { + if value, err := core.StringifyJSON(d._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(d); err == nil { + return value + } + return fmt.Sprintf("%#v", d) +} + +type TemplateProperty = interface{} + +type Tenant struct { + // Id of the tenant. + Id string `json:"id"` + // Name of the tenant. + Name string `json:"name"` + // Tenant's parent id (if any). + ParentTenantId *string `json:"parent_tenant_id,omitempty"` + // Defines the preferences used for the account when the user hasn't specified their own. + DefaultPreferences *DefaultPreferences `json:"default_preferences,omitempty"` + // Arbitrary properties accessible to a template. + Properties *TemplateProperty `json:"properties,omitempty"` + // A user profile object merged with user profile on send. + UserProfile map[string]interface{} `json:"user_profile,omitempty"` + // Brand to be used for the account when one is not specified by the send call. + BrandId *string `json:"brand_id,omitempty"` + + _rawJSON json.RawMessage +} + +func (t *Tenant) UnmarshalJSON(data []byte) error { + type unmarshaler Tenant + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *t = Tenant(value) + t._rawJSON = json.RawMessage(data) + return nil +} + +func (t *Tenant) String() string { + if len(t._rawJSON) > 0 { + if value, err := core.StringifyJSON(t._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(t); err == nil { + return value + } + return fmt.Sprintf("%#v", t) +} + +type TenantListResponse struct { + // A pointer to the next page of results. Defined only whenhas_more is set to true. + Cursor *string `json:"cursor,omitempty"` + // Set to true when there are more pages that can be retrieved. + HasMore bool `json:"has_more"` + // An array of Tenants + Items []*Tenant `json:"items,omitempty"` + // A url that may be used to generate fetch the next set of results. + // Defined only whenhas_more is set to true + NextUrl *string `json:"next_url,omitempty"` + // A url that may be used to generate these results. + Url string `json:"url"` + // Always set to "list". Represents the type of this object. + type_ string + + _rawJSON json.RawMessage +} + +func (t *TenantListResponse) Type() string { + return t.type_ +} + +func (t *TenantListResponse) UnmarshalJSON(data []byte) error { + type unmarshaler TenantListResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *t = TenantListResponse(value) + t.type_ = "list" + t._rawJSON = json.RawMessage(data) + return nil +} + +func (t *TenantListResponse) MarshalJSON() ([]byte, error) { + type embed TenantListResponse + var marshaler = struct { + embed + Type string `json:"type"` + }{ + embed: embed(*t), + Type: "list", + } + return json.Marshal(marshaler) +} + +func (t *TenantListResponse) String() string { + if len(t._rawJSON) > 0 { + if value, err := core.StringifyJSON(t._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(t); err == nil { + return value + } + return fmt.Sprintf("%#v", t) +} diff --git a/tenants/client.go b/tenants/client.go new file mode 100644 index 0000000..1816be0 --- /dev/null +++ b/tenants/client.go @@ -0,0 +1,209 @@ +// This file was auto-generated by Fern from our API Definition. + +package tenants + +import ( + bytes "bytes" + context "context" + json "encoding/json" + errors "errors" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + io "io" + http "net/http" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +func (c *Client) CreateOrReplace( + ctx context.Context, + // A unique identifier representing the tenant to be returned. + tenantId string, + request *v3.TenantCreateOrReplaceParams, + opts ...option.RequestOption, +) (*v3.Tenant, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"tenants/%v", tenantId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.Tenant + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +func (c *Client) Get( + ctx context.Context, + // A unique identifier representing the tenant to be returned. + tenantId string, + opts ...option.RequestOption, +) (*v3.Tenant, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"tenants/%v", tenantId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *v3.Tenant + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +func (c *Client) List( + ctx context.Context, + opts ...option.RequestOption, +) (*v3.TenantListResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := baseURL + "/" + "tenants" + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *v3.TenantListResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +func (c *Client) Delete( + ctx context.Context, + // Id of the tenant to be deleted. + tenantId string, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"tenants/%v", tenantId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodDelete, + Headers: headers, + Client: options.HTTPClient, + }, + ); err != nil { + return err + } + return nil +} diff --git a/translations/client.go b/translations/client.go new file mode 100644 index 0000000..bfd452c --- /dev/null +++ b/translations/client.go @@ -0,0 +1,147 @@ +// This file was auto-generated by Fern from our API Definition. + +package translations + +import ( + bytes "bytes" + context "context" + json "encoding/json" + errors "errors" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + io "io" + http "net/http" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +// Get translations by locale +func (c *Client) Get( + ctx context.Context, + // The domain you want to retrieve translations for. Only `default` is supported at the moment + domain string, + // The locale you want to retrieve the translations for + locale string, + opts ...option.RequestOption, +) (string, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"translations/%v/%v", domain, locale) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 404: + value := new(v3.NotFoundError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response string + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return "", err + } + return response, nil +} + +// Update a translation +func (c *Client) Update( + ctx context.Context, + // The domain you want to retrieve translations for. Only `default` is supported at the moment + domain string, + // The locale you want to retrieve the translations for + locale string, + request string, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"translations/%v/%v", domain, locale) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 404: + value := new(v3.NotFoundError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + Request: request, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return err + } + return nil +} diff --git a/types.go b/types.go new file mode 100644 index 0000000..bc9bc0b --- /dev/null +++ b/types.go @@ -0,0 +1,6910 @@ +// This file was auto-generated by Fern from our API Definition. + +package api + +import ( + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" +) + +type SendMessageRequest struct { + // Defines the message to be delivered + Message *Message `json:"message,omitempty"` +} + +type SendMessageResponse struct { + // A successful call to `POST /send` returns a `202` status code along with a `requestId` in the response body. + // + // For send requests that have a single recipient, the `requestId` is assigned to the derived message as its message_id. Therefore the `requestId` can be supplied to the Message's API for single recipient messages. + // + // For send requests that have multiple recipients (accounts, audiences, lists, etc.), Courier assigns a unique id to each derived message as its `message_id`. Therefore the `requestId` cannot be supplied to the Message's API for single-recipient messages. + RequestId string `json:"requestId"` + + _rawJSON json.RawMessage +} + +func (s *SendMessageResponse) UnmarshalJSON(data []byte) error { + type unmarshaler SendMessageResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *s = SendMessageResponse(value) + s._rawJSON = json.RawMessage(data) + return nil +} + +func (s *SendMessageResponse) String() string { + if len(s._rawJSON) > 0 { + if value, err := core.StringifyJSON(s._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(s); err == nil { + return value + } + return fmt.Sprintf("%#v", s) +} + +type AudienceMember struct { + AddedAt string `json:"added_at"` + AudienceId string `json:"audience_id"` + AudienceVersion int `json:"audience_version"` + MemberId string `json:"member_id"` + Reason string `json:"reason"` + + _rawJSON json.RawMessage +} + +func (a *AudienceMember) UnmarshalJSON(data []byte) error { + type unmarshaler AudienceMember + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AudienceMember(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AudienceMember) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AudienceMemberGetResponse struct { + AudienceMember *AudienceMember `json:"audienceMember,omitempty"` + + _rawJSON json.RawMessage +} + +func (a *AudienceMemberGetResponse) UnmarshalJSON(data []byte) error { + type unmarshaler AudienceMemberGetResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AudienceMemberGetResponse(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AudienceMemberGetResponse) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type BaseFilterConfig struct { + // The operator to use for filtering + Operator *Operator `json:"operator,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BaseFilterConfig) UnmarshalJSON(data []byte) error { + type unmarshaler BaseFilterConfig + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BaseFilterConfig(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BaseFilterConfig) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type ComparisonOperator string + +const ( + ComparisonOperatorEndsWith ComparisonOperator = "ENDS_WITH" + ComparisonOperatorEq ComparisonOperator = "EQ" + ComparisonOperatorExists ComparisonOperator = "EXISTS" + ComparisonOperatorGt ComparisonOperator = "GT" + ComparisonOperatorGte ComparisonOperator = "GTE" + ComparisonOperatorIncludes ComparisonOperator = "INCLUDES" + ComparisonOperatorIsAfter ComparisonOperator = "IS_AFTER" + ComparisonOperatorIsBefore ComparisonOperator = "IS_BEFORE" + ComparisonOperatorLt ComparisonOperator = "LT" + ComparisonOperatorLte ComparisonOperator = "LTE" + ComparisonOperatorNeq ComparisonOperator = "NEQ" + ComparisonOperatorOmit ComparisonOperator = "OMIT" + ComparisonOperatorStartsWith ComparisonOperator = "STARTS_WITH" +) + +func NewComparisonOperatorFromString(s string) (ComparisonOperator, error) { + switch s { + case "ENDS_WITH": + return ComparisonOperatorEndsWith, nil + case "EQ": + return ComparisonOperatorEq, nil + case "EXISTS": + return ComparisonOperatorExists, nil + case "GT": + return ComparisonOperatorGt, nil + case "GTE": + return ComparisonOperatorGte, nil + case "INCLUDES": + return ComparisonOperatorIncludes, nil + case "IS_AFTER": + return ComparisonOperatorIsAfter, nil + case "IS_BEFORE": + return ComparisonOperatorIsBefore, nil + case "LT": + return ComparisonOperatorLt, nil + case "LTE": + return ComparisonOperatorLte, nil + case "NEQ": + return ComparisonOperatorNeq, nil + case "OMIT": + return ComparisonOperatorOmit, nil + case "STARTS_WITH": + return ComparisonOperatorStartsWith, nil + } + var t ComparisonOperator + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (c ComparisonOperator) Ptr() *ComparisonOperator { + return &c +} + +type FilterConfig struct { + typeName string + SingleFilterConfig *SingleFilterConfig + NestedFilterConfig *NestedFilterConfig +} + +func NewFilterConfigFromSingleFilterConfig(value *SingleFilterConfig) *FilterConfig { + return &FilterConfig{typeName: "singleFilterConfig", SingleFilterConfig: value} +} + +func NewFilterConfigFromNestedFilterConfig(value *NestedFilterConfig) *FilterConfig { + return &FilterConfig{typeName: "nestedFilterConfig", NestedFilterConfig: value} +} + +func (f *FilterConfig) UnmarshalJSON(data []byte) error { + valueSingleFilterConfig := new(SingleFilterConfig) + if err := json.Unmarshal(data, &valueSingleFilterConfig); err == nil { + f.typeName = "singleFilterConfig" + f.SingleFilterConfig = valueSingleFilterConfig + return nil + } + valueNestedFilterConfig := new(NestedFilterConfig) + if err := json.Unmarshal(data, &valueNestedFilterConfig); err == nil { + f.typeName = "nestedFilterConfig" + f.NestedFilterConfig = valueNestedFilterConfig + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, f) +} + +func (f FilterConfig) MarshalJSON() ([]byte, error) { + switch f.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", f.typeName, f) + case "singleFilterConfig": + return json.Marshal(f.SingleFilterConfig) + case "nestedFilterConfig": + return json.Marshal(f.NestedFilterConfig) + } +} + +type FilterConfigVisitor interface { + VisitSingleFilterConfig(*SingleFilterConfig) error + VisitNestedFilterConfig(*NestedFilterConfig) error +} + +func (f *FilterConfig) Accept(visitor FilterConfigVisitor) error { + switch f.typeName { + default: + return fmt.Errorf("invalid type %s in %T", f.typeName, f) + case "singleFilterConfig": + return visitor.VisitSingleFilterConfig(f.SingleFilterConfig) + case "nestedFilterConfig": + return visitor.VisitNestedFilterConfig(f.NestedFilterConfig) + } +} + +type LogicalOperator string + +const ( + LogicalOperatorAnd LogicalOperator = "AND" + LogicalOperatorOr LogicalOperator = "OR" +) + +func NewLogicalOperatorFromString(s string) (LogicalOperator, error) { + switch s { + case "AND": + return LogicalOperatorAnd, nil + case "OR": + return LogicalOperatorOr, nil + } + var t LogicalOperator + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (l LogicalOperator) Ptr() *LogicalOperator { + return &l +} + +// The operator to use for filtering +type NestedFilterConfig struct { + // The operator to use for filtering + Operator *Operator `json:"operator,omitempty"` + Rules []*FilterConfig `json:"rules,omitempty"` + + _rawJSON json.RawMessage +} + +func (n *NestedFilterConfig) UnmarshalJSON(data []byte) error { + type unmarshaler NestedFilterConfig + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *n = NestedFilterConfig(value) + n._rawJSON = json.RawMessage(data) + return nil +} + +func (n *NestedFilterConfig) String() string { + if len(n._rawJSON) > 0 { + if value, err := core.StringifyJSON(n._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(n); err == nil { + return value + } + return fmt.Sprintf("%#v", n) +} + +type Operator struct { + typeName string + ComparisonOperator ComparisonOperator + LogicalOperator LogicalOperator +} + +func NewOperatorFromComparisonOperator(value ComparisonOperator) *Operator { + return &Operator{typeName: "comparisonOperator", ComparisonOperator: value} +} + +func NewOperatorFromLogicalOperator(value LogicalOperator) *Operator { + return &Operator{typeName: "logicalOperator", LogicalOperator: value} +} + +func (o *Operator) UnmarshalJSON(data []byte) error { + var valueComparisonOperator ComparisonOperator + if err := json.Unmarshal(data, &valueComparisonOperator); err == nil { + o.typeName = "comparisonOperator" + o.ComparisonOperator = valueComparisonOperator + return nil + } + var valueLogicalOperator LogicalOperator + if err := json.Unmarshal(data, &valueLogicalOperator); err == nil { + o.typeName = "logicalOperator" + o.LogicalOperator = valueLogicalOperator + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, o) +} + +func (o Operator) MarshalJSON() ([]byte, error) { + switch o.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", o.typeName, o) + case "comparisonOperator": + return json.Marshal(o.ComparisonOperator) + case "logicalOperator": + return json.Marshal(o.LogicalOperator) + } +} + +type OperatorVisitor interface { + VisitComparisonOperator(ComparisonOperator) error + VisitLogicalOperator(LogicalOperator) error +} + +func (o *Operator) Accept(visitor OperatorVisitor) error { + switch o.typeName { + default: + return fmt.Errorf("invalid type %s in %T", o.typeName, o) + case "comparisonOperator": + return visitor.VisitComparisonOperator(o.ComparisonOperator) + case "logicalOperator": + return visitor.VisitLogicalOperator(o.LogicalOperator) + } +} + +// A single filter to use for filtering +type SingleFilterConfig struct { + // The operator to use for filtering + Operator *Operator `json:"operator,omitempty"` + // The value to use for filtering + Value string `json:"value"` + // The attribe name from profile whose value will be operated against the filter value + Path string `json:"path"` + + _rawJSON json.RawMessage +} + +func (s *SingleFilterConfig) UnmarshalJSON(data []byte) error { + type unmarshaler SingleFilterConfig + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *s = SingleFilterConfig(value) + s._rawJSON = json.RawMessage(data) + return nil +} + +func (s *SingleFilterConfig) String() string { + if len(s._rawJSON) > 0 { + if value, err := core.StringifyJSON(s._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(s); err == nil { + return value + } + return fmt.Sprintf("%#v", s) +} + +type Actor struct { + Id *string `json:"id,omitempty"` + Email *string `json:"email,omitempty"` + + _rawJSON json.RawMessage +} + +func (a *Actor) UnmarshalJSON(data []byte) error { + type unmarshaler Actor + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = Actor(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *Actor) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type GetAuditEventParams struct { + AuditEventId string `json:"auditEventId"` + + _rawJSON json.RawMessage +} + +func (g *GetAuditEventParams) UnmarshalJSON(data []byte) error { + type unmarshaler GetAuditEventParams + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *g = GetAuditEventParams(value) + g._rawJSON = json.RawMessage(data) + return nil +} + +func (g *GetAuditEventParams) String() string { + if len(g._rawJSON) > 0 { + if value, err := core.StringifyJSON(g._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(g); err == nil { + return value + } + return fmt.Sprintf("%#v", g) +} + +type ListAuditEventsParams struct { + Cursor *string `json:"cursor,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *ListAuditEventsParams) UnmarshalJSON(data []byte) error { + type unmarshaler ListAuditEventsParams + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListAuditEventsParams(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListAuditEventsParams) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type Target struct { + Id *string `json:"id,omitempty"` + Email *string `json:"email,omitempty"` + + _rawJSON json.RawMessage +} + +func (t *Target) UnmarshalJSON(data []byte) error { + type unmarshaler Target + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *t = Target(value) + t._rawJSON = json.RawMessage(data) + return nil +} + +func (t *Target) String() string { + if len(t._rawJSON) > 0 { + if value, err := core.StringifyJSON(t._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(t); err == nil { + return value + } + return fmt.Sprintf("%#v", t) +} + +type Automation struct { + CancelationToken *string `json:"cancelation_token,omitempty"` + Steps []*AutomationStepOption `json:"steps,omitempty"` + + _rawJSON json.RawMessage +} + +func (a *Automation) UnmarshalJSON(data []byte) error { + type unmarshaler Automation + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = Automation(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *Automation) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AutomationCancelStep struct { + If *string `json:"if,omitempty"` + Ref *string `json:"ref,omitempty"` + CancelationToken *string `json:"cancelation_token,omitempty"` + action string + + _rawJSON json.RawMessage +} + +func (a *AutomationCancelStep) Action() string { + return a.action +} + +func (a *AutomationCancelStep) UnmarshalJSON(data []byte) error { + type unmarshaler AutomationCancelStep + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AutomationCancelStep(value) + a.action = "cancel" + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AutomationCancelStep) MarshalJSON() ([]byte, error) { + type embed AutomationCancelStep + var marshaler = struct { + embed + Action string `json:"action"` + }{ + embed: embed(*a), + Action: "cancel", + } + return json.Marshal(marshaler) +} + +func (a *AutomationCancelStep) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AutomationDelayStep struct { + If *string `json:"if,omitempty"` + Ref *string `json:"ref,omitempty"` + Until *string `json:"until,omitempty"` + action string + + _rawJSON json.RawMessage +} + +func (a *AutomationDelayStep) Action() string { + return a.action +} + +func (a *AutomationDelayStep) UnmarshalJSON(data []byte) error { + type unmarshaler AutomationDelayStep + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AutomationDelayStep(value) + a.action = "delay" + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AutomationDelayStep) MarshalJSON() ([]byte, error) { + type embed AutomationDelayStep + var marshaler = struct { + embed + Action string `json:"action"` + }{ + embed: embed(*a), + Action: "delay", + } + return json.Marshal(marshaler) +} + +func (a *AutomationDelayStep) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AutomationInvokeStep struct { + If *string `json:"if,omitempty"` + Ref *string `json:"ref,omitempty"` + Template string `json:"template"` + action string + + _rawJSON json.RawMessage +} + +func (a *AutomationInvokeStep) Action() string { + return a.action +} + +func (a *AutomationInvokeStep) UnmarshalJSON(data []byte) error { + type unmarshaler AutomationInvokeStep + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AutomationInvokeStep(value) + a.action = "invoke" + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AutomationInvokeStep) MarshalJSON() ([]byte, error) { + type embed AutomationInvokeStep + var marshaler = struct { + embed + Action string `json:"action"` + }{ + embed: embed(*a), + Action: "invoke", + } + return json.Marshal(marshaler) +} + +func (a *AutomationInvokeStep) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AutomationInvokeTemplateParams struct { + Brand *string `json:"brand,omitempty"` + Data map[string]interface{} `json:"data,omitempty"` + Profile *Profile `json:"profile,omitempty"` + Recipient *string `json:"recipient,omitempty"` + Template *string `json:"template,omitempty"` + TemplateId string `json:"templateId"` + + _rawJSON json.RawMessage +} + +func (a *AutomationInvokeTemplateParams) UnmarshalJSON(data []byte) error { + type unmarshaler AutomationInvokeTemplateParams + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AutomationInvokeTemplateParams(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AutomationInvokeTemplateParams) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AutomationRunContext struct { + Brand *string `json:"brand,omitempty"` + Data interface{} `json:"data,omitempty"` + Profile *Profile `json:"profile,omitempty"` + Template *string `json:"template,omitempty"` + Recipient *string `json:"recipient,omitempty"` + + _rawJSON json.RawMessage +} + +func (a *AutomationRunContext) UnmarshalJSON(data []byte) error { + type unmarshaler AutomationRunContext + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AutomationRunContext(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AutomationRunContext) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AutomationSendListStep struct { + If *string `json:"if,omitempty"` + Ref *string `json:"ref,omitempty"` + Brand *string `json:"brand,omitempty"` + Data map[string]interface{} `json:"data,omitempty"` + List string `json:"list"` + Override map[string]interface{} `json:"override,omitempty"` + Template *string `json:"template,omitempty"` + action string + + _rawJSON json.RawMessage +} + +func (a *AutomationSendListStep) Action() string { + return a.action +} + +func (a *AutomationSendListStep) UnmarshalJSON(data []byte) error { + type unmarshaler AutomationSendListStep + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AutomationSendListStep(value) + a.action = "send-list" + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AutomationSendListStep) MarshalJSON() ([]byte, error) { + type embed AutomationSendListStep + var marshaler = struct { + embed + Action string `json:"action"` + }{ + embed: embed(*a), + Action: "send-list", + } + return json.Marshal(marshaler) +} + +func (a *AutomationSendListStep) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AutomationSendStep struct { + If *string `json:"if,omitempty"` + Ref *string `json:"ref,omitempty"` + Brand *string `json:"brand,omitempty"` + Data map[string]interface{} `json:"data,omitempty"` + Override map[string]interface{} `json:"override,omitempty"` + Profile interface{} `json:"profile,omitempty"` + Recipient *string `json:"recipient,omitempty"` + Template *string `json:"template,omitempty"` + action string + + _rawJSON json.RawMessage +} + +func (a *AutomationSendStep) Action() string { + return a.action +} + +func (a *AutomationSendStep) UnmarshalJSON(data []byte) error { + type unmarshaler AutomationSendStep + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AutomationSendStep(value) + a.action = "send" + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AutomationSendStep) MarshalJSON() ([]byte, error) { + type embed AutomationSendStep + var marshaler = struct { + embed + Action string `json:"action"` + }{ + embed: embed(*a), + Action: "send", + } + return json.Marshal(marshaler) +} + +func (a *AutomationSendStep) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AutomationStep struct { + If *string `json:"if,omitempty"` + Ref *string `json:"ref,omitempty"` + + _rawJSON json.RawMessage +} + +func (a *AutomationStep) UnmarshalJSON(data []byte) error { + type unmarshaler AutomationStep + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AutomationStep(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AutomationStep) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AutomationStepAction string + +const ( + AutomationStepActionCancel AutomationStepAction = "cancel" + AutomationStepActionDelay AutomationStepAction = "delay" + AutomationStepActionInvoke AutomationStepAction = "invoke" + AutomationStepActionSend AutomationStepAction = "send" + AutomationStepActionSendList AutomationStepAction = "send-list" + AutomationStepActionUpdateProfile AutomationStepAction = "update-profile" +) + +func NewAutomationStepActionFromString(s string) (AutomationStepAction, error) { + switch s { + case "cancel": + return AutomationStepActionCancel, nil + case "delay": + return AutomationStepActionDelay, nil + case "invoke": + return AutomationStepActionInvoke, nil + case "send": + return AutomationStepActionSend, nil + case "send-list": + return AutomationStepActionSendList, nil + case "update-profile": + return AutomationStepActionUpdateProfile, nil + } + var t AutomationStepAction + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (a AutomationStepAction) Ptr() *AutomationStepAction { + return &a +} + +type AutomationStepOption struct { + typeName string + AutomationCancelStep *AutomationCancelStep + AutomationDelayStep *AutomationDelayStep + AutomationInvokeStep *AutomationInvokeStep + AutomationSendStep *AutomationSendStep + AutomationV2SendStep *AutomationV2SendStep + AutomationSendListStep *AutomationSendListStep + AutomationUpdateProfileStep *AutomationUpdateProfileStep +} + +func NewAutomationStepOptionFromAutomationCancelStep(value *AutomationCancelStep) *AutomationStepOption { + return &AutomationStepOption{typeName: "automationCancelStep", AutomationCancelStep: value} +} + +func NewAutomationStepOptionFromAutomationDelayStep(value *AutomationDelayStep) *AutomationStepOption { + return &AutomationStepOption{typeName: "automationDelayStep", AutomationDelayStep: value} +} + +func NewAutomationStepOptionFromAutomationInvokeStep(value *AutomationInvokeStep) *AutomationStepOption { + return &AutomationStepOption{typeName: "automationInvokeStep", AutomationInvokeStep: value} +} + +func NewAutomationStepOptionFromAutomationSendStep(value *AutomationSendStep) *AutomationStepOption { + return &AutomationStepOption{typeName: "automationSendStep", AutomationSendStep: value} +} + +func NewAutomationStepOptionFromAutomationV2SendStep(value *AutomationV2SendStep) *AutomationStepOption { + return &AutomationStepOption{typeName: "automationV2SendStep", AutomationV2SendStep: value} +} + +func NewAutomationStepOptionFromAutomationSendListStep(value *AutomationSendListStep) *AutomationStepOption { + return &AutomationStepOption{typeName: "automationSendListStep", AutomationSendListStep: value} +} + +func NewAutomationStepOptionFromAutomationUpdateProfileStep(value *AutomationUpdateProfileStep) *AutomationStepOption { + return &AutomationStepOption{typeName: "automationUpdateProfileStep", AutomationUpdateProfileStep: value} +} + +func (a *AutomationStepOption) UnmarshalJSON(data []byte) error { + valueAutomationCancelStep := new(AutomationCancelStep) + if err := json.Unmarshal(data, &valueAutomationCancelStep); err == nil { + a.typeName = "automationCancelStep" + a.AutomationCancelStep = valueAutomationCancelStep + return nil + } + valueAutomationDelayStep := new(AutomationDelayStep) + if err := json.Unmarshal(data, &valueAutomationDelayStep); err == nil { + a.typeName = "automationDelayStep" + a.AutomationDelayStep = valueAutomationDelayStep + return nil + } + valueAutomationInvokeStep := new(AutomationInvokeStep) + if err := json.Unmarshal(data, &valueAutomationInvokeStep); err == nil { + a.typeName = "automationInvokeStep" + a.AutomationInvokeStep = valueAutomationInvokeStep + return nil + } + valueAutomationSendStep := new(AutomationSendStep) + if err := json.Unmarshal(data, &valueAutomationSendStep); err == nil { + a.typeName = "automationSendStep" + a.AutomationSendStep = valueAutomationSendStep + return nil + } + valueAutomationV2SendStep := new(AutomationV2SendStep) + if err := json.Unmarshal(data, &valueAutomationV2SendStep); err == nil { + a.typeName = "automationV2SendStep" + a.AutomationV2SendStep = valueAutomationV2SendStep + return nil + } + valueAutomationSendListStep := new(AutomationSendListStep) + if err := json.Unmarshal(data, &valueAutomationSendListStep); err == nil { + a.typeName = "automationSendListStep" + a.AutomationSendListStep = valueAutomationSendListStep + return nil + } + valueAutomationUpdateProfileStep := new(AutomationUpdateProfileStep) + if err := json.Unmarshal(data, &valueAutomationUpdateProfileStep); err == nil { + a.typeName = "automationUpdateProfileStep" + a.AutomationUpdateProfileStep = valueAutomationUpdateProfileStep + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, a) +} + +func (a AutomationStepOption) MarshalJSON() ([]byte, error) { + switch a.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", a.typeName, a) + case "automationCancelStep": + return json.Marshal(a.AutomationCancelStep) + case "automationDelayStep": + return json.Marshal(a.AutomationDelayStep) + case "automationInvokeStep": + return json.Marshal(a.AutomationInvokeStep) + case "automationSendStep": + return json.Marshal(a.AutomationSendStep) + case "automationV2SendStep": + return json.Marshal(a.AutomationV2SendStep) + case "automationSendListStep": + return json.Marshal(a.AutomationSendListStep) + case "automationUpdateProfileStep": + return json.Marshal(a.AutomationUpdateProfileStep) + } +} + +type AutomationStepOptionVisitor interface { + VisitAutomationCancelStep(*AutomationCancelStep) error + VisitAutomationDelayStep(*AutomationDelayStep) error + VisitAutomationInvokeStep(*AutomationInvokeStep) error + VisitAutomationSendStep(*AutomationSendStep) error + VisitAutomationV2SendStep(*AutomationV2SendStep) error + VisitAutomationSendListStep(*AutomationSendListStep) error + VisitAutomationUpdateProfileStep(*AutomationUpdateProfileStep) error +} + +func (a *AutomationStepOption) Accept(visitor AutomationStepOptionVisitor) error { + switch a.typeName { + default: + return fmt.Errorf("invalid type %s in %T", a.typeName, a) + case "automationCancelStep": + return visitor.VisitAutomationCancelStep(a.AutomationCancelStep) + case "automationDelayStep": + return visitor.VisitAutomationDelayStep(a.AutomationDelayStep) + case "automationInvokeStep": + return visitor.VisitAutomationInvokeStep(a.AutomationInvokeStep) + case "automationSendStep": + return visitor.VisitAutomationSendStep(a.AutomationSendStep) + case "automationV2SendStep": + return visitor.VisitAutomationV2SendStep(a.AutomationV2SendStep) + case "automationSendListStep": + return visitor.VisitAutomationSendListStep(a.AutomationSendListStep) + case "automationUpdateProfileStep": + return visitor.VisitAutomationUpdateProfileStep(a.AutomationUpdateProfileStep) + } +} + +type AutomationUpdateProfileStep struct { + RecipientId string `json:"recipient_id"` + Profile Profile `json:"profile,omitempty"` + Merge MergeAlgorithm `json:"merge,omitempty"` + action string + + _rawJSON json.RawMessage +} + +func (a *AutomationUpdateProfileStep) Action() string { + return a.action +} + +func (a *AutomationUpdateProfileStep) UnmarshalJSON(data []byte) error { + type unmarshaler AutomationUpdateProfileStep + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AutomationUpdateProfileStep(value) + a.action = "update-profile" + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AutomationUpdateProfileStep) MarshalJSON() ([]byte, error) { + type embed AutomationUpdateProfileStep + var marshaler = struct { + embed + Action string `json:"action"` + }{ + embed: embed(*a), + Action: "update-profile", + } + return json.Marshal(marshaler) +} + +func (a *AutomationUpdateProfileStep) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AutomationV2SendStep struct { + If *string `json:"if,omitempty"` + Ref *string `json:"ref,omitempty"` + Message *Message `json:"message,omitempty"` + action string + + _rawJSON json.RawMessage +} + +func (a *AutomationV2SendStep) Action() string { + return a.action +} + +func (a *AutomationV2SendStep) UnmarshalJSON(data []byte) error { + type unmarshaler AutomationV2SendStep + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AutomationV2SendStep(value) + a.action = "send" + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AutomationV2SendStep) MarshalJSON() ([]byte, error) { + type embed AutomationV2SendStep + var marshaler = struct { + embed + Action string `json:"action"` + }{ + embed: embed(*a), + Action: "send", + } + return json.Marshal(marshaler) +} + +func (a *AutomationV2SendStep) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type MergeAlgorithm string + +const ( + MergeAlgorithmReplace MergeAlgorithm = "replace" + MergeAlgorithmNone MergeAlgorithm = "none" + MergeAlgorithmOverwrite MergeAlgorithm = "overwrite" + MergeAlgorithmSoftMerge MergeAlgorithm = "soft-merge" +) + +func NewMergeAlgorithmFromString(s string) (MergeAlgorithm, error) { + switch s { + case "replace": + return MergeAlgorithmReplace, nil + case "none": + return MergeAlgorithmNone, nil + case "overwrite": + return MergeAlgorithmOverwrite, nil + case "soft-merge": + return MergeAlgorithmSoftMerge, nil + } + var t MergeAlgorithm + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (m MergeAlgorithm) Ptr() *MergeAlgorithm { + return &m +} + +type Profile = interface{} + +type BrandColors struct { + Primary *string `json:"primary,omitempty"` + Secondary *string `json:"secondary,omitempty"` + Tertiary *string `json:"tertiary,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BrandColors) UnmarshalJSON(data []byte) error { + type unmarshaler BrandColors + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BrandColors(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BrandColors) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BrandGetAllResponse struct { + Paging *Paging `json:"paging,omitempty"` + Results []*Brand `json:"results,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BrandGetAllResponse) UnmarshalJSON(data []byte) error { + type unmarshaler BrandGetAllResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BrandGetAllResponse(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BrandGetAllResponse) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BrandSnippet struct { + Name string `json:"name"` + Value string `json:"value"` + format string + + _rawJSON json.RawMessage +} + +func (b *BrandSnippet) Format() string { + return b.format +} + +func (b *BrandSnippet) UnmarshalJSON(data []byte) error { + type unmarshaler BrandSnippet + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BrandSnippet(value) + b.format = "handlebars" + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BrandSnippet) MarshalJSON() ([]byte, error) { + type embed BrandSnippet + var marshaler = struct { + embed + Format string `json:"format"` + }{ + embed: embed(*b), + Format: "handlebars", + } + return json.Marshal(marshaler) +} + +func (b *BrandSnippet) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BulkGetJobParams struct { + JobId string `json:"jobId"` + + _rawJSON json.RawMessage +} + +func (b *BulkGetJobParams) UnmarshalJSON(data []byte) error { + type unmarshaler BulkGetJobParams + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BulkGetJobParams(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BulkGetJobParams) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BulkGetJobUsersParams struct { + JobId string `json:"jobId"` + Cursor *string `json:"cursor,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BulkGetJobUsersParams) UnmarshalJSON(data []byte) error { + type unmarshaler BulkGetJobUsersParams + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BulkGetJobUsersParams(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BulkGetJobUsersParams) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BulkIngestError struct { + User interface{} `json:"user,omitempty"` + Error interface{} `json:"error,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BulkIngestError) UnmarshalJSON(data []byte) error { + type unmarshaler BulkIngestError + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BulkIngestError(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BulkIngestError) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BulkIngestUsersResponse struct { + Total int `json:"total"` + Errors []*BulkIngestError `json:"errors,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BulkIngestUsersResponse) UnmarshalJSON(data []byte) error { + type unmarshaler BulkIngestUsersResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BulkIngestUsersResponse(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BulkIngestUsersResponse) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BulkJobStatus string + +const ( + BulkJobStatusCreated BulkJobStatus = "CREATED" + BulkJobStatusProcessing BulkJobStatus = "PROCESSING" + BulkJobStatusCompleted BulkJobStatus = "COMPLETED" + BulkJobStatusError BulkJobStatus = "ERROR" +) + +func NewBulkJobStatusFromString(s string) (BulkJobStatus, error) { + switch s { + case "CREATED": + return BulkJobStatusCreated, nil + case "PROCESSING": + return BulkJobStatusProcessing, nil + case "COMPLETED": + return BulkJobStatusCompleted, nil + case "ERROR": + return BulkJobStatusError, nil + } + var t BulkJobStatus + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (b BulkJobStatus) Ptr() *BulkJobStatus { + return &b +} + +type BulkJobUserStatus string + +const ( + BulkJobUserStatusPending BulkJobUserStatus = "PENDING" + BulkJobUserStatusEnqueued BulkJobUserStatus = "ENQUEUED" + BulkJobUserStatusError BulkJobUserStatus = "ERROR" +) + +func NewBulkJobUserStatusFromString(s string) (BulkJobUserStatus, error) { + switch s { + case "PENDING": + return BulkJobUserStatusPending, nil + case "ENQUEUED": + return BulkJobUserStatusEnqueued, nil + case "ERROR": + return BulkJobUserStatusError, nil + } + var t BulkJobUserStatus + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (b BulkJobUserStatus) Ptr() *BulkJobUserStatus { + return &b +} + +type BulkMessageUserResponse struct { + Preferences *RecipientPreferences `json:"preferences,omitempty"` + Profile interface{} `json:"profile,omitempty"` + Recipient *string `json:"recipient,omitempty"` + Data interface{} `json:"data,omitempty"` + To *UserRecipient `json:"to,omitempty"` + Status BulkJobUserStatus `json:"status,omitempty"` + MessageId *string `json:"messageId,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BulkMessageUserResponse) UnmarshalJSON(data []byte) error { + type unmarshaler BulkMessageUserResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BulkMessageUserResponse(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BulkMessageUserResponse) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +// The message property has the following primary top-level properties. They define the destination and content of the message. +// Additional advanced configuration fields [are defined below](https://www.courier.com/docs/reference/send/message/#other-message-properties). +type InboundBulkContentMessage struct { + // An arbitrary object that includes any data you want to pass to the message. + // The data will populate the corresponding template or elements variables. + Data *MessageData `json:"data,omitempty"` + BrandId *string `json:"brand_id,omitempty"` + // "Define run-time configuration for one or more channels. If you don't specify channels, the default configuration for each channel will be used. Valid ChannelId's are: email, sms, push, inbox, direct_message, banner, and webhook." + Channels *MessageChannels `json:"channels,omitempty"` + // Context to load with this recipient. Will override any context set on message.context. + Context *MessageContext `json:"context,omitempty"` + // Metadata such as utm tracking attached with the notification through this channel. + Metadata *MessageMetadata `json:"metadata,omitempty"` + // An object whose keys are valid provider identifiers which map to an object. + Providers *MessageProviders `json:"providers,omitempty"` + Routing *Routing `json:"routing,omitempty"` + // Time in ms to attempt the channel before failing over to the next available channel. + Timeout *Timeout `json:"timeout,omitempty"` + // Defines the time to wait before delivering the message. + Delay *Delay `json:"delay,omitempty"` + // "Expiry allows you to set an absolute or relative time in which a message expires. + // Note: This is only valid for the Courier Inbox channel as of 12-08-2022." + Expiry *Expiry `json:"expiry,omitempty"` + // Describes the content of the message in a way that will work for email, push, + // chat, or any channel. Either this or template must be specified. + Content *Content `json:"content,omitempty"` + + _rawJSON json.RawMessage +} + +func (i *InboundBulkContentMessage) UnmarshalJSON(data []byte) error { + type unmarshaler InboundBulkContentMessage + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *i = InboundBulkContentMessage(value) + i._rawJSON = json.RawMessage(data) + return nil +} + +func (i *InboundBulkContentMessage) String() string { + if len(i._rawJSON) > 0 { + if value, err := core.StringifyJSON(i._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(i); err == nil { + return value + } + return fmt.Sprintf("%#v", i) +} + +type InboundBulkMessageUser struct { + Preferences *RecipientPreferences `json:"preferences,omitempty"` + Profile interface{} `json:"profile,omitempty"` + Recipient *string `json:"recipient,omitempty"` + Data interface{} `json:"data,omitempty"` + To *UserRecipient `json:"to,omitempty"` + + _rawJSON json.RawMessage +} + +func (i *InboundBulkMessageUser) UnmarshalJSON(data []byte) error { + type unmarshaler InboundBulkMessageUser + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *i = InboundBulkMessageUser(value) + i._rawJSON = json.RawMessage(data) + return nil +} + +func (i *InboundBulkMessageUser) String() string { + if len(i._rawJSON) > 0 { + if value, err := core.StringifyJSON(i._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(i); err == nil { + return value + } + return fmt.Sprintf("%#v", i) +} + +type InboundBulkMessageV1 struct { + // A unique identifier that represents the brand that should be used + // for rendering the notification. + Brand *string `json:"brand,omitempty"` + // JSON that includes any data you want to pass to a message template. + // The data will populate the corresponding template variables. + Data map[string]interface{} `json:"data,omitempty"` + Event *string `json:"event,omitempty"` + Locale map[string]interface{} `json:"locale,omitempty"` + // JSON that is merged into the request sent by Courier to the provider + // to override properties or to gain access to features in the provider + // API that are not natively supported by Courier. + Override interface{} `json:"override,omitempty"` + + _rawJSON json.RawMessage +} + +func (i *InboundBulkMessageV1) UnmarshalJSON(data []byte) error { + type unmarshaler InboundBulkMessageV1 + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *i = InboundBulkMessageV1(value) + i._rawJSON = json.RawMessage(data) + return nil +} + +func (i *InboundBulkMessageV1) String() string { + if len(i._rawJSON) > 0 { + if value, err := core.StringifyJSON(i._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(i); err == nil { + return value + } + return fmt.Sprintf("%#v", i) +} + +type InboundBulkMessageV2 struct { + typeName string + // Describes the content of the message in a way that will + // work for email, push, chat, or any channel. + InboundBulkTemplateMessage *InboundBulkTemplateMessage + // A template for a type of message that can be sent more than once. + // For example, you might create an "Appointment Reminder" Notification or + // “Reset Password” Notifications. + InboundBulkContentMessage *InboundBulkContentMessage +} + +func NewInboundBulkMessageV2FromInboundBulkTemplateMessage(value *InboundBulkTemplateMessage) *InboundBulkMessageV2 { + return &InboundBulkMessageV2{typeName: "inboundBulkTemplateMessage", InboundBulkTemplateMessage: value} +} + +func NewInboundBulkMessageV2FromInboundBulkContentMessage(value *InboundBulkContentMessage) *InboundBulkMessageV2 { + return &InboundBulkMessageV2{typeName: "inboundBulkContentMessage", InboundBulkContentMessage: value} +} + +func (i *InboundBulkMessageV2) UnmarshalJSON(data []byte) error { + valueInboundBulkTemplateMessage := new(InboundBulkTemplateMessage) + if err := json.Unmarshal(data, &valueInboundBulkTemplateMessage); err == nil { + i.typeName = "inboundBulkTemplateMessage" + i.InboundBulkTemplateMessage = valueInboundBulkTemplateMessage + return nil + } + valueInboundBulkContentMessage := new(InboundBulkContentMessage) + if err := json.Unmarshal(data, &valueInboundBulkContentMessage); err == nil { + i.typeName = "inboundBulkContentMessage" + i.InboundBulkContentMessage = valueInboundBulkContentMessage + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, i) +} + +func (i InboundBulkMessageV2) MarshalJSON() ([]byte, error) { + switch i.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", i.typeName, i) + case "inboundBulkTemplateMessage": + return json.Marshal(i.InboundBulkTemplateMessage) + case "inboundBulkContentMessage": + return json.Marshal(i.InboundBulkContentMessage) + } +} + +type InboundBulkMessageV2Visitor interface { + VisitInboundBulkTemplateMessage(*InboundBulkTemplateMessage) error + VisitInboundBulkContentMessage(*InboundBulkContentMessage) error +} + +func (i *InboundBulkMessageV2) Accept(visitor InboundBulkMessageV2Visitor) error { + switch i.typeName { + default: + return fmt.Errorf("invalid type %s in %T", i.typeName, i) + case "inboundBulkTemplateMessage": + return visitor.VisitInboundBulkTemplateMessage(i.InboundBulkTemplateMessage) + case "inboundBulkContentMessage": + return visitor.VisitInboundBulkContentMessage(i.InboundBulkContentMessage) + } +} + +type InboundBulkTemplateMessage struct { + // An arbitrary object that includes any data you want to pass to the message. + // The data will populate the corresponding template or elements variables. + Data *MessageData `json:"data,omitempty"` + BrandId *string `json:"brand_id,omitempty"` + // "Define run-time configuration for one or more channels. If you don't specify channels, the default configuration for each channel will be used. Valid ChannelId's are: email, sms, push, inbox, direct_message, banner, and webhook." + Channels *MessageChannels `json:"channels,omitempty"` + // Context to load with this recipient. Will override any context set on message.context. + Context *MessageContext `json:"context,omitempty"` + // Metadata such as utm tracking attached with the notification through this channel. + Metadata *MessageMetadata `json:"metadata,omitempty"` + // An object whose keys are valid provider identifiers which map to an object. + Providers *MessageProviders `json:"providers,omitempty"` + Routing *Routing `json:"routing,omitempty"` + // Time in ms to attempt the channel before failing over to the next available channel. + Timeout *Timeout `json:"timeout,omitempty"` + // Defines the time to wait before delivering the message. + Delay *Delay `json:"delay,omitempty"` + // "Expiry allows you to set an absolute or relative time in which a message expires. + // Note: This is only valid for the Courier Inbox channel as of 12-08-2022." + Expiry *Expiry `json:"expiry,omitempty"` + // The id of the notification template to be rendered and sent to the recipient(s). + // This field or the content field must be supplied. + Template string `json:"template"` + + _rawJSON json.RawMessage +} + +func (i *InboundBulkTemplateMessage) UnmarshalJSON(data []byte) error { + type unmarshaler InboundBulkTemplateMessage + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *i = InboundBulkTemplateMessage(value) + i._rawJSON = json.RawMessage(data) + return nil +} + +func (i *InboundBulkTemplateMessage) String() string { + if len(i._rawJSON) > 0 { + if value, err := core.StringifyJSON(i._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(i); err == nil { + return value + } + return fmt.Sprintf("%#v", i) +} + +type JobDetails struct { + Definition *InboundBulkMessage `json:"definition,omitempty"` + Enqueued int `json:"enqueued"` + Failures int `json:"failures"` + Received int `json:"received"` + Status BulkJobStatus `json:"status,omitempty"` + + _rawJSON json.RawMessage +} + +func (j *JobDetails) UnmarshalJSON(data []byte) error { + type unmarshaler JobDetails + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *j = JobDetails(value) + j._rawJSON = json.RawMessage(data) + return nil +} + +func (j *JobDetails) String() string { + if len(j._rawJSON) > 0 { + if value, err := core.StringifyJSON(j._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(j); err == nil { + return value + } + return fmt.Sprintf("%#v", j) +} + +type AlreadyExists struct { + // A message describing the error that occurred. + Message string `json:"message"` + type_ string + + _rawJSON json.RawMessage +} + +func (a *AlreadyExists) Type() string { + return a.type_ +} + +func (a *AlreadyExists) UnmarshalJSON(data []byte) error { + type unmarshaler AlreadyExists + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AlreadyExists(value) + a.type_ = "invalid_request_error" + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AlreadyExists) MarshalJSON() ([]byte, error) { + type embed AlreadyExists + var marshaler = struct { + embed + Type string `json:"type"` + }{ + embed: embed(*a), + Type: "invalid_request_error", + } + return json.Marshal(marshaler) +} + +func (a *AlreadyExists) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type BadRequest struct { + // A message describing the error that occurred. + Message string `json:"message"` + type_ string + + _rawJSON json.RawMessage +} + +func (b *BadRequest) Type() string { + return b.type_ +} + +func (b *BadRequest) UnmarshalJSON(data []byte) error { + type unmarshaler BadRequest + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BadRequest(value) + b.type_ = "invalid_request_error" + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BadRequest) MarshalJSON() ([]byte, error) { + type embed BadRequest + var marshaler = struct { + embed + Type string `json:"type"` + }{ + embed: embed(*b), + Type: "invalid_request_error", + } + return json.Marshal(marshaler) +} + +func (b *BadRequest) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BaseError struct { + // A message describing the error that occurred. + Message string `json:"message"` + + _rawJSON json.RawMessage +} + +func (b *BaseError) UnmarshalJSON(data []byte) error { + type unmarshaler BaseError + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BaseError(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BaseError) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type ChannelClassification string + +const ( + ChannelClassificationDirectMessage ChannelClassification = "direct_message" + ChannelClassificationEmail ChannelClassification = "email" + ChannelClassificationPush ChannelClassification = "push" + ChannelClassificationSms ChannelClassification = "sms" + ChannelClassificationWebhook ChannelClassification = "webhook" + ChannelClassificationInbox ChannelClassification = "inbox" +) + +func NewChannelClassificationFromString(s string) (ChannelClassification, error) { + switch s { + case "direct_message": + return ChannelClassificationDirectMessage, nil + case "email": + return ChannelClassificationEmail, nil + case "push": + return ChannelClassificationPush, nil + case "sms": + return ChannelClassificationSms, nil + case "webhook": + return ChannelClassificationWebhook, nil + case "inbox": + return ChannelClassificationInbox, nil + } + var t ChannelClassification + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (c ChannelClassification) Ptr() *ChannelClassification { + return &c +} + +type ChannelPreference struct { + Channel ChannelClassification `json:"channel,omitempty"` + + _rawJSON json.RawMessage +} + +func (c *ChannelPreference) UnmarshalJSON(data []byte) error { + type unmarshaler ChannelPreference + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *c = ChannelPreference(value) + c._rawJSON = json.RawMessage(data) + return nil +} + +func (c *ChannelPreference) String() string { + if len(c._rawJSON) > 0 { + if value, err := core.StringifyJSON(c._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(c); err == nil { + return value + } + return fmt.Sprintf("%#v", c) +} + +type Conflict struct { + // A message describing the error that occurred. + Message string `json:"message"` + type_ string + + _rawJSON json.RawMessage +} + +func (c *Conflict) Type() string { + return c.type_ +} + +func (c *Conflict) UnmarshalJSON(data []byte) error { + type unmarshaler Conflict + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *c = Conflict(value) + c.type_ = "invalid_request_error" + c._rawJSON = json.RawMessage(data) + return nil +} + +func (c *Conflict) MarshalJSON() ([]byte, error) { + type embed Conflict + var marshaler = struct { + embed + Type string `json:"type"` + }{ + embed: embed(*c), + Type: "invalid_request_error", + } + return json.Marshal(marshaler) +} + +func (c *Conflict) String() string { + if len(c._rawJSON) > 0 { + if value, err := core.StringifyJSON(c._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(c); err == nil { + return value + } + return fmt.Sprintf("%#v", c) +} + +type Email struct { + Footer interface{} `json:"footer,omitempty"` + Header interface{} `json:"header,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *Email) UnmarshalJSON(data []byte) error { + type unmarshaler Email + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = Email(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *Email) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +type MessageNotFound struct { + // A message describing the error that occurred. + Message string `json:"message"` + type_ string + + _rawJSON json.RawMessage +} + +func (m *MessageNotFound) Type() string { + return m.type_ +} + +func (m *MessageNotFound) UnmarshalJSON(data []byte) error { + type unmarshaler MessageNotFound + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *m = MessageNotFound(value) + m.type_ = "invalid_request_error" + m._rawJSON = json.RawMessage(data) + return nil +} + +func (m *MessageNotFound) MarshalJSON() ([]byte, error) { + type embed MessageNotFound + var marshaler = struct { + embed + Type string `json:"type"` + }{ + embed: embed(*m), + Type: "invalid_request_error", + } + return json.Marshal(marshaler) +} + +func (m *MessageNotFound) String() string { + if len(m._rawJSON) > 0 { + if value, err := core.StringifyJSON(m._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(m); err == nil { + return value + } + return fmt.Sprintf("%#v", m) +} + +type NotFound struct { + // A message describing the error that occurred. + Message string `json:"message"` + type_ string + + _rawJSON json.RawMessage +} + +func (n *NotFound) Type() string { + return n.type_ +} + +func (n *NotFound) UnmarshalJSON(data []byte) error { + type unmarshaler NotFound + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *n = NotFound(value) + n.type_ = "invalid_request_error" + n._rawJSON = json.RawMessage(data) + return nil +} + +func (n *NotFound) MarshalJSON() ([]byte, error) { + type embed NotFound + var marshaler = struct { + embed + Type string `json:"type"` + }{ + embed: embed(*n), + Type: "invalid_request_error", + } + return json.Marshal(marshaler) +} + +func (n *NotFound) String() string { + if len(n._rawJSON) > 0 { + if value, err := core.StringifyJSON(n._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(n); err == nil { + return value + } + return fmt.Sprintf("%#v", n) +} + +type NotificationPreferenceDetails struct { + Status PreferenceStatus `json:"status,omitempty"` + Rules []*Rule `json:"rules,omitempty"` + ChannelPreferences []*ChannelPreference `json:"channel_preferences,omitempty"` + + _rawJSON json.RawMessage +} + +func (n *NotificationPreferenceDetails) UnmarshalJSON(data []byte) error { + type unmarshaler NotificationPreferenceDetails + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *n = NotificationPreferenceDetails(value) + n._rawJSON = json.RawMessage(data) + return nil +} + +func (n *NotificationPreferenceDetails) String() string { + if len(n._rawJSON) > 0 { + if value, err := core.StringifyJSON(n._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(n); err == nil { + return value + } + return fmt.Sprintf("%#v", n) +} + +type NotificationPreferences = map[string]*NotificationPreferenceDetails + +type Paging struct { + Cursor *string `json:"cursor,omitempty"` + More bool `json:"more"` + + _rawJSON json.RawMessage +} + +func (p *Paging) UnmarshalJSON(data []byte) error { + type unmarshaler Paging + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *p = Paging(value) + p._rawJSON = json.RawMessage(data) + return nil +} + +func (p *Paging) String() string { + if len(p._rawJSON) > 0 { + if value, err := core.StringifyJSON(p._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(p); err == nil { + return value + } + return fmt.Sprintf("%#v", p) +} + +type PaymentRequired struct { + // A message describing the error that occurred. + Message string `json:"message"` + type_ string + + _rawJSON json.RawMessage +} + +func (p *PaymentRequired) Type() string { + return p.type_ +} + +func (p *PaymentRequired) UnmarshalJSON(data []byte) error { + type unmarshaler PaymentRequired + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *p = PaymentRequired(value) + p.type_ = "authorization_error" + p._rawJSON = json.RawMessage(data) + return nil +} + +func (p *PaymentRequired) MarshalJSON() ([]byte, error) { + type embed PaymentRequired + var marshaler = struct { + embed + Type string `json:"type"` + }{ + embed: embed(*p), + Type: "authorization_error", + } + return json.Marshal(marshaler) +} + +func (p *PaymentRequired) String() string { + if len(p._rawJSON) > 0 { + if value, err := core.StringifyJSON(p._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(p); err == nil { + return value + } + return fmt.Sprintf("%#v", p) +} + +type PreferenceStatus string + +const ( + PreferenceStatusOptedIn PreferenceStatus = "OPTED_IN" + PreferenceStatusOptedOut PreferenceStatus = "OPTED_OUT" + PreferenceStatusRequired PreferenceStatus = "REQUIRED" +) + +func NewPreferenceStatusFromString(s string) (PreferenceStatus, error) { + switch s { + case "OPTED_IN": + return PreferenceStatusOptedIn, nil + case "OPTED_OUT": + return PreferenceStatusOptedOut, nil + case "REQUIRED": + return PreferenceStatusRequired, nil + } + var t PreferenceStatus + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (p PreferenceStatus) Ptr() *PreferenceStatus { + return &p +} + +type Rule struct { + Start *string `json:"start,omitempty"` + Until string `json:"until"` + + _rawJSON json.RawMessage +} + +func (r *Rule) UnmarshalJSON(data []byte) error { + type unmarshaler Rule + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *r = Rule(value) + r._rawJSON = json.RawMessage(data) + return nil +} + +func (r *Rule) String() string { + if len(r._rawJSON) > 0 { + if value, err := core.StringifyJSON(r._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(r); err == nil { + return value + } + return fmt.Sprintf("%#v", r) +} + +type ListFindByRecipientIdParams struct { + Cursor *string `json:"cursor,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *ListFindByRecipientIdParams) UnmarshalJSON(data []byte) error { + type unmarshaler ListFindByRecipientIdParams + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListFindByRecipientIdParams(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListFindByRecipientIdParams) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type ListFindByRecipientIdResponse struct { + Paging *Paging `json:"paging,omitempty"` + Results []*List `json:"results,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *ListFindByRecipientIdResponse) UnmarshalJSON(data []byte) error { + type unmarshaler ListFindByRecipientIdResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListFindByRecipientIdResponse(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListFindByRecipientIdResponse) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type ListGetAllParams struct { + Cursor *string `json:"cursor,omitempty"` + Pattern *string `json:"pattern,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *ListGetAllParams) UnmarshalJSON(data []byte) error { + type unmarshaler ListGetAllParams + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListGetAllParams(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListGetAllParams) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type ListGetSubscriptionsParams struct { + Cursor *string `json:"cursor,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *ListGetSubscriptionsParams) UnmarshalJSON(data []byte) error { + type unmarshaler ListGetSubscriptionsParams + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListGetSubscriptionsParams(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListGetSubscriptionsParams) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type ListSubscriptionRecipient struct { + RecipientId string `json:"recipientId"` + Created *string `json:"created,omitempty"` + Preferences *RecipientPreferences `json:"preferences,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *ListSubscriptionRecipient) UnmarshalJSON(data []byte) error { + type unmarshaler ListSubscriptionRecipient + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListSubscriptionRecipient(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListSubscriptionRecipient) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type RecipientSubscriptionsResponse struct { + Paging *Paging `json:"paging,omitempty"` + Results []*List `json:"results,omitempty"` + + _rawJSON json.RawMessage +} + +func (r *RecipientSubscriptionsResponse) UnmarshalJSON(data []byte) error { + type unmarshaler RecipientSubscriptionsResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *r = RecipientSubscriptionsResponse(value) + r._rawJSON = json.RawMessage(data) + return nil +} + +func (r *RecipientSubscriptionsResponse) String() string { + if len(r._rawJSON) > 0 { + if value, err := core.StringifyJSON(r._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(r); err == nil { + return value + } + return fmt.Sprintf("%#v", r) +} + +type MessageStatus string + +const ( + // The recipient has clicked on any link in the message at least one time. + MessageStatusClicked MessageStatus = "CLICKED" + // The provider successfully delivered the message to the recipient. + MessageStatusDelivered MessageStatus = "DELIVERED" + // The request has been received to send a message, is waiting in the work queue. + MessageStatusEnqueued MessageStatus = "ENQUEUED" + // The recipient has opened the message at least one time. + MessageStatusOpened MessageStatus = "OPENED" + // The message has been canceled such that it will not be delivered. + MessageStatusCanceled MessageStatus = "CANCELED" + // The message has been accepted by the provider. + MessageStatusSent MessageStatus = "SENT" + // The message could not be delivered to at least one provider, or the provider could not deliver the message to the recipient. This can happen for multiple reasons: an error, insufficient profile data, invalid notification setup, invalid integration configuration, etc. + MessageStatusUndeliverable MessageStatus = "UNDELIVERABLE" + // Could not find a corresponding notification or event for the messages. + MessageStatusUnmapped MessageStatus = "UNMAPPED" + // The message could not be routed to any channel or provider. This can happen for multiple reasons: insufficient profile data, invalid notification setup, invalid integration configuration, etc. + MessageStatusUnroutable MessageStatus = "UNROUTABLE" +) + +func NewMessageStatusFromString(s string) (MessageStatus, error) { + switch s { + case "CLICKED": + return MessageStatusClicked, nil + case "DELIVERED": + return MessageStatusDelivered, nil + case "ENQUEUED": + return MessageStatusEnqueued, nil + case "OPENED": + return MessageStatusOpened, nil + case "CANCELED": + return MessageStatusCanceled, nil + case "SENT": + return MessageStatusSent, nil + case "UNDELIVERABLE": + return MessageStatusUndeliverable, nil + case "UNMAPPED": + return MessageStatusUnmapped, nil + case "UNROUTABLE": + return MessageStatusUnroutable, nil + } + var t MessageStatus + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (m MessageStatus) Ptr() *MessageStatus { + return &m +} + +type Reason string + +const ( + // The recipient did not receive the notification because of a condition that passed. + ReasonFiltered Reason = "FILTERED" + // The notification did not contain any valid channels. + ReasonNoChannels Reason = "NO_CHANNELS" + // The notification did not contain a configured provider for a channel. + ReasonNoProviders Reason = "NO_PROVIDERS" + // The Integration provider had an error when sending a notification. + ReasonProviderError Reason = "PROVIDER_ERROR" + // The notification hasn't been published yet. + ReasonUnpublished Reason = "UNPUBLISHED" + // The recipient did not receive the notification because they chose to unsubscribe from it. + ReasonUnsubscribed Reason = "UNSUBSCRIBED" +) + +func NewReasonFromString(s string) (Reason, error) { + switch s { + case "FILTERED": + return ReasonFiltered, nil + case "NO_CHANNELS": + return ReasonNoChannels, nil + case "NO_PROVIDERS": + return ReasonNoProviders, nil + case "PROVIDER_ERROR": + return ReasonProviderError, nil + case "UNPUBLISHED": + return ReasonUnpublished, nil + case "UNSUBSCRIBED": + return ReasonUnsubscribed, nil + } + var t Reason + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (r Reason) Ptr() *Reason { + return &r +} + +type RenderOutput struct { + // The channel used for rendering the message. + Channel string `json:"channel"` + // The ID of channel used for rendering the message. + ChannelId string `json:"channel_id"` + // Content details of the rendered message. + Content *RenderedMessageContent `json:"content,omitempty"` + + _rawJSON json.RawMessage +} + +func (r *RenderOutput) UnmarshalJSON(data []byte) error { + type unmarshaler RenderOutput + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *r = RenderOutput(value) + r._rawJSON = json.RawMessage(data) + return nil +} + +func (r *RenderOutput) String() string { + if len(r._rawJSON) > 0 { + if value, err := core.StringifyJSON(r._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(r); err == nil { + return value + } + return fmt.Sprintf("%#v", r) +} + +type RenderedMessageBlock struct { + // The block type of the rendered message block. + Type string `json:"type"` + // The block text of the rendered message block. + Text string `json:"text"` + + _rawJSON json.RawMessage +} + +func (r *RenderedMessageBlock) UnmarshalJSON(data []byte) error { + type unmarshaler RenderedMessageBlock + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *r = RenderedMessageBlock(value) + r._rawJSON = json.RawMessage(data) + return nil +} + +func (r *RenderedMessageBlock) String() string { + if len(r._rawJSON) > 0 { + if value, err := core.StringifyJSON(r._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(r); err == nil { + return value + } + return fmt.Sprintf("%#v", r) +} + +type RenderedMessageContent struct { + // The html content of the rendered message. + Html string `json:"html"` + // The title of the rendered message. + Title string `json:"title"` + // The body of the rendered message. + Body string `json:"body"` + // The subject of the rendered message. + Subject string `json:"subject"` + // The text of the rendered message. + Text string `json:"text"` + // The blocks of the rendered message. + Blocks []*RenderedMessageBlock `json:"blocks,omitempty"` + + _rawJSON json.RawMessage +} + +func (r *RenderedMessageContent) UnmarshalJSON(data []byte) error { + type unmarshaler RenderedMessageContent + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *r = RenderedMessageContent(value) + r._rawJSON = json.RawMessage(data) + return nil +} + +func (r *RenderedMessageContent) String() string { + if len(r._rawJSON) > 0 { + if value, err := core.StringifyJSON(r._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(r); err == nil { + return value + } + return fmt.Sprintf("%#v", r) +} + +type BlockType string + +const ( + BlockTypeAction BlockType = "action" + BlockTypeDivider BlockType = "divider" + BlockTypeImage BlockType = "image" + BlockTypeJsonnet BlockType = "jsonnet" + BlockTypeList BlockType = "list" + BlockTypeMarkdown BlockType = "markdown" + BlockTypeQuote BlockType = "quote" + BlockTypeTemplate BlockType = "template" + BlockTypeText BlockType = "text" +) + +func NewBlockTypeFromString(s string) (BlockType, error) { + switch s { + case "action": + return BlockTypeAction, nil + case "divider": + return BlockTypeDivider, nil + case "image": + return BlockTypeImage, nil + case "jsonnet": + return BlockTypeJsonnet, nil + case "list": + return BlockTypeList, nil + case "markdown": + return BlockTypeMarkdown, nil + case "quote": + return BlockTypeQuote, nil + case "template": + return BlockTypeTemplate, nil + case "text": + return BlockTypeText, nil + } + var t BlockType + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (b BlockType) Ptr() *BlockType { + return &b +} + +type Check struct { + Id string `json:"id"` + Status CheckStatus `json:"status,omitempty"` + Updated int64 `json:"updated"` + type_ string + + _rawJSON json.RawMessage +} + +func (c *Check) Type() string { + return c.type_ +} + +func (c *Check) UnmarshalJSON(data []byte) error { + type unmarshaler Check + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *c = Check(value) + c.type_ = "custom" + c._rawJSON = json.RawMessage(data) + return nil +} + +func (c *Check) MarshalJSON() ([]byte, error) { + type embed Check + var marshaler = struct { + embed + Type string `json:"type"` + }{ + embed: embed(*c), + Type: "custom", + } + return json.Marshal(marshaler) +} + +func (c *Check) String() string { + if len(c._rawJSON) > 0 { + if value, err := core.StringifyJSON(c._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(c); err == nil { + return value + } + return fmt.Sprintf("%#v", c) +} + +type CheckStatus string + +const ( + CheckStatusResolved CheckStatus = "RESOLVED" + CheckStatusFailed CheckStatus = "FAILED" + CheckStatusPending CheckStatus = "PENDING" +) + +func NewCheckStatusFromString(s string) (CheckStatus, error) { + switch s { + case "RESOLVED": + return CheckStatusResolved, nil + case "FAILED": + return CheckStatusFailed, nil + case "PENDING": + return CheckStatusPending, nil + } + var t CheckStatus + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (c CheckStatus) Ptr() *CheckStatus { + return &c +} + +type MessageRouting struct { + Method MessageRoutingMethod `json:"method,omitempty"` + Channels []*MessageRoutingChannel `json:"channels,omitempty"` + + _rawJSON json.RawMessage +} + +func (m *MessageRouting) UnmarshalJSON(data []byte) error { + type unmarshaler MessageRouting + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *m = MessageRouting(value) + m._rawJSON = json.RawMessage(data) + return nil +} + +func (m *MessageRouting) String() string { + if len(m._rawJSON) > 0 { + if value, err := core.StringifyJSON(m._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(m); err == nil { + return value + } + return fmt.Sprintf("%#v", m) +} + +type MessageRoutingChannel struct { + typeName string + String string + MessageRouting *MessageRouting +} + +func NewMessageRoutingChannelFromString(value string) *MessageRoutingChannel { + return &MessageRoutingChannel{typeName: "string", String: value} +} + +func NewMessageRoutingChannelFromMessageRouting(value *MessageRouting) *MessageRoutingChannel { + return &MessageRoutingChannel{typeName: "messageRouting", MessageRouting: value} +} + +func (m *MessageRoutingChannel) UnmarshalJSON(data []byte) error { + var valueString string + if err := json.Unmarshal(data, &valueString); err == nil { + m.typeName = "string" + m.String = valueString + return nil + } + valueMessageRouting := new(MessageRouting) + if err := json.Unmarshal(data, &valueMessageRouting); err == nil { + m.typeName = "messageRouting" + m.MessageRouting = valueMessageRouting + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, m) +} + +func (m MessageRoutingChannel) MarshalJSON() ([]byte, error) { + switch m.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", m.typeName, m) + case "string": + return json.Marshal(m.String) + case "messageRouting": + return json.Marshal(m.MessageRouting) + } +} + +type MessageRoutingChannelVisitor interface { + VisitString(string) error + VisitMessageRouting(*MessageRouting) error +} + +func (m *MessageRoutingChannel) Accept(visitor MessageRoutingChannelVisitor) error { + switch m.typeName { + default: + return fmt.Errorf("invalid type %s in %T", m.typeName, m) + case "string": + return visitor.VisitString(m.String) + case "messageRouting": + return visitor.VisitMessageRouting(m.MessageRouting) + } +} + +type MessageRoutingMethod string + +const ( + MessageRoutingMethodAll MessageRoutingMethod = "all" + MessageRoutingMethodSingle MessageRoutingMethod = "single" +) + +func NewMessageRoutingMethodFromString(s string) (MessageRoutingMethod, error) { + switch s { + case "all": + return MessageRoutingMethodAll, nil + case "single": + return MessageRoutingMethodSingle, nil + } + var t MessageRoutingMethod + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (m MessageRoutingMethod) Ptr() *MessageRoutingMethod { + return &m +} + +type Notification struct { + CreatedAt int64 `json:"created_at"` + Id string `json:"id"` + Routing *MessageRouting `json:"routing,omitempty"` + + _rawJSON json.RawMessage +} + +func (n *Notification) UnmarshalJSON(data []byte) error { + type unmarshaler Notification + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *n = Notification(value) + n._rawJSON = json.RawMessage(data) + return nil +} + +func (n *Notification) String() string { + if len(n._rawJSON) > 0 { + if value, err := core.StringifyJSON(n._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(n); err == nil { + return value + } + return fmt.Sprintf("%#v", n) +} + +type NotificationChannelContent struct { + Subject *string `json:"subject,omitempty"` + Title *string `json:"title,omitempty"` + + _rawJSON json.RawMessage +} + +func (n *NotificationChannelContent) UnmarshalJSON(data []byte) error { + type unmarshaler NotificationChannelContent + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *n = NotificationChannelContent(value) + n._rawJSON = json.RawMessage(data) + return nil +} + +func (n *NotificationChannelContent) String() string { + if len(n._rawJSON) > 0 { + if value, err := core.StringifyJSON(n._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(n); err == nil { + return value + } + return fmt.Sprintf("%#v", n) +} + +type NotificationContent struct { + typeName string + String string + NotificationContentHierarchy *NotificationContentHierarchy +} + +func NewNotificationContentFromString(value string) *NotificationContent { + return &NotificationContent{typeName: "string", String: value} +} + +func NewNotificationContentFromNotificationContentHierarchy(value *NotificationContentHierarchy) *NotificationContent { + return &NotificationContent{typeName: "notificationContentHierarchy", NotificationContentHierarchy: value} +} + +func (n *NotificationContent) UnmarshalJSON(data []byte) error { + var valueString string + if err := json.Unmarshal(data, &valueString); err == nil { + n.typeName = "string" + n.String = valueString + return nil + } + valueNotificationContentHierarchy := new(NotificationContentHierarchy) + if err := json.Unmarshal(data, &valueNotificationContentHierarchy); err == nil { + n.typeName = "notificationContentHierarchy" + n.NotificationContentHierarchy = valueNotificationContentHierarchy + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, n) +} + +func (n NotificationContent) MarshalJSON() ([]byte, error) { + switch n.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", n.typeName, n) + case "string": + return json.Marshal(n.String) + case "notificationContentHierarchy": + return json.Marshal(n.NotificationContentHierarchy) + } +} + +type NotificationContentVisitor interface { + VisitString(string) error + VisitNotificationContentHierarchy(*NotificationContentHierarchy) error +} + +func (n *NotificationContent) Accept(visitor NotificationContentVisitor) error { + switch n.typeName { + default: + return fmt.Errorf("invalid type %s in %T", n.typeName, n) + case "string": + return visitor.VisitString(n.String) + case "notificationContentHierarchy": + return visitor.VisitNotificationContentHierarchy(n.NotificationContentHierarchy) + } +} + +type NotificationContentHierarchy struct { + Parent *string `json:"parent,omitempty"` + Children *string `json:"children,omitempty"` + + _rawJSON json.RawMessage +} + +func (n *NotificationContentHierarchy) UnmarshalJSON(data []byte) error { + type unmarshaler NotificationContentHierarchy + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *n = NotificationContentHierarchy(value) + n._rawJSON = json.RawMessage(data) + return nil +} + +func (n *NotificationContentHierarchy) String() string { + if len(n._rawJSON) > 0 { + if value, err := core.StringifyJSON(n._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(n); err == nil { + return value + } + return fmt.Sprintf("%#v", n) +} + +type Address struct { + Formatted string `json:"formatted"` + StreetAddress string `json:"street_address"` + Locality string `json:"locality"` + Region string `json:"region"` + PostalCode string `json:"postal_code"` + Country string `json:"country"` + + _rawJSON json.RawMessage +} + +func (a *Address) UnmarshalJSON(data []byte) error { + type unmarshaler Address + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = Address(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *Address) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AirshipProfile struct { + Audience *AirshipProfileAudience `json:"audience,omitempty"` + DeviceTypes []DeviceType `json:"device_types,omitempty"` + + _rawJSON json.RawMessage +} + +func (a *AirshipProfile) UnmarshalJSON(data []byte) error { + type unmarshaler AirshipProfile + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AirshipProfile(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AirshipProfile) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AirshipProfileAudience struct { + NamedUser string `json:"named_user"` + + _rawJSON json.RawMessage +} + +func (a *AirshipProfileAudience) UnmarshalJSON(data []byte) error { + type unmarshaler AirshipProfileAudience + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AirshipProfileAudience(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AirshipProfileAudience) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type DeviceType = interface{} + +type Discord struct { + typeName string + SendToChannel *SendToChannel + SendDirectMessage *SendDirectMessage +} + +func NewDiscordFromSendToChannel(value *SendToChannel) *Discord { + return &Discord{typeName: "sendToChannel", SendToChannel: value} +} + +func NewDiscordFromSendDirectMessage(value *SendDirectMessage) *Discord { + return &Discord{typeName: "sendDirectMessage", SendDirectMessage: value} +} + +func (d *Discord) UnmarshalJSON(data []byte) error { + valueSendToChannel := new(SendToChannel) + if err := json.Unmarshal(data, &valueSendToChannel); err == nil { + d.typeName = "sendToChannel" + d.SendToChannel = valueSendToChannel + return nil + } + valueSendDirectMessage := new(SendDirectMessage) + if err := json.Unmarshal(data, &valueSendDirectMessage); err == nil { + d.typeName = "sendDirectMessage" + d.SendDirectMessage = valueSendDirectMessage + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, d) +} + +func (d Discord) MarshalJSON() ([]byte, error) { + switch d.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", d.typeName, d) + case "sendToChannel": + return json.Marshal(d.SendToChannel) + case "sendDirectMessage": + return json.Marshal(d.SendDirectMessage) + } +} + +type DiscordVisitor interface { + VisitSendToChannel(*SendToChannel) error + VisitSendDirectMessage(*SendDirectMessage) error +} + +func (d *Discord) Accept(visitor DiscordVisitor) error { + switch d.typeName { + default: + return fmt.Errorf("invalid type %s in %T", d.typeName, d) + case "sendToChannel": + return visitor.VisitSendToChannel(d.SendToChannel) + case "sendDirectMessage": + return visitor.VisitSendDirectMessage(d.SendDirectMessage) + } +} + +type Expo struct { + typeName string + Token *Token + MultipleTokens *MultipleTokens +} + +func NewExpoFromToken(value *Token) *Expo { + return &Expo{typeName: "token", Token: value} +} + +func NewExpoFromMultipleTokens(value *MultipleTokens) *Expo { + return &Expo{typeName: "multipleTokens", MultipleTokens: value} +} + +func (e *Expo) UnmarshalJSON(data []byte) error { + valueToken := new(Token) + if err := json.Unmarshal(data, &valueToken); err == nil { + e.typeName = "token" + e.Token = valueToken + return nil + } + valueMultipleTokens := new(MultipleTokens) + if err := json.Unmarshal(data, &valueMultipleTokens); err == nil { + e.typeName = "multipleTokens" + e.MultipleTokens = valueMultipleTokens + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, e) +} + +func (e Expo) MarshalJSON() ([]byte, error) { + switch e.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", e.typeName, e) + case "token": + return json.Marshal(e.Token) + case "multipleTokens": + return json.Marshal(e.MultipleTokens) + } +} + +type ExpoVisitor interface { + VisitToken(*Token) error + VisitMultipleTokens(*MultipleTokens) error +} + +func (e *Expo) Accept(visitor ExpoVisitor) error { + switch e.typeName { + default: + return fmt.Errorf("invalid type %s in %T", e.typeName, e) + case "token": + return visitor.VisitToken(e.Token) + case "multipleTokens": + return visitor.VisitMultipleTokens(e.MultipleTokens) + } +} + +type GetListSubscriptionsList struct { + Id string `json:"id"` + // List name + Name string `json:"name"` + // The date/time of when the list was created. Represented as a string in ISO format. + Created string `json:"created"` + // The date/time of when the list was updated. Represented as a string in ISO format. + Updated string `json:"updated"` + Preferences *RecipientPreferences `json:"preferences,omitempty"` + + _rawJSON json.RawMessage +} + +func (g *GetListSubscriptionsList) UnmarshalJSON(data []byte) error { + type unmarshaler GetListSubscriptionsList + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *g = GetListSubscriptionsList(value) + g._rawJSON = json.RawMessage(data) + return nil +} + +func (g *GetListSubscriptionsList) String() string { + if len(g._rawJSON) > 0 { + if value, err := core.StringifyJSON(g._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(g); err == nil { + return value + } + return fmt.Sprintf("%#v", g) +} + +type Intercom struct { + From string `json:"from"` + To *IntercomeRecipient `json:"to,omitempty"` + + _rawJSON json.RawMessage +} + +func (i *Intercom) UnmarshalJSON(data []byte) error { + type unmarshaler Intercom + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *i = Intercom(value) + i._rawJSON = json.RawMessage(data) + return nil +} + +func (i *Intercom) String() string { + if len(i._rawJSON) > 0 { + if value, err := core.StringifyJSON(i._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(i); err == nil { + return value + } + return fmt.Sprintf("%#v", i) +} + +type IntercomeRecipient struct { + Id string `json:"id"` + + _rawJSON json.RawMessage +} + +func (i *IntercomeRecipient) UnmarshalJSON(data []byte) error { + type unmarshaler IntercomeRecipient + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *i = IntercomeRecipient(value) + i._rawJSON = json.RawMessage(data) + return nil +} + +func (i *IntercomeRecipient) String() string { + if len(i._rawJSON) > 0 { + if value, err := core.StringifyJSON(i._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(i); err == nil { + return value + } + return fmt.Sprintf("%#v", i) +} + +type MsTeams struct { + typeName string + SendToMsTeamsChannel *SendToMsTeamsChannel + SendToMsTeamsUser *SendToMsTeamsUser +} + +func NewMsTeamsFromSendToMsTeamsChannel(value *SendToMsTeamsChannel) *MsTeams { + return &MsTeams{typeName: "sendToMsTeamsChannel", SendToMsTeamsChannel: value} +} + +func NewMsTeamsFromSendToMsTeamsUser(value *SendToMsTeamsUser) *MsTeams { + return &MsTeams{typeName: "sendToMsTeamsUser", SendToMsTeamsUser: value} +} + +func (m *MsTeams) UnmarshalJSON(data []byte) error { + valueSendToMsTeamsChannel := new(SendToMsTeamsChannel) + if err := json.Unmarshal(data, &valueSendToMsTeamsChannel); err == nil { + m.typeName = "sendToMsTeamsChannel" + m.SendToMsTeamsChannel = valueSendToMsTeamsChannel + return nil + } + valueSendToMsTeamsUser := new(SendToMsTeamsUser) + if err := json.Unmarshal(data, &valueSendToMsTeamsUser); err == nil { + m.typeName = "sendToMsTeamsUser" + m.SendToMsTeamsUser = valueSendToMsTeamsUser + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, m) +} + +func (m MsTeams) MarshalJSON() ([]byte, error) { + switch m.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", m.typeName, m) + case "sendToMsTeamsChannel": + return json.Marshal(m.SendToMsTeamsChannel) + case "sendToMsTeamsUser": + return json.Marshal(m.SendToMsTeamsUser) + } +} + +type MsTeamsVisitor interface { + VisitSendToMsTeamsChannel(*SendToMsTeamsChannel) error + VisitSendToMsTeamsUser(*SendToMsTeamsUser) error +} + +func (m *MsTeams) Accept(visitor MsTeamsVisitor) error { + switch m.typeName { + default: + return fmt.Errorf("invalid type %s in %T", m.typeName, m) + case "sendToMsTeamsChannel": + return visitor.VisitSendToMsTeamsChannel(m.SendToMsTeamsChannel) + case "sendToMsTeamsUser": + return visitor.VisitSendToMsTeamsUser(m.SendToMsTeamsUser) + } +} + +type MultipleTokens struct { + Tokens []*Token `json:"tokens,omitempty"` + + _rawJSON json.RawMessage +} + +func (m *MultipleTokens) UnmarshalJSON(data []byte) error { + type unmarshaler MultipleTokens + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *m = MultipleTokens(value) + m._rawJSON = json.RawMessage(data) + return nil +} + +func (m *MultipleTokens) String() string { + if len(m._rawJSON) > 0 { + if value, err := core.StringifyJSON(m._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(m); err == nil { + return value + } + return fmt.Sprintf("%#v", m) +} + +type ProfileGetParameters struct { + RecipientId string `json:"recipientId"` + + _rawJSON json.RawMessage +} + +func (p *ProfileGetParameters) UnmarshalJSON(data []byte) error { + type unmarshaler ProfileGetParameters + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *p = ProfileGetParameters(value) + p._rawJSON = json.RawMessage(data) + return nil +} + +func (p *ProfileGetParameters) String() string { + if len(p._rawJSON) > 0 { + if value, err := core.StringifyJSON(p._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(p); err == nil { + return value + } + return fmt.Sprintf("%#v", p) +} + +type SendDirectMessage struct { + UserId string `json:"user_id"` + + _rawJSON json.RawMessage +} + +func (s *SendDirectMessage) UnmarshalJSON(data []byte) error { + type unmarshaler SendDirectMessage + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *s = SendDirectMessage(value) + s._rawJSON = json.RawMessage(data) + return nil +} + +func (s *SendDirectMessage) String() string { + if len(s._rawJSON) > 0 { + if value, err := core.StringifyJSON(s._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(s); err == nil { + return value + } + return fmt.Sprintf("%#v", s) +} + +type SendToChannel struct { + ChannelId string `json:"channel_id"` + + _rawJSON json.RawMessage +} + +func (s *SendToChannel) UnmarshalJSON(data []byte) error { + type unmarshaler SendToChannel + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *s = SendToChannel(value) + s._rawJSON = json.RawMessage(data) + return nil +} + +func (s *SendToChannel) String() string { + if len(s._rawJSON) > 0 { + if value, err := core.StringifyJSON(s._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(s); err == nil { + return value + } + return fmt.Sprintf("%#v", s) +} + +type SendToMsTeamsChannel struct { + ConversationId string `json:"conversation_id"` + TenantId string `json:"tenant_id"` + ServiceUrl string `json:"service_url"` + + _rawJSON json.RawMessage +} + +func (s *SendToMsTeamsChannel) UnmarshalJSON(data []byte) error { + type unmarshaler SendToMsTeamsChannel + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *s = SendToMsTeamsChannel(value) + s._rawJSON = json.RawMessage(data) + return nil +} + +func (s *SendToMsTeamsChannel) String() string { + if len(s._rawJSON) > 0 { + if value, err := core.StringifyJSON(s._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(s); err == nil { + return value + } + return fmt.Sprintf("%#v", s) +} + +type SendToMsTeamsUser struct { + UserId string `json:"user_id"` + TenantId string `json:"tenant_id"` + ServiceUrl string `json:"service_url"` + + _rawJSON json.RawMessage +} + +func (s *SendToMsTeamsUser) UnmarshalJSON(data []byte) error { + type unmarshaler SendToMsTeamsUser + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *s = SendToMsTeamsUser(value) + s._rawJSON = json.RawMessage(data) + return nil +} + +func (s *SendToMsTeamsUser) String() string { + if len(s._rawJSON) > 0 { + if value, err := core.StringifyJSON(s._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(s); err == nil { + return value + } + return fmt.Sprintf("%#v", s) +} + +type SnoozeRule struct { + Type SnoozeRuleType `json:"type,omitempty"` + Start string `json:"start"` + Until string `json:"until"` + + _rawJSON json.RawMessage +} + +func (s *SnoozeRule) UnmarshalJSON(data []byte) error { + type unmarshaler SnoozeRule + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *s = SnoozeRule(value) + s._rawJSON = json.RawMessage(data) + return nil +} + +func (s *SnoozeRule) String() string { + if len(s._rawJSON) > 0 { + if value, err := core.StringifyJSON(s._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(s); err == nil { + return value + } + return fmt.Sprintf("%#v", s) +} + +type SnoozeRuleType string + +const ( + SnoozeRuleTypeSnooze SnoozeRuleType = "snooze" +) + +func NewSnoozeRuleTypeFromString(s string) (SnoozeRuleType, error) { + switch s { + case "snooze": + return SnoozeRuleTypeSnooze, nil + } + var t SnoozeRuleType + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (s SnoozeRuleType) Ptr() *SnoozeRuleType { + return &s +} + +type SubscribeToListsRequestListObject struct { + ListId string `json:"listId"` + Preferences *RecipientPreferences `json:"preferences,omitempty"` + + _rawJSON json.RawMessage +} + +func (s *SubscribeToListsRequestListObject) UnmarshalJSON(data []byte) error { + type unmarshaler SubscribeToListsRequestListObject + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *s = SubscribeToListsRequestListObject(value) + s._rawJSON = json.RawMessage(data) + return nil +} + +func (s *SubscribeToListsRequestListObject) String() string { + if len(s._rawJSON) > 0 { + if value, err := core.StringifyJSON(s._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(s); err == nil { + return value + } + return fmt.Sprintf("%#v", s) +} + +type Token struct { + Token string `json:"token"` + + _rawJSON json.RawMessage +} + +func (t *Token) UnmarshalJSON(data []byte) error { + type unmarshaler Token + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *t = Token(value) + t._rawJSON = json.RawMessage(data) + return nil +} + +func (t *Token) String() string { + if len(t._rawJSON) > 0 { + if value, err := core.StringifyJSON(t._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(t); err == nil { + return value + } + return fmt.Sprintf("%#v", t) +} + +type UserProfile struct { + Address *Address `json:"address,omitempty"` + Birthdate string `json:"birthdate"` + Email string `json:"email"` + EmailVerified bool `json:"email_verified"` + FamilyName string `json:"family_name"` + Gender string `json:"gender"` + GivenName string `json:"given_name"` + Locale string `json:"locale"` + MiddleName string `json:"middle_name"` + Name string `json:"name"` + Nickname string `json:"nickname"` + PhoneNumber string `json:"phone_number"` + PhoneNumberVerified bool `json:"phone_number_verified"` + Picture string `json:"picture"` + PreferredName string `json:"preferred_name"` + Profile string `json:"profile"` + Sub string `json:"sub"` + UpdatedAt string `json:"updated_at"` + Website string `json:"website"` + Zoneinfo string `json:"zoneinfo"` + // A free form object. Due to a limitation of the API Explorer, you can only enter string key/values below, but this API accepts more complex object structures. + Custom interface{} `json:"custom,omitempty"` + Airship *AirshipProfile `json:"airship,omitempty"` + Apn string `json:"apn"` + TargetArn string `json:"target_arn"` + Discord *Discord `json:"discord,omitempty"` + Expo *Expo `json:"expo,omitempty"` + FacebookPsid string `json:"facebookPSID"` + FirebaseToken string `json:"firebaseToken"` + Intercom *Intercom `json:"intercom,omitempty"` + MsTeams *MsTeams `json:"ms_teams,omitempty"` + + _rawJSON json.RawMessage +} + +func (u *UserProfile) UnmarshalJSON(data []byte) error { + type unmarshaler UserProfile + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *u = UserProfile(value) + u._rawJSON = json.RawMessage(data) + return nil +} + +func (u *UserProfile) String() string { + if len(u._rawJSON) > 0 { + if value, err := core.StringifyJSON(u._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(u); err == nil { + return value + } + return fmt.Sprintf("%#v", u) +} + +type Attachment = map[string]interface{} + +type AudienceFilter struct { + // Send to users only if they are member of the account + Value string `json:"value"` + operator string + path string + + _rawJSON json.RawMessage +} + +func (a *AudienceFilter) Operator() string { + return a.operator +} + +func (a *AudienceFilter) Path() string { + return a.path +} + +func (a *AudienceFilter) UnmarshalJSON(data []byte) error { + type unmarshaler AudienceFilter + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AudienceFilter(value) + a.operator = "MEMBER_OF" + a.path = "account_id" + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AudienceFilter) MarshalJSON() ([]byte, error) { + type embed AudienceFilter + var marshaler = struct { + embed + Operator string `json:"operator"` + Path string `json:"path"` + }{ + embed: embed(*a), + Operator: "MEMBER_OF", + Path: "account_id", + } + return json.Marshal(marshaler) +} + +func (a *AudienceFilter) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type AudienceRecipient struct { + // A unique identifier associated with an Audience. A message will be sent to each user in the audience. + AudienceId string `json:"audience_id"` + Data *MessageData `json:"data,omitempty"` + Filters []*AudienceFilter `json:"filters,omitempty"` + + _rawJSON json.RawMessage +} + +func (a *AudienceRecipient) UnmarshalJSON(data []byte) error { + type unmarshaler AudienceRecipient + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AudienceRecipient(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AudienceRecipient) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type BaseMessage struct { + // An arbitrary object that includes any data you want to pass to the message. + // The data will populate the corresponding template or elements variables. + Data *MessageData `json:"data,omitempty"` + BrandId *string `json:"brand_id,omitempty"` + // "Define run-time configuration for one or more channels. If you don't specify channels, the default configuration for each channel will be used. Valid ChannelId's are: email, sms, push, inbox, direct_message, banner, and webhook." + Channels *MessageChannels `json:"channels,omitempty"` + // Context to load with this recipient. Will override any context set on message.context. + Context *MessageContext `json:"context,omitempty"` + // Metadata such as utm tracking attached with the notification through this channel. + Metadata *MessageMetadata `json:"metadata,omitempty"` + // An object whose keys are valid provider identifiers which map to an object. + Providers *MessageProviders `json:"providers,omitempty"` + Routing *Routing `json:"routing,omitempty"` + // Time in ms to attempt the channel before failing over to the next available channel. + Timeout *Timeout `json:"timeout,omitempty"` + // Defines the time to wait before delivering the message. + Delay *Delay `json:"delay,omitempty"` + // "Expiry allows you to set an absolute or relative time in which a message expires. + // Note: This is only valid for the Courier Inbox channel as of 12-08-2022." + Expiry *Expiry `json:"expiry,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BaseMessage) UnmarshalJSON(data []byte) error { + type unmarshaler BaseMessage + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BaseMessage(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BaseMessage) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BaseSocialPresence struct { + Url string `json:"url"` + + _rawJSON json.RawMessage +} + +func (b *BaseSocialPresence) UnmarshalJSON(data []byte) error { + type unmarshaler BaseSocialPresence + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BaseSocialPresence(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BaseSocialPresence) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BrandSettingsEmail struct { + TemplateOverride *BrandTemplateOverride `json:"templateOverride,omitempty"` + Head *EmailHead `json:"head,omitempty"` + Footer *EmailFooter `json:"footer,omitempty"` + Header *EmailHeader `json:"header,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BrandSettingsEmail) UnmarshalJSON(data []byte) error { + type unmarshaler BrandSettingsEmail + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BrandSettingsEmail(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BrandSettingsEmail) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BrandSettingsInApp struct { + BorderRadius *string `json:"borderRadius,omitempty"` + DisableMessageIcon *bool `json:"disableMessageIcon,omitempty"` + FontFamily *string `json:"fontFamily,omitempty"` + Placement *InAppPlacement `json:"placement,omitempty"` + WidgetBackground *WidgetBackground `json:"widgetBackground,omitempty"` + Colors *BrandColors `json:"colors,omitempty"` + Icons *Icons `json:"icons,omitempty"` + Preferences *Preferences `json:"preferences,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BrandSettingsInApp) UnmarshalJSON(data []byte) error { + type unmarshaler BrandSettingsInApp + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BrandSettingsInApp(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BrandSettingsInApp) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BrandSettingsSocialPresence struct { + InheritDefault *bool `json:"inheritDefault,omitempty"` + Facebook *BaseSocialPresence `json:"facebook,omitempty"` + Instagram *BaseSocialPresence `json:"instagram,omitempty"` + Linkedin *BaseSocialPresence `json:"linkedin,omitempty"` + Medium *BaseSocialPresence `json:"medium,omitempty"` + Twitter *BaseSocialPresence `json:"twitter,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BrandSettingsSocialPresence) UnmarshalJSON(data []byte) error { + type unmarshaler BrandSettingsSocialPresence + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BrandSettingsSocialPresence(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BrandSettingsSocialPresence) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BrandTemplate struct { + BackgroundColor *string `json:"backgroundColor,omitempty"` + BlocksBackgroundColor *string `json:"blocksBackgroundColor,omitempty"` + Enabled bool `json:"enabled"` + Footer *string `json:"footer,omitempty"` + Head *string `json:"head,omitempty"` + Header *string `json:"header,omitempty"` + Width *string `json:"width,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BrandTemplate) UnmarshalJSON(data []byte) error { + type unmarshaler BrandTemplate + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BrandTemplate(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BrandTemplate) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type BrandTemplateOverride struct { + BackgroundColor *string `json:"backgroundColor,omitempty"` + BlocksBackgroundColor *string `json:"blocksBackgroundColor,omitempty"` + Enabled bool `json:"enabled"` + Footer *string `json:"footer,omitempty"` + Head *string `json:"head,omitempty"` + Header *string `json:"header,omitempty"` + Width *string `json:"width,omitempty"` + Mjml *BrandTemplate `json:"mjml,omitempty"` + FooterBackgroundColor *string `json:"footerBackgroundColor,omitempty"` + FooterFullWidth *bool `json:"footerFullWidth,omitempty"` + + _rawJSON json.RawMessage +} + +func (b *BrandTemplateOverride) UnmarshalJSON(data []byte) error { + type unmarshaler BrandTemplateOverride + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *b = BrandTemplateOverride(value) + b._rawJSON = json.RawMessage(data) + return nil +} + +func (b *BrandTemplateOverride) String() string { + if len(b._rawJSON) > 0 { + if value, err := core.StringifyJSON(b._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(b); err == nil { + return value + } + return fmt.Sprintf("%#v", b) +} + +type Channel struct { + // Id of the brand that should be used for rendering the message. + // If not specified, the brand configured as default brand will be used. + BrandId *string `json:"brand_id,omitempty"` + // A list of providers enabled for this channel. Courier will select + // one provider to send through unless routing_method is set to all. + Providers []string `json:"providers,omitempty"` + // The method for selecting the providers to send the message with. + // Single will send to one of the available providers for this channel, + // all will send the message through all channels. Defaults to `single`. + RoutingMethod *RoutingMethod `json:"routing_method,omitempty"` + // A JavaScript conditional expression to determine if the message should + // be sent through the channel. Has access to the data and profile object. + // For example, `data.name === profile.name` + If *string `json:"if,omitempty"` + Timeouts *Timeouts `json:"timeouts,omitempty"` + // Channel specific overrides. + Override *Override `json:"override,omitempty"` + Metadata *ChannelMetadata `json:"metadata,omitempty"` + + _rawJSON json.RawMessage +} + +func (c *Channel) UnmarshalJSON(data []byte) error { + type unmarshaler Channel + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *c = Channel(value) + c._rawJSON = json.RawMessage(data) + return nil +} + +func (c *Channel) String() string { + if len(c._rawJSON) > 0 { + if value, err := core.StringifyJSON(c._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(c); err == nil { + return value + } + return fmt.Sprintf("%#v", c) +} + +type ChannelMetadata struct { + Utm *Utm `json:"utm,omitempty"` + + _rawJSON json.RawMessage +} + +func (c *ChannelMetadata) UnmarshalJSON(data []byte) error { + type unmarshaler ChannelMetadata + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *c = ChannelMetadata(value) + c._rawJSON = json.RawMessage(data) + return nil +} + +func (c *ChannelMetadata) String() string { + if len(c._rawJSON) > 0 { + if value, err := core.StringifyJSON(c._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(c); err == nil { + return value + } + return fmt.Sprintf("%#v", c) +} + +type ChannelSource string + +const ( + ChannelSourceSubscription ChannelSource = "subscription" + ChannelSourceList ChannelSource = "list" + ChannelSourceRecipient ChannelSource = "recipient" +) + +func NewChannelSourceFromString(s string) (ChannelSource, error) { + switch s { + case "subscription": + return ChannelSourceSubscription, nil + case "list": + return ChannelSourceList, nil + case "recipient": + return ChannelSourceRecipient, nil + } + var t ChannelSource + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (c ChannelSource) Ptr() *ChannelSource { + return &c +} + +type Content struct { + typeName string + ElementalContent *ElementalContent + ElementalContentSugar *ElementalContentSugar +} + +func NewContentFromElementalContent(value *ElementalContent) *Content { + return &Content{typeName: "elementalContent", ElementalContent: value} +} + +func NewContentFromElementalContentSugar(value *ElementalContentSugar) *Content { + return &Content{typeName: "elementalContentSugar", ElementalContentSugar: value} +} + +func (c *Content) UnmarshalJSON(data []byte) error { + valueElementalContent := new(ElementalContent) + if err := json.Unmarshal(data, &valueElementalContent); err == nil { + c.typeName = "elementalContent" + c.ElementalContent = valueElementalContent + return nil + } + valueElementalContentSugar := new(ElementalContentSugar) + if err := json.Unmarshal(data, &valueElementalContentSugar); err == nil { + c.typeName = "elementalContentSugar" + c.ElementalContentSugar = valueElementalContentSugar + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, c) +} + +func (c Content) MarshalJSON() ([]byte, error) { + switch c.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", c.typeName, c) + case "elementalContent": + return json.Marshal(c.ElementalContent) + case "elementalContentSugar": + return json.Marshal(c.ElementalContentSugar) + } +} + +type ContentVisitor interface { + VisitElementalContent(*ElementalContent) error + VisitElementalContentSugar(*ElementalContentSugar) error +} + +func (c *Content) Accept(visitor ContentVisitor) error { + switch c.typeName { + default: + return fmt.Errorf("invalid type %s in %T", c.typeName, c) + case "elementalContent": + return visitor.VisitElementalContent(c.ElementalContent) + case "elementalContentSugar": + return visitor.VisitElementalContentSugar(c.ElementalContentSugar) + } +} + +// The message property has the following primary top-level properties. They define the destination and content of the message. +// Additional advanced configuration fields [are defined below](https://www.courier.com/docs/reference/send/message/#other-message-properties). +type ContentMessage struct { + // An arbitrary object that includes any data you want to pass to the message. + // The data will populate the corresponding template or elements variables. + Data *MessageData `json:"data,omitempty"` + BrandId *string `json:"brand_id,omitempty"` + // "Define run-time configuration for one or more channels. If you don't specify channels, the default configuration for each channel will be used. Valid ChannelId's are: email, sms, push, inbox, direct_message, banner, and webhook." + Channels *MessageChannels `json:"channels,omitempty"` + // Context to load with this recipient. Will override any context set on message.context. + Context *MessageContext `json:"context,omitempty"` + // Metadata such as utm tracking attached with the notification through this channel. + Metadata *MessageMetadata `json:"metadata,omitempty"` + // An object whose keys are valid provider identifiers which map to an object. + Providers *MessageProviders `json:"providers,omitempty"` + Routing *Routing `json:"routing,omitempty"` + // Time in ms to attempt the channel before failing over to the next available channel. + Timeout *Timeout `json:"timeout,omitempty"` + // Defines the time to wait before delivering the message. + Delay *Delay `json:"delay,omitempty"` + // "Expiry allows you to set an absolute or relative time in which a message expires. + // Note: This is only valid for the Courier Inbox channel as of 12-08-2022." + Expiry *Expiry `json:"expiry,omitempty"` + // Describes the content of the message in a way that will work for email, push, + // chat, or any channel. Either this or template must be specified. + Content *Content `json:"content,omitempty"` + // The recipient or a list of recipients of the message + To *MessageRecipient `json:"to,omitempty"` + + _rawJSON json.RawMessage +} + +func (c *ContentMessage) UnmarshalJSON(data []byte) error { + type unmarshaler ContentMessage + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *c = ContentMessage(value) + c._rawJSON = json.RawMessage(data) + return nil +} + +func (c *ContentMessage) String() string { + if len(c._rawJSON) > 0 { + if value, err := core.StringifyJSON(c._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(c); err == nil { + return value + } + return fmt.Sprintf("%#v", c) +} + +type Criteria string + +const ( + CriteriaNoEscalation Criteria = "no-escalation" + CriteriaDelivered Criteria = "delivered" + CriteriaViewed Criteria = "viewed" + CriteriaEngaged Criteria = "engaged" +) + +func NewCriteriaFromString(s string) (Criteria, error) { + switch s { + case "no-escalation": + return CriteriaNoEscalation, nil + case "delivered": + return CriteriaDelivered, nil + case "viewed": + return CriteriaViewed, nil + case "engaged": + return CriteriaEngaged, nil + } + var t Criteria + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (c Criteria) Ptr() *Criteria { + return &c +} + +type Delay struct { + // The duration of the delay in milliseconds. + Duration int `json:"duration"` + + _rawJSON json.RawMessage +} + +func (d *Delay) UnmarshalJSON(data []byte) error { + type unmarshaler Delay + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *d = Delay(value) + d._rawJSON = json.RawMessage(data) + return nil +} + +func (d *Delay) String() string { + if len(d._rawJSON) > 0 { + if value, err := core.StringifyJSON(d._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(d); err == nil { + return value + } + return fmt.Sprintf("%#v", d) +} + +// Allows the user to execute an action. Can be a button or a link. +type ElementalActionNode struct { + Channels []string `json:"channels,omitempty"` + Ref *string `json:"ref,omitempty"` + If *string `json:"if,omitempty"` + Loop *string `json:"loop,omitempty"` + // The text content of the action shown to the user. + Content string `json:"content"` + // The target URL of the action. + Href string `json:"href"` + // A unique id used to identify the action when it is executed. + ActionId *string `json:"action_id,omitempty"` + // The alignment of the action button. Defaults to "center". + Align *IAlignment `json:"align,omitempty"` + // The background color of the action button. + BackgroundColor *string `json:"background_color,omitempty"` + // Defaults to `button`. + Style *IActionButtonStyle `json:"style,omitempty"` + // Region specific content. See [locales docs](https://www.courier.com/docs/platform/content/elemental/locales/) for more details. + Locales Locales `json:"locales,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *ElementalActionNode) UnmarshalJSON(data []byte) error { + type unmarshaler ElementalActionNode + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = ElementalActionNode(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *ElementalActionNode) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +type ElementalBaseNode struct { + Channels []string `json:"channels,omitempty"` + Ref *string `json:"ref,omitempty"` + If *string `json:"if,omitempty"` + Loop *string `json:"loop,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *ElementalBaseNode) UnmarshalJSON(data []byte) error { + type unmarshaler ElementalBaseNode + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = ElementalBaseNode(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *ElementalBaseNode) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +// The channel element allows a notification to be customized based on which channel it is sent through. +// For example, you may want to display a detailed message when the notification is sent through email, +// and a more concise message in a push notification. Channel elements are only valid as top-level +// elements; you cannot nest channel elements. If there is a channel element specified at the top-level +// of the document, all sibling elements must be channel elements. +// Note: As an alternative, most elements support a `channel` property. Which allows you to selectively +// display an individual element on a per channel basis. See the +// [control flow docs](https://www.courier.com/docs/platform/content/elemental/control-flow/) for more details. +type ElementalChannelNode struct { + Channels []string `json:"channels,omitempty"` + Ref *string `json:"ref,omitempty"` + If *string `json:"if,omitempty"` + Loop *string `json:"loop,omitempty"` + // The channel the contents of this element should be applied to. Can be `email`, + // `push`, `direct_message`, `sms` or a provider such as slack + Channel string `json:"channel"` + // An array of elements to apply to the channel. If `raw` has not been + // specified, `elements` is `required`. + Elements []*ElementalNode `json:"elements,omitempty"` + // Raw data to apply to the channel. If `elements` has not been + // specified, `raw` is `required`. + Raw map[string]interface{} `json:"raw,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *ElementalChannelNode) UnmarshalJSON(data []byte) error { + type unmarshaler ElementalChannelNode + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = ElementalChannelNode(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *ElementalChannelNode) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +type ElementalContent struct { + // For example, "2022-01-01" + Version string `json:"version"` + Brand interface{} `json:"brand,omitempty"` + Elements []*ElementalNode `json:"elements,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *ElementalContent) UnmarshalJSON(data []byte) error { + type unmarshaler ElementalContent + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = ElementalContent(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *ElementalContent) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +// Syntatic Sugar to provide a fast shorthand for Courier Elemental Blocks. +type ElementalContentSugar struct { + // The title to be displayed by supported channels i.e. push, email (as subject) + Title string `json:"title"` + // The text content displayed in the notification. + Body string `json:"body"` + + _rawJSON json.RawMessage +} + +func (e *ElementalContentSugar) UnmarshalJSON(data []byte) error { + type unmarshaler ElementalContentSugar + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = ElementalContentSugar(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *ElementalContentSugar) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +// Renders a dividing line between elements. +type ElementalDividerNode struct { + Channels []string `json:"channels,omitempty"` + Ref *string `json:"ref,omitempty"` + If *string `json:"if,omitempty"` + Loop *string `json:"loop,omitempty"` + // The CSS color to render the line with. For example, `#fff` + Color *string `json:"color,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *ElementalDividerNode) UnmarshalJSON(data []byte) error { + type unmarshaler ElementalDividerNode + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = ElementalDividerNode(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *ElementalDividerNode) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +// Allows you to group elements together. This can be useful when used in combination with "if" or "loop". See [control flow docs](https://www.courier.com/docs/platform/content/elemental/control-flow/) for more details. +type ElementalGroupNode struct { + Channels []string `json:"channels,omitempty"` + Ref *string `json:"ref,omitempty"` + If *string `json:"if,omitempty"` + Loop *string `json:"loop,omitempty"` + // Sub elements to render. + Elements []*ElementalNode `json:"elements,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *ElementalGroupNode) UnmarshalJSON(data []byte) error { + type unmarshaler ElementalGroupNode + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = ElementalGroupNode(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *ElementalGroupNode) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +// Used to embed an image into the notification. +type ElementalImageNode struct { + Channels []string `json:"channels,omitempty"` + Ref *string `json:"ref,omitempty"` + If *string `json:"if,omitempty"` + Loop *string `json:"loop,omitempty"` + // The source of the image. + Src string `json:"src"` + // A URL to link to when the image is clicked. + Href *string `json:"href,omitempty"` + // The alignment of the image. + Align *IAlignment `json:"align,omitempty"` + // Alternate text for the image. + AltText *string `json:"altText,omitempty"` + // CSS width properties to apply to the image. For example, 50px + Width *string `json:"width,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *ElementalImageNode) UnmarshalJSON(data []byte) error { + type unmarshaler ElementalImageNode + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = ElementalImageNode(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *ElementalImageNode) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +// The meta element contains information describing the notification that may +// be used by a particular channel or provider. One important field is the title +// field which will be used as the title for channels that support it. +type ElementalMetaNode struct { + Channels []string `json:"channels,omitempty"` + Ref *string `json:"ref,omitempty"` + If *string `json:"if,omitempty"` + Loop *string `json:"loop,omitempty"` + // The title to be displayed by supported channels. For example, the email subject. + Title *string `json:"title,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *ElementalMetaNode) UnmarshalJSON(data []byte) error { + type unmarshaler ElementalMetaNode + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = ElementalMetaNode(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *ElementalMetaNode) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +type ElementalNode struct { + Type string + Text *ElementalTextNode + Meta *ElementalMetaNode + Channel *ElementalChannelNode + Image *ElementalImageNode + Action *ElementalActionNode + Divider *ElementalDividerNode + Group *ElementalGroupNode + Quote *ElementalQuoteNode +} + +func NewElementalNodeFromText(value *ElementalTextNode) *ElementalNode { + return &ElementalNode{Type: "text", Text: value} +} + +func NewElementalNodeFromMeta(value *ElementalMetaNode) *ElementalNode { + return &ElementalNode{Type: "meta", Meta: value} +} + +func NewElementalNodeFromChannel(value *ElementalChannelNode) *ElementalNode { + return &ElementalNode{Type: "channel", Channel: value} +} + +func NewElementalNodeFromImage(value *ElementalImageNode) *ElementalNode { + return &ElementalNode{Type: "image", Image: value} +} + +func NewElementalNodeFromAction(value *ElementalActionNode) *ElementalNode { + return &ElementalNode{Type: "action", Action: value} +} + +func NewElementalNodeFromDivider(value *ElementalDividerNode) *ElementalNode { + return &ElementalNode{Type: "divider", Divider: value} +} + +func NewElementalNodeFromGroup(value *ElementalGroupNode) *ElementalNode { + return &ElementalNode{Type: "group", Group: value} +} + +func NewElementalNodeFromQuote(value *ElementalQuoteNode) *ElementalNode { + return &ElementalNode{Type: "quote", Quote: value} +} + +func (e *ElementalNode) UnmarshalJSON(data []byte) error { + var unmarshaler struct { + Type string `json:"type"` + } + if err := json.Unmarshal(data, &unmarshaler); err != nil { + return err + } + e.Type = unmarshaler.Type + switch unmarshaler.Type { + case "text": + value := new(ElementalTextNode) + if err := json.Unmarshal(data, &value); err != nil { + return err + } + e.Text = value + case "meta": + value := new(ElementalMetaNode) + if err := json.Unmarshal(data, &value); err != nil { + return err + } + e.Meta = value + case "channel": + value := new(ElementalChannelNode) + if err := json.Unmarshal(data, &value); err != nil { + return err + } + e.Channel = value + case "image": + value := new(ElementalImageNode) + if err := json.Unmarshal(data, &value); err != nil { + return err + } + e.Image = value + case "action": + value := new(ElementalActionNode) + if err := json.Unmarshal(data, &value); err != nil { + return err + } + e.Action = value + case "divider": + value := new(ElementalDividerNode) + if err := json.Unmarshal(data, &value); err != nil { + return err + } + e.Divider = value + case "group": + value := new(ElementalGroupNode) + if err := json.Unmarshal(data, &value); err != nil { + return err + } + e.Group = value + case "quote": + value := new(ElementalQuoteNode) + if err := json.Unmarshal(data, &value); err != nil { + return err + } + e.Quote = value + } + return nil +} + +func (e ElementalNode) MarshalJSON() ([]byte, error) { + switch e.Type { + default: + return nil, fmt.Errorf("invalid type %s in %T", e.Type, e) + case "text": + var marshaler = struct { + Type string `json:"type"` + *ElementalTextNode + }{ + Type: e.Type, + ElementalTextNode: e.Text, + } + return json.Marshal(marshaler) + case "meta": + var marshaler = struct { + Type string `json:"type"` + *ElementalMetaNode + }{ + Type: e.Type, + ElementalMetaNode: e.Meta, + } + return json.Marshal(marshaler) + case "channel": + var marshaler = struct { + Type string `json:"type"` + *ElementalChannelNode + }{ + Type: e.Type, + ElementalChannelNode: e.Channel, + } + return json.Marshal(marshaler) + case "image": + var marshaler = struct { + Type string `json:"type"` + *ElementalImageNode + }{ + Type: e.Type, + ElementalImageNode: e.Image, + } + return json.Marshal(marshaler) + case "action": + var marshaler = struct { + Type string `json:"type"` + *ElementalActionNode + }{ + Type: e.Type, + ElementalActionNode: e.Action, + } + return json.Marshal(marshaler) + case "divider": + var marshaler = struct { + Type string `json:"type"` + *ElementalDividerNode + }{ + Type: e.Type, + ElementalDividerNode: e.Divider, + } + return json.Marshal(marshaler) + case "group": + var marshaler = struct { + Type string `json:"type"` + *ElementalGroupNode + }{ + Type: e.Type, + ElementalGroupNode: e.Group, + } + return json.Marshal(marshaler) + case "quote": + var marshaler = struct { + Type string `json:"type"` + *ElementalQuoteNode + }{ + Type: e.Type, + ElementalQuoteNode: e.Quote, + } + return json.Marshal(marshaler) + } +} + +type ElementalNodeVisitor interface { + VisitText(*ElementalTextNode) error + VisitMeta(*ElementalMetaNode) error + VisitChannel(*ElementalChannelNode) error + VisitImage(*ElementalImageNode) error + VisitAction(*ElementalActionNode) error + VisitDivider(*ElementalDividerNode) error + VisitGroup(*ElementalGroupNode) error + VisitQuote(*ElementalQuoteNode) error +} + +func (e *ElementalNode) Accept(visitor ElementalNodeVisitor) error { + switch e.Type { + default: + return fmt.Errorf("invalid type %s in %T", e.Type, e) + case "text": + return visitor.VisitText(e.Text) + case "meta": + return visitor.VisitMeta(e.Meta) + case "channel": + return visitor.VisitChannel(e.Channel) + case "image": + return visitor.VisitImage(e.Image) + case "action": + return visitor.VisitAction(e.Action) + case "divider": + return visitor.VisitDivider(e.Divider) + case "group": + return visitor.VisitGroup(e.Group) + case "quote": + return visitor.VisitQuote(e.Quote) + } +} + +// Renders a quote block. +type ElementalQuoteNode struct { + Channels []string `json:"channels,omitempty"` + Ref *string `json:"ref,omitempty"` + If *string `json:"if,omitempty"` + Loop *string `json:"loop,omitempty"` + // The text value of the quote. + Content string `json:"content"` + // Alignment of the quote. + Align *IAlignment `json:"align,omitempty"` + // CSS border color property. For example, `#fff` + BorderColor *string `json:"borderColor,omitempty"` + TextStyle TextStyle `json:"text_style,omitempty"` + // Region specific content. See [locales docs](https://www.courier.com/docs/platform/content/elemental/locales/) for more details. + Locales Locales `json:"locales,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *ElementalQuoteNode) UnmarshalJSON(data []byte) error { + type unmarshaler ElementalQuoteNode + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = ElementalQuoteNode(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *ElementalQuoteNode) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +// Represents a body of text to be rendered inside of the notification. +type ElementalTextNode struct { + Channels []string `json:"channels,omitempty"` + Ref *string `json:"ref,omitempty"` + If *string `json:"if,omitempty"` + Loop *string `json:"loop,omitempty"` + // The text content displayed in the notification. Either this + // field must be specified, or the elements field + Content string `json:"content"` + // Text alignment. + Align TextAlign `json:"align,omitempty"` + // Allows the text to be rendered as a heading level. + TextStyle *TextStyle `json:"text_style,omitempty"` + // Specifies the color of text. Can be any valid css color value + Color *string `json:"color,omitempty"` + // Apply bold to the text + Bold *string `json:"bold,omitempty"` + // Apply italics to the text + Italic *string `json:"italic,omitempty"` + // Apply a strike through the text + Strikethrough *string `json:"strikethrough,omitempty"` + // Apply an underline to the text + Underline *string `json:"underline,omitempty"` + // Region specific content. See [locales docs](https://www.courier.com/docs/platform/content/elemental/locales/) for more details. + Locales *Locales `json:"locales,omitempty"` + Format *string `json:"format,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *ElementalTextNode) UnmarshalJSON(data []byte) error { + type unmarshaler ElementalTextNode + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = ElementalTextNode(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *ElementalTextNode) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +type EmailFooter struct { + Content interface{} `json:"content,omitempty"` + InheritDefault *bool `json:"inheritDefault,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *EmailFooter) UnmarshalJSON(data []byte) error { + type unmarshaler EmailFooter + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = EmailFooter(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *EmailFooter) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +type EmailHead struct { + InheritDefault bool `json:"inheritDefault"` + Content *string `json:"content,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *EmailHead) UnmarshalJSON(data []byte) error { + type unmarshaler EmailHead + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = EmailHead(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *EmailHead) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +type EmailHeader struct { + InheritDefault *bool `json:"inheritDefault,omitempty"` + BarColor *string `json:"barColor,omitempty"` + Logo *Logo `json:"logo,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *EmailHeader) UnmarshalJSON(data []byte) error { + type unmarshaler EmailHeader + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = EmailHeader(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *EmailHeader) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +type ExpiresInType struct { + typeName string + String string + Integer int +} + +func NewExpiresInTypeFromString(value string) *ExpiresInType { + return &ExpiresInType{typeName: "string", String: value} +} + +func NewExpiresInTypeFromInteger(value int) *ExpiresInType { + return &ExpiresInType{typeName: "integer", Integer: value} +} + +func (e *ExpiresInType) UnmarshalJSON(data []byte) error { + var valueString string + if err := json.Unmarshal(data, &valueString); err == nil { + e.typeName = "string" + e.String = valueString + return nil + } + var valueInteger int + if err := json.Unmarshal(data, &valueInteger); err == nil { + e.typeName = "integer" + e.Integer = valueInteger + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, e) +} + +func (e ExpiresInType) MarshalJSON() ([]byte, error) { + switch e.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", e.typeName, e) + case "string": + return json.Marshal(e.String) + case "integer": + return json.Marshal(e.Integer) + } +} + +type ExpiresInTypeVisitor interface { + VisitString(string) error + VisitInteger(int) error +} + +func (e *ExpiresInType) Accept(visitor ExpiresInTypeVisitor) error { + switch e.typeName { + default: + return fmt.Errorf("invalid type %s in %T", e.typeName, e) + case "string": + return visitor.VisitString(e.String) + case "integer": + return visitor.VisitInteger(e.Integer) + } +} + +type Expiry struct { + // An epoch timestamp or ISO8601 timestamp with timezone `(YYYY-MM-DDThh:mm:ss.sTZD)` that describes the time in which a message expires. + ExpiresAt *string `json:"expires_at,omitempty"` + // A duration in the form of milliseconds or an ISO8601 Duration format (i.e. P1DT4H). + ExpiresIn *ExpiresInType `json:"expires_in,omitempty"` + + _rawJSON json.RawMessage +} + +func (e *Expiry) UnmarshalJSON(data []byte) error { + type unmarshaler Expiry + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *e = Expiry(value) + e._rawJSON = json.RawMessage(data) + return nil +} + +func (e *Expiry) String() string { + if len(e._rawJSON) > 0 { + if value, err := core.StringifyJSON(e._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(e); err == nil { + return value + } + return fmt.Sprintf("%#v", e) +} + +type IActionButtonStyle string + +const ( + IActionButtonStyleButton IActionButtonStyle = "button" + IActionButtonStyleLink IActionButtonStyle = "link" +) + +func NewIActionButtonStyleFromString(s string) (IActionButtonStyle, error) { + switch s { + case "button": + return IActionButtonStyleButton, nil + case "link": + return IActionButtonStyleLink, nil + } + var t IActionButtonStyle + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (i IActionButtonStyle) Ptr() *IActionButtonStyle { + return &i +} + +type IAlignment string + +const ( + IAlignmentCenter IAlignment = "center" + IAlignmentLeft IAlignment = "left" + IAlignmentRight IAlignment = "right" + IAlignmentFull IAlignment = "full" +) + +func NewIAlignmentFromString(s string) (IAlignment, error) { + switch s { + case "center": + return IAlignmentCenter, nil + case "left": + return IAlignmentLeft, nil + case "right": + return IAlignmentRight, nil + case "full": + return IAlignmentFull, nil + } + var t IAlignment + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (i IAlignment) Ptr() *IAlignment { + return &i +} + +type IPreferences = map[string]*Preference + +type IProfilePreferences struct { + Categories *IPreferences `json:"categories,omitempty"` + Notifications IPreferences `json:"notifications,omitempty"` + TemplateId *string `json:"templateId,omitempty"` + + _rawJSON json.RawMessage +} + +func (i *IProfilePreferences) UnmarshalJSON(data []byte) error { + type unmarshaler IProfilePreferences + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *i = IProfilePreferences(value) + i._rawJSON = json.RawMessage(data) + return nil +} + +func (i *IProfilePreferences) String() string { + if len(i._rawJSON) > 0 { + if value, err := core.StringifyJSON(i._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(i); err == nil { + return value + } + return fmt.Sprintf("%#v", i) +} + +type Icons struct { + Bell *string `json:"bell,omitempty"` + Message *string `json:"message,omitempty"` + + _rawJSON json.RawMessage +} + +func (i *Icons) UnmarshalJSON(data []byte) error { + type unmarshaler Icons + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *i = Icons(value) + i._rawJSON = json.RawMessage(data) + return nil +} + +func (i *Icons) String() string { + if len(i._rawJSON) > 0 { + if value, err := core.StringifyJSON(i._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(i); err == nil { + return value + } + return fmt.Sprintf("%#v", i) +} + +type InAppPlacement string + +const ( + InAppPlacementTop InAppPlacement = "top" + InAppPlacementBottom InAppPlacement = "bottom" + InAppPlacementLeft InAppPlacement = "left" + InAppPlacementRight InAppPlacement = "right" +) + +func NewInAppPlacementFromString(s string) (InAppPlacement, error) { + switch s { + case "top": + return InAppPlacementTop, nil + case "bottom": + return InAppPlacementBottom, nil + case "left": + return InAppPlacementLeft, nil + case "right": + return InAppPlacementRight, nil + } + var t InAppPlacement + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (i InAppPlacement) Ptr() *InAppPlacement { + return &i +} + +type InvalidListPatternRecipient struct { + UserId string `json:"user_id"` + ListId string `json:"list_id"` + + _rawJSON json.RawMessage +} + +func (i *InvalidListPatternRecipient) UnmarshalJSON(data []byte) error { + type unmarshaler InvalidListPatternRecipient + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *i = InvalidListPatternRecipient(value) + i._rawJSON = json.RawMessage(data) + return nil +} + +func (i *InvalidListPatternRecipient) String() string { + if len(i._rawJSON) > 0 { + if value, err := core.StringifyJSON(i._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(i); err == nil { + return value + } + return fmt.Sprintf("%#v", i) +} + +type InvalidListRecipient struct { + UserId string `json:"user_id"` + ListPattern string `json:"list_pattern"` + + _rawJSON json.RawMessage +} + +func (i *InvalidListRecipient) UnmarshalJSON(data []byte) error { + type unmarshaler InvalidListRecipient + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *i = InvalidListRecipient(value) + i._rawJSON = json.RawMessage(data) + return nil +} + +func (i *InvalidListRecipient) String() string { + if len(i._rawJSON) > 0 { + if value, err := core.StringifyJSON(i._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(i); err == nil { + return value + } + return fmt.Sprintf("%#v", i) +} + +type InvalidUserRecipient struct { + ListId string `json:"list_id"` + ListPattern string `json:"list_pattern"` + + _rawJSON json.RawMessage +} + +func (i *InvalidUserRecipient) UnmarshalJSON(data []byte) error { + type unmarshaler InvalidUserRecipient + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *i = InvalidUserRecipient(value) + i._rawJSON = json.RawMessage(data) + return nil +} + +func (i *InvalidUserRecipient) String() string { + if len(i._rawJSON) > 0 { + if value, err := core.StringifyJSON(i._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(i); err == nil { + return value + } + return fmt.Sprintf("%#v", i) +} + +type ListFilter struct { + // Send to users only if they are member of the account + Value string `json:"value"` + operator string + path string + + _rawJSON json.RawMessage +} + +func (l *ListFilter) Operator() string { + return l.operator +} + +func (l *ListFilter) Path() string { + return l.path +} + +func (l *ListFilter) UnmarshalJSON(data []byte) error { + type unmarshaler ListFilter + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListFilter(value) + l.operator = "MEMBER_OF" + l.path = "account_id" + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListFilter) MarshalJSON() ([]byte, error) { + type embed ListFilter + var marshaler = struct { + embed + Operator string `json:"operator"` + Path string `json:"path"` + }{ + embed: embed(*l), + Operator: "MEMBER_OF", + Path: "account_id", + } + return json.Marshal(marshaler) +} + +func (l *ListFilter) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type ListPatternRecipient struct { + ListPattern *string `json:"list_pattern,omitempty"` + Data *MessageData `json:"data,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *ListPatternRecipient) UnmarshalJSON(data []byte) error { + type unmarshaler ListPatternRecipient + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListPatternRecipient(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListPatternRecipient) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type ListPatternRecipientType struct { + _rawJSON json.RawMessage +} + +func (l *ListPatternRecipientType) UnmarshalJSON(data []byte) error { + type unmarshaler ListPatternRecipientType + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListPatternRecipientType(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListPatternRecipientType) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type ListRecipient struct { + ListId *string `json:"list_id,omitempty"` + Data *MessageData `json:"data,omitempty"` + Filters []*ListFilter `json:"filters,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *ListRecipient) UnmarshalJSON(data []byte) error { + type unmarshaler ListRecipient + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListRecipient(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListRecipient) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type ListRecipientType struct { + _rawJSON json.RawMessage +} + +func (l *ListRecipientType) UnmarshalJSON(data []byte) error { + type unmarshaler ListRecipientType + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListRecipientType(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListRecipientType) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type Locale struct { + Content string `json:"content"` + + _rawJSON json.RawMessage +} + +func (l *Locale) UnmarshalJSON(data []byte) error { + type unmarshaler Locale + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = Locale(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *Locale) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type Locales = map[string]*Locale + +type Logo struct { + Href *string `json:"href,omitempty"` + Image *string `json:"image,omitempty"` + + _rawJSON json.RawMessage +} + +func (l *Logo) UnmarshalJSON(data []byte) error { + type unmarshaler Logo + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = Logo(value) + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *Logo) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type Message struct { + typeName string + // Describes the content of the message in a way that will work for email, push, chat, or any channel. + ContentMessage *ContentMessage + // A template for a type of message that can be sent more than once. For example, you might create an "Appointment Reminder" Notification or “Reset Password” Notifications. + TemplateMessage *TemplateMessage +} + +func NewMessageFromContentMessage(value *ContentMessage) *Message { + return &Message{typeName: "contentMessage", ContentMessage: value} +} + +func NewMessageFromTemplateMessage(value *TemplateMessage) *Message { + return &Message{typeName: "templateMessage", TemplateMessage: value} +} + +func (m *Message) UnmarshalJSON(data []byte) error { + valueContentMessage := new(ContentMessage) + if err := json.Unmarshal(data, &valueContentMessage); err == nil { + m.typeName = "contentMessage" + m.ContentMessage = valueContentMessage + return nil + } + valueTemplateMessage := new(TemplateMessage) + if err := json.Unmarshal(data, &valueTemplateMessage); err == nil { + m.typeName = "templateMessage" + m.TemplateMessage = valueTemplateMessage + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, m) +} + +func (m Message) MarshalJSON() ([]byte, error) { + switch m.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", m.typeName, m) + case "contentMessage": + return json.Marshal(m.ContentMessage) + case "templateMessage": + return json.Marshal(m.TemplateMessage) + } +} + +type MessageVisitor interface { + VisitContentMessage(*ContentMessage) error + VisitTemplateMessage(*TemplateMessage) error +} + +func (m *Message) Accept(visitor MessageVisitor) error { + switch m.typeName { + default: + return fmt.Errorf("invalid type %s in %T", m.typeName, m) + case "contentMessage": + return visitor.VisitContentMessage(m.ContentMessage) + case "templateMessage": + return visitor.VisitTemplateMessage(m.TemplateMessage) + } +} + +type MessageChannelEmailOverride struct { + Attachments []Attachment `json:"attachments,omitempty"` + Bcc *string `json:"bcc,omitempty"` + Brand *Brand `json:"brand,omitempty"` + Cc *string `json:"cc,omitempty"` + From *string `json:"from,omitempty"` + Html *string `json:"html,omitempty"` + ReplyTo *string `json:"reply_to,omitempty"` + Subject *string `json:"subject,omitempty"` + Text *string `json:"text,omitempty"` + Tracking *TrackingOverride `json:"tracking,omitempty"` + + _rawJSON json.RawMessage +} + +func (m *MessageChannelEmailOverride) UnmarshalJSON(data []byte) error { + type unmarshaler MessageChannelEmailOverride + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *m = MessageChannelEmailOverride(value) + m._rawJSON = json.RawMessage(data) + return nil +} + +func (m *MessageChannelEmailOverride) String() string { + if len(m._rawJSON) > 0 { + if value, err := core.StringifyJSON(m._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(m); err == nil { + return value + } + return fmt.Sprintf("%#v", m) +} + +type MessageChannels = map[string]*Channel + +type MessageContext struct { + // An id of a tenant, see [tenants api docs](https://www.courier.com/docs/reference/tenants/). + // Will load brand, default preferences and any other base context data associated with this tenant. + TenantId *string `json:"tenant_id,omitempty"` + + _rawJSON json.RawMessage +} + +func (m *MessageContext) UnmarshalJSON(data []byte) error { + type unmarshaler MessageContext + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *m = MessageContext(value) + m._rawJSON = json.RawMessage(data) + return nil +} + +func (m *MessageContext) String() string { + if len(m._rawJSON) > 0 { + if value, err := core.StringifyJSON(m._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(m); err == nil { + return value + } + return fmt.Sprintf("%#v", m) +} + +type MessageData = map[string]interface{} + +type MessageMetadata struct { + // An arbitrary string to tracks the event that generated this request (e.g. 'signup'). + Event *string `json:"event,omitempty"` + // An array of up to 9 tags you wish to associate with this request (and corresponding messages) for later analysis. Individual tags cannot be more than 30 characters in length. + Tags []string `json:"tags,omitempty"` + // Identify the campaign that refers traffic to a specific website, and attributes the browser's website session. + Utm *Utm `json:"utm,omitempty"` + // A unique ID used to correlate this request to processing on your servers. Note: Courier does not verify the uniqueness of this ID. + TraceId *string `json:"trace_id,omitempty"` + + _rawJSON json.RawMessage +} + +func (m *MessageMetadata) UnmarshalJSON(data []byte) error { + type unmarshaler MessageMetadata + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *m = MessageMetadata(value) + m._rawJSON = json.RawMessage(data) + return nil +} + +func (m *MessageMetadata) String() string { + if len(m._rawJSON) > 0 { + if value, err := core.StringifyJSON(m._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(m); err == nil { + return value + } + return fmt.Sprintf("%#v", m) +} + +type MessageProviders = map[string]*MessageProvidersType + +type MessageProvidersType struct { + // Provider specific overrides. + Override map[string]interface{} `json:"override,omitempty"` + // A JavaScript conditional expression to determine if the message should be sent + // through the channel. Has access to the data and profile object. For example, + // `data.name === profile.name` + If *string `json:"if,omitempty"` + Timeouts *int `json:"timeouts,omitempty"` + Metadata *Metadata `json:"metadata,omitempty"` + + _rawJSON json.RawMessage +} + +func (m *MessageProvidersType) UnmarshalJSON(data []byte) error { + type unmarshaler MessageProvidersType + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *m = MessageProvidersType(value) + m._rawJSON = json.RawMessage(data) + return nil +} + +func (m *MessageProvidersType) String() string { + if len(m._rawJSON) > 0 { + if value, err := core.StringifyJSON(m._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(m); err == nil { + return value + } + return fmt.Sprintf("%#v", m) +} + +type MessageRecipient struct { + typeName string + Recipient *Recipient + RecipientList []*Recipient +} + +func NewMessageRecipientFromRecipient(value *Recipient) *MessageRecipient { + return &MessageRecipient{typeName: "recipient", Recipient: value} +} + +func NewMessageRecipientFromRecipientList(value []*Recipient) *MessageRecipient { + return &MessageRecipient{typeName: "recipientList", RecipientList: value} +} + +func (m *MessageRecipient) UnmarshalJSON(data []byte) error { + valueRecipient := new(Recipient) + if err := json.Unmarshal(data, &valueRecipient); err == nil { + m.typeName = "recipient" + m.Recipient = valueRecipient + return nil + } + var valueRecipientList []*Recipient + if err := json.Unmarshal(data, &valueRecipientList); err == nil { + m.typeName = "recipientList" + m.RecipientList = valueRecipientList + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, m) +} + +func (m MessageRecipient) MarshalJSON() ([]byte, error) { + switch m.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", m.typeName, m) + case "recipient": + return json.Marshal(m.Recipient) + case "recipientList": + return json.Marshal(m.RecipientList) + } +} + +type MessageRecipientVisitor interface { + VisitRecipient(*Recipient) error + VisitRecipientList([]*Recipient) error +} + +func (m *MessageRecipient) Accept(visitor MessageRecipientVisitor) error { + switch m.typeName { + default: + return fmt.Errorf("invalid type %s in %T", m.typeName, m) + case "recipient": + return visitor.VisitRecipient(m.Recipient) + case "recipientList": + return visitor.VisitRecipientList(m.RecipientList) + } +} + +type Metadata struct { + Utm *Utm `json:"utm,omitempty"` + + _rawJSON json.RawMessage +} + +func (m *Metadata) UnmarshalJSON(data []byte) error { + type unmarshaler Metadata + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *m = Metadata(value) + m._rawJSON = json.RawMessage(data) + return nil +} + +func (m *Metadata) String() string { + if len(m._rawJSON) > 0 { + if value, err := core.StringifyJSON(m._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(m); err == nil { + return value + } + return fmt.Sprintf("%#v", m) +} + +type Override string + +const ( + OverrideMessageChannelEmailOverride Override = "MessageChannelEmailOverride" + OverrideMessageChannelPushOverride Override = "MessageChannelPushOverride" +) + +func NewOverrideFromString(s string) (Override, error) { + switch s { + case "MessageChannelEmailOverride": + return OverrideMessageChannelEmailOverride, nil + case "MessageChannelPushOverride": + return OverrideMessageChannelPushOverride, nil + } + var t Override + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (o Override) Ptr() *Override { + return &o +} + +type Preference struct { + Status PreferenceStatus `json:"status,omitempty"` + Rules []*Rule `json:"rules,omitempty"` + ChannelPreferences []*ChannelPreference `json:"channel_preferences,omitempty"` + Source *ChannelSource `json:"source,omitempty"` + + _rawJSON json.RawMessage +} + +func (p *Preference) UnmarshalJSON(data []byte) error { + type unmarshaler Preference + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *p = Preference(value) + p._rawJSON = json.RawMessage(data) + return nil +} + +func (p *Preference) String() string { + if len(p._rawJSON) > 0 { + if value, err := core.StringifyJSON(p._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(p); err == nil { + return value + } + return fmt.Sprintf("%#v", p) +} + +type Preferences struct { + TemplateIds []string `json:"templateIds,omitempty"` + + _rawJSON json.RawMessage +} + +func (p *Preferences) UnmarshalJSON(data []byte) error { + type unmarshaler Preferences + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *p = Preferences(value) + p._rawJSON = json.RawMessage(data) + return nil +} + +func (p *Preferences) String() string { + if len(p._rawJSON) > 0 { + if value, err := core.StringifyJSON(p._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(p); err == nil { + return value + } + return fmt.Sprintf("%#v", p) +} + +type Recipient struct { + typeName string + AudienceRecipient *AudienceRecipient + ListRecipient *ListRecipient + ListPatternRecipient *ListPatternRecipient + UserRecipient *UserRecipient +} + +func NewRecipientFromAudienceRecipient(value *AudienceRecipient) *Recipient { + return &Recipient{typeName: "audienceRecipient", AudienceRecipient: value} +} + +func NewRecipientFromListRecipient(value *ListRecipient) *Recipient { + return &Recipient{typeName: "listRecipient", ListRecipient: value} +} + +func NewRecipientFromListPatternRecipient(value *ListPatternRecipient) *Recipient { + return &Recipient{typeName: "listPatternRecipient", ListPatternRecipient: value} +} + +func NewRecipientFromUserRecipient(value *UserRecipient) *Recipient { + return &Recipient{typeName: "userRecipient", UserRecipient: value} +} + +func (r *Recipient) UnmarshalJSON(data []byte) error { + valueAudienceRecipient := new(AudienceRecipient) + if err := json.Unmarshal(data, &valueAudienceRecipient); err == nil { + r.typeName = "audienceRecipient" + r.AudienceRecipient = valueAudienceRecipient + return nil + } + valueListRecipient := new(ListRecipient) + if err := json.Unmarshal(data, &valueListRecipient); err == nil { + r.typeName = "listRecipient" + r.ListRecipient = valueListRecipient + return nil + } + valueListPatternRecipient := new(ListPatternRecipient) + if err := json.Unmarshal(data, &valueListPatternRecipient); err == nil { + r.typeName = "listPatternRecipient" + r.ListPatternRecipient = valueListPatternRecipient + return nil + } + valueUserRecipient := new(UserRecipient) + if err := json.Unmarshal(data, &valueUserRecipient); err == nil { + r.typeName = "userRecipient" + r.UserRecipient = valueUserRecipient + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, r) +} + +func (r Recipient) MarshalJSON() ([]byte, error) { + switch r.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", r.typeName, r) + case "audienceRecipient": + return json.Marshal(r.AudienceRecipient) + case "listRecipient": + return json.Marshal(r.ListRecipient) + case "listPatternRecipient": + return json.Marshal(r.ListPatternRecipient) + case "userRecipient": + return json.Marshal(r.UserRecipient) + } +} + +type RecipientVisitor interface { + VisitAudienceRecipient(*AudienceRecipient) error + VisitListRecipient(*ListRecipient) error + VisitListPatternRecipient(*ListPatternRecipient) error + VisitUserRecipient(*UserRecipient) error +} + +func (r *Recipient) Accept(visitor RecipientVisitor) error { + switch r.typeName { + default: + return fmt.Errorf("invalid type %s in %T", r.typeName, r) + case "audienceRecipient": + return visitor.VisitAudienceRecipient(r.AudienceRecipient) + case "listRecipient": + return visitor.VisitListRecipient(r.ListRecipient) + case "listPatternRecipient": + return visitor.VisitListPatternRecipient(r.ListPatternRecipient) + case "userRecipient": + return visitor.VisitUserRecipient(r.UserRecipient) + } +} + +// Allows you to customize which channel(s) Courier will potentially deliver the message. +// If no routing key is specified, Courier will use the default routing configuration or +// routing defined by the template. +type Routing struct { + Method RoutingMethod `json:"method,omitempty"` + // A list of channels or providers to send the message through. Can also recursively define + // sub-routing methods, which can be useful for defining advanced push notification + // delivery strategies. + Channels []*RoutingChannel `json:"channels,omitempty"` + + _rawJSON json.RawMessage +} + +func (r *Routing) UnmarshalJSON(data []byte) error { + type unmarshaler Routing + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *r = Routing(value) + r._rawJSON = json.RawMessage(data) + return nil +} + +func (r *Routing) String() string { + if len(r._rawJSON) > 0 { + if value, err := core.StringifyJSON(r._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(r); err == nil { + return value + } + return fmt.Sprintf("%#v", r) +} + +type RoutingChannel struct { + typeName string + RoutingStrategyChannel *RoutingStrategyChannel + RoutingStrategyProvider *RoutingStrategyProvider + String string +} + +func NewRoutingChannelFromRoutingStrategyChannel(value *RoutingStrategyChannel) *RoutingChannel { + return &RoutingChannel{typeName: "routingStrategyChannel", RoutingStrategyChannel: value} +} + +func NewRoutingChannelFromRoutingStrategyProvider(value *RoutingStrategyProvider) *RoutingChannel { + return &RoutingChannel{typeName: "routingStrategyProvider", RoutingStrategyProvider: value} +} + +func NewRoutingChannelFromString(value string) *RoutingChannel { + return &RoutingChannel{typeName: "string", String: value} +} + +func (r *RoutingChannel) UnmarshalJSON(data []byte) error { + valueRoutingStrategyChannel := new(RoutingStrategyChannel) + if err := json.Unmarshal(data, &valueRoutingStrategyChannel); err == nil { + r.typeName = "routingStrategyChannel" + r.RoutingStrategyChannel = valueRoutingStrategyChannel + return nil + } + valueRoutingStrategyProvider := new(RoutingStrategyProvider) + if err := json.Unmarshal(data, &valueRoutingStrategyProvider); err == nil { + r.typeName = "routingStrategyProvider" + r.RoutingStrategyProvider = valueRoutingStrategyProvider + return nil + } + var valueString string + if err := json.Unmarshal(data, &valueString); err == nil { + r.typeName = "string" + r.String = valueString + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, r) +} + +func (r RoutingChannel) MarshalJSON() ([]byte, error) { + switch r.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", r.typeName, r) + case "routingStrategyChannel": + return json.Marshal(r.RoutingStrategyChannel) + case "routingStrategyProvider": + return json.Marshal(r.RoutingStrategyProvider) + case "string": + return json.Marshal(r.String) + } +} + +type RoutingChannelVisitor interface { + VisitRoutingStrategyChannel(*RoutingStrategyChannel) error + VisitRoutingStrategyProvider(*RoutingStrategyProvider) error + VisitString(string) error +} + +func (r *RoutingChannel) Accept(visitor RoutingChannelVisitor) error { + switch r.typeName { + default: + return fmt.Errorf("invalid type %s in %T", r.typeName, r) + case "routingStrategyChannel": + return visitor.VisitRoutingStrategyChannel(r.RoutingStrategyChannel) + case "routingStrategyProvider": + return visitor.VisitRoutingStrategyProvider(r.RoutingStrategyProvider) + case "string": + return visitor.VisitString(r.String) + } +} + +type RoutingMethod string + +const ( + RoutingMethodAll RoutingMethod = "all" + RoutingMethodSingle RoutingMethod = "single" +) + +func NewRoutingMethodFromString(s string) (RoutingMethod, error) { + switch s { + case "all": + return RoutingMethodAll, nil + case "single": + return RoutingMethodSingle, nil + } + var t RoutingMethod + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (r RoutingMethod) Ptr() *RoutingMethod { + return &r +} + +type RoutingStrategyChannel struct { + Channel string `json:"channel"` + Config map[string]interface{} `json:"config,omitempty"` + Method *RoutingMethod `json:"method,omitempty"` + Providers *MessageProviders `json:"providers,omitempty"` + If *string `json:"if,omitempty"` + + _rawJSON json.RawMessage +} + +func (r *RoutingStrategyChannel) UnmarshalJSON(data []byte) error { + type unmarshaler RoutingStrategyChannel + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *r = RoutingStrategyChannel(value) + r._rawJSON = json.RawMessage(data) + return nil +} + +func (r *RoutingStrategyChannel) String() string { + if len(r._rawJSON) > 0 { + if value, err := core.StringifyJSON(r._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(r); err == nil { + return value + } + return fmt.Sprintf("%#v", r) +} + +type RoutingStrategyProvider struct { + Name string `json:"name"` + Config map[string]interface{} `json:"config,omitempty"` + If *string `json:"if,omitempty"` + Metadata *Metadata `json:"metadata,omitempty"` + + _rawJSON json.RawMessage +} + +func (r *RoutingStrategyProvider) UnmarshalJSON(data []byte) error { + type unmarshaler RoutingStrategyProvider + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *r = RoutingStrategyProvider(value) + r._rawJSON = json.RawMessage(data) + return nil +} + +func (r *RoutingStrategyProvider) String() string { + if len(r._rawJSON) > 0 { + if value, err := core.StringifyJSON(r._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(r); err == nil { + return value + } + return fmt.Sprintf("%#v", r) +} + +type RuleType string + +const ( + RuleTypeSnooze RuleType = "snooze" + RuleTypeChannelPreferences RuleType = "channel_preferences" + RuleTypeStatus RuleType = "status" +) + +func NewRuleTypeFromString(s string) (RuleType, error) { + switch s { + case "snooze": + return RuleTypeSnooze, nil + case "channel_preferences": + return RuleTypeChannelPreferences, nil + case "status": + return RuleTypeStatus, nil + } + var t RuleType + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (r RuleType) Ptr() *RuleType { + return &r +} + +type TemplateMessage struct { + // An arbitrary object that includes any data you want to pass to the message. + // The data will populate the corresponding template or elements variables. + Data *MessageData `json:"data,omitempty"` + BrandId *string `json:"brand_id,omitempty"` + // "Define run-time configuration for one or more channels. If you don't specify channels, the default configuration for each channel will be used. Valid ChannelId's are: email, sms, push, inbox, direct_message, banner, and webhook." + Channels *MessageChannels `json:"channels,omitempty"` + // Context to load with this recipient. Will override any context set on message.context. + Context *MessageContext `json:"context,omitempty"` + // Metadata such as utm tracking attached with the notification through this channel. + Metadata *MessageMetadata `json:"metadata,omitempty"` + // An object whose keys are valid provider identifiers which map to an object. + Providers *MessageProviders `json:"providers,omitempty"` + Routing *Routing `json:"routing,omitempty"` + // Time in ms to attempt the channel before failing over to the next available channel. + Timeout *Timeout `json:"timeout,omitempty"` + // Defines the time to wait before delivering the message. + Delay *Delay `json:"delay,omitempty"` + // "Expiry allows you to set an absolute or relative time in which a message expires. + // Note: This is only valid for the Courier Inbox channel as of 12-08-2022." + Expiry *Expiry `json:"expiry,omitempty"` + // The id of the notification template to be rendered and sent to the recipient(s). + // This field or the content field must be supplied. + Template string `json:"template"` + // The recipient or a list of recipients of the message + To *MessageRecipient `json:"to,omitempty"` + + _rawJSON json.RawMessage +} + +func (t *TemplateMessage) UnmarshalJSON(data []byte) error { + type unmarshaler TemplateMessage + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *t = TemplateMessage(value) + t._rawJSON = json.RawMessage(data) + return nil +} + +func (t *TemplateMessage) String() string { + if len(t._rawJSON) > 0 { + if value, err := core.StringifyJSON(t._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(t); err == nil { + return value + } + return fmt.Sprintf("%#v", t) +} + +type TextAlign string + +const ( + TextAlignLeft TextAlign = "left" + TextAlignCenter TextAlign = "center" + TextAlignRight TextAlign = "right" +) + +func NewTextAlignFromString(s string) (TextAlign, error) { + switch s { + case "left": + return TextAlignLeft, nil + case "center": + return TextAlignCenter, nil + case "right": + return TextAlignRight, nil + } + var t TextAlign + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (t TextAlign) Ptr() *TextAlign { + return &t +} + +type TextStyle string + +const ( + TextStyleText TextStyle = "text" + TextStyleH1 TextStyle = "h1" + TextStyleH2 TextStyle = "h2" + TextStyleSubtext TextStyle = "subtext" +) + +func NewTextStyleFromString(s string) (TextStyle, error) { + switch s { + case "text": + return TextStyleText, nil + case "h1": + return TextStyleH1, nil + case "h2": + return TextStyleH2, nil + case "subtext": + return TextStyleSubtext, nil + } + var t TextStyle + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (t TextStyle) Ptr() *TextStyle { + return &t +} + +type Timeout struct { + Provider map[string]int `json:"provider,omitempty"` + Channel map[string]int `json:"channel,omitempty"` + Message *int `json:"message,omitempty"` + Escalation *int `json:"escalation,omitempty"` + Criteria *Criteria `json:"criteria,omitempty"` + + _rawJSON json.RawMessage +} + +func (t *Timeout) UnmarshalJSON(data []byte) error { + type unmarshaler Timeout + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *t = Timeout(value) + t._rawJSON = json.RawMessage(data) + return nil +} + +func (t *Timeout) String() string { + if len(t._rawJSON) > 0 { + if value, err := core.StringifyJSON(t._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(t); err == nil { + return value + } + return fmt.Sprintf("%#v", t) +} + +type Timeouts struct { + Provider *int `json:"provider,omitempty"` + Channel *int `json:"channel,omitempty"` + + _rawJSON json.RawMessage +} + +func (t *Timeouts) UnmarshalJSON(data []byte) error { + type unmarshaler Timeouts + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *t = Timeouts(value) + t._rawJSON = json.RawMessage(data) + return nil +} + +func (t *Timeouts) String() string { + if len(t._rawJSON) > 0 { + if value, err := core.StringifyJSON(t._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(t); err == nil { + return value + } + return fmt.Sprintf("%#v", t) +} + +type TrackingOverride struct { + Open bool `json:"open"` + + _rawJSON json.RawMessage +} + +func (t *TrackingOverride) UnmarshalJSON(data []byte) error { + type unmarshaler TrackingOverride + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *t = TrackingOverride(value) + t._rawJSON = json.RawMessage(data) + return nil +} + +func (t *TrackingOverride) String() string { + if len(t._rawJSON) > 0 { + if value, err := core.StringifyJSON(t._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(t); err == nil { + return value + } + return fmt.Sprintf("%#v", t) +} + +type Utm struct { + Source *string `json:"source,omitempty"` + Medium *string `json:"medium,omitempty"` + Campaign *string `json:"campaign,omitempty"` + Term *string `json:"term,omitempty"` + Content *string `json:"content,omitempty"` + + _rawJSON json.RawMessage +} + +func (u *Utm) UnmarshalJSON(data []byte) error { + type unmarshaler Utm + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *u = Utm(value) + u._rawJSON = json.RawMessage(data) + return nil +} + +func (u *Utm) String() string { + if len(u._rawJSON) > 0 { + if value, err := core.StringifyJSON(u._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(u); err == nil { + return value + } + return fmt.Sprintf("%#v", u) +} + +type UserRecipient struct { + // Use `tenant_id` instad. + AccountId *string `json:"account_id,omitempty"` + // Context information such as tenant_id to send the notification with. + Context *MessageContext `json:"context,omitempty"` + Data *MessageData `json:"data,omitempty"` + Email *string `json:"email,omitempty"` + // The user's preferred ISO 639-1 language code. + Locale *string `json:"locale,omitempty"` + UserId *string `json:"user_id,omitempty"` + PhoneNumber *string `json:"phone_number,omitempty"` + Preferences *IProfilePreferences `json:"preferences,omitempty"` + // An id of a tenant, [see tenants api docs](https://www.courier.com/docs/reference/tenants). + // Will load brand, default preferences and any other base context data associated with this tenant. + TenantId *string `json:"tenant_id,omitempty"` + + _rawJSON json.RawMessage +} + +func (u *UserRecipient) UnmarshalJSON(data []byte) error { + type unmarshaler UserRecipient + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *u = UserRecipient(value) + u._rawJSON = json.RawMessage(data) + return nil +} + +func (u *UserRecipient) String() string { + if len(u._rawJSON) > 0 { + if value, err := core.StringifyJSON(u._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(u); err == nil { + return value + } + return fmt.Sprintf("%#v", u) +} + +type UserRecipientType struct { + _rawJSON json.RawMessage +} + +func (u *UserRecipientType) UnmarshalJSON(data []byte) error { + type unmarshaler UserRecipientType + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *u = UserRecipientType(value) + u._rawJSON = json.RawMessage(data) + return nil +} + +func (u *UserRecipientType) String() string { + if len(u._rawJSON) > 0 { + if value, err := core.StringifyJSON(u._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(u); err == nil { + return value + } + return fmt.Sprintf("%#v", u) +} + +type WidgetBackground struct { + TopColor *string `json:"topColor,omitempty"` + BottomColor *string `json:"bottomColor,omitempty"` + + _rawJSON json.RawMessage +} + +func (w *WidgetBackground) UnmarshalJSON(data []byte) error { + type unmarshaler WidgetBackground + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *w = WidgetBackground(value) + w._rawJSON = json.RawMessage(data) + return nil +} + +func (w *WidgetBackground) String() string { + if len(w._rawJSON) > 0 { + if value, err := core.StringifyJSON(w._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(w); err == nil { + return value + } + return fmt.Sprintf("%#v", w) +} + +type ChannelIdentifier = string + +type NotificationTemplates struct { + // A UTC timestamp at which notification was created. This is stored as a millisecond representation of the Unix epoch (the time passed since January 1, 1970). + CreatedAt int `json:"created_at"` + // A unique identifier associated with the notification. + Id string `json:"id"` + // Routing strategy used by this notification. + Routing *RoutingStrategy `json:"routing,omitempty"` + // A list of tags attached to the notification. + Tags []*Tag `json:"tags,omitempty"` + // The title of the notification. + Title string `json:"title"` + // A UTC timestamp at which notification was updated. This is stored as a millisecond representation of the Unix epoch (the time passed since January 1, 1970). + UpdatedAt int `json:"updated_at"` + + _rawJSON json.RawMessage +} + +func (n *NotificationTemplates) UnmarshalJSON(data []byte) error { + type unmarshaler NotificationTemplates + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *n = NotificationTemplates(value) + n._rawJSON = json.RawMessage(data) + return nil +} + +func (n *NotificationTemplates) String() string { + if len(n._rawJSON) > 0 { + if value, err := core.StringifyJSON(n._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(n); err == nil { + return value + } + return fmt.Sprintf("%#v", n) +} + +type RoutingStrategy struct { + // The method for selecting channels to send the message with. Value can be either 'single' or 'all'. If not provided will default to 'single' + Method RoutingStrategyMethod `json:"method,omitempty"` + // An array of valid channel identifiers (like email, push, sms, etc.) and additional routing nodes. + Channels []ChannelIdentifier `json:"channels,omitempty"` + + _rawJSON json.RawMessage +} + +func (r *RoutingStrategy) UnmarshalJSON(data []byte) error { + type unmarshaler RoutingStrategy + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *r = RoutingStrategy(value) + r._rawJSON = json.RawMessage(data) + return nil +} + +func (r *RoutingStrategy) String() string { + if len(r._rawJSON) > 0 { + if value, err := core.StringifyJSON(r._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(r); err == nil { + return value + } + return fmt.Sprintf("%#v", r) +} + +type RoutingStrategyMethod string + +const ( + RoutingStrategyMethodAll RoutingStrategyMethod = "all" + RoutingStrategyMethodSingle RoutingStrategyMethod = "single" +) + +func NewRoutingStrategyMethodFromString(s string) (RoutingStrategyMethod, error) { + switch s { + case "all": + return RoutingStrategyMethodAll, nil + case "single": + return RoutingStrategyMethodSingle, nil + } + var t RoutingStrategyMethod + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (r RoutingStrategyMethod) Ptr() *RoutingStrategyMethod { + return &r +} + +type Tag struct { + Data []*TagData `json:"data,omitempty"` + + _rawJSON json.RawMessage +} + +func (t *Tag) UnmarshalJSON(data []byte) error { + type unmarshaler Tag + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *t = Tag(value) + t._rawJSON = json.RawMessage(data) + return nil +} + +func (t *Tag) String() string { + if len(t._rawJSON) > 0 { + if value, err := core.StringifyJSON(t._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(t); err == nil { + return value + } + return fmt.Sprintf("%#v", t) +} + +type TagData struct { + // A unique identifier of the tag. + Id string `json:"id"` + // Name of the tag. + Name string `json:"name"` + + _rawJSON json.RawMessage +} + +func (t *TagData) UnmarshalJSON(data []byte) error { + type unmarshaler TagData + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *t = TagData(value) + t._rawJSON = json.RawMessage(data) + return nil +} + +func (t *TagData) String() string { + if len(t._rawJSON) > 0 { + if value, err := core.StringifyJSON(t._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(t); err == nil { + return value + } + return fmt.Sprintf("%#v", t) +} + +type SubscriptionTopic struct { + // Topic ID + Id string `json:"id"` + Status SubscriptionTopicStatus `json:"status,omitempty"` + + _rawJSON json.RawMessage +} + +func (s *SubscriptionTopic) UnmarshalJSON(data []byte) error { + type unmarshaler SubscriptionTopic + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *s = SubscriptionTopic(value) + s._rawJSON = json.RawMessage(data) + return nil +} + +func (s *SubscriptionTopic) String() string { + if len(s._rawJSON) > 0 { + if value, err := core.StringifyJSON(s._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(s); err == nil { + return value + } + return fmt.Sprintf("%#v", s) +} + +type SubscriptionTopicStatus string + +const ( + SubscriptionTopicStatusOptedOut SubscriptionTopicStatus = "OPTED_OUT" + SubscriptionTopicStatusOptedIn SubscriptionTopicStatus = "OPTED_IN" + SubscriptionTopicStatusRequired SubscriptionTopicStatus = "REQUIRED" +) + +func NewSubscriptionTopicStatusFromString(s string) (SubscriptionTopicStatus, error) { + switch s { + case "OPTED_OUT": + return SubscriptionTopicStatusOptedOut, nil + case "OPTED_IN": + return SubscriptionTopicStatusOptedIn, nil + case "REQUIRED": + return SubscriptionTopicStatusRequired, nil + } + var t SubscriptionTopicStatus + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (s SubscriptionTopicStatus) Ptr() *SubscriptionTopicStatus { + return &s +} diff --git a/users/client/client.go b/users/client/client.go new file mode 100644 index 0000000..36caefb --- /dev/null +++ b/users/client/client.go @@ -0,0 +1,34 @@ +// This file was auto-generated by Fern from our API Definition. + +package client + +import ( + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + preferences "github.com/trycourier/courier-go/v3/users/preferences" + tenants "github.com/trycourier/courier-go/v3/users/tenants" + tokens "github.com/trycourier/courier-go/v3/users/tokens" + http "net/http" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header + + Preferences *preferences.Client + Tenants *tenants.Client + Tokens *tokens.Client +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + Preferences: preferences.NewClient(opts...), + Tenants: tenants.NewClient(opts...), + Tokens: tokens.NewClient(opts...), + } +} diff --git a/users/preferences.go b/users/preferences.go new file mode 100644 index 0000000..4ae2c25 --- /dev/null +++ b/users/preferences.go @@ -0,0 +1,107 @@ +// This file was auto-generated by Fern from our API Definition. + +package users + +import ( + json "encoding/json" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" +) + +type UserPreferencesGetResponse struct { + Topic *TopicPreference `json:"topic,omitempty"` + + _rawJSON json.RawMessage +} + +func (u *UserPreferencesGetResponse) UnmarshalJSON(data []byte) error { + type unmarshaler UserPreferencesGetResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *u = UserPreferencesGetResponse(value) + u._rawJSON = json.RawMessage(data) + return nil +} + +func (u *UserPreferencesGetResponse) String() string { + if len(u._rawJSON) > 0 { + if value, err := core.StringifyJSON(u._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(u); err == nil { + return value + } + return fmt.Sprintf("%#v", u) +} + +type UserPreferencesListResponse struct { + Paging *v3.Paging `json:"paging,omitempty"` + // The Preferences associated with the user_id. + Items []*TopicPreference `json:"items,omitempty"` + + _rawJSON json.RawMessage +} + +func (u *UserPreferencesListResponse) UnmarshalJSON(data []byte) error { + type unmarshaler UserPreferencesListResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *u = UserPreferencesListResponse(value) + u._rawJSON = json.RawMessage(data) + return nil +} + +func (u *UserPreferencesListResponse) String() string { + if len(u._rawJSON) > 0 { + if value, err := core.StringifyJSON(u._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(u); err == nil { + return value + } + return fmt.Sprintf("%#v", u) +} + +type UserPreferencesUpdateResponse struct { + Message string `json:"message"` + + _rawJSON json.RawMessage +} + +func (u *UserPreferencesUpdateResponse) UnmarshalJSON(data []byte) error { + type unmarshaler UserPreferencesUpdateResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *u = UserPreferencesUpdateResponse(value) + u._rawJSON = json.RawMessage(data) + return nil +} + +func (u *UserPreferencesUpdateResponse) String() string { + if len(u._rawJSON) > 0 { + if value, err := core.StringifyJSON(u._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(u); err == nil { + return value + } + return fmt.Sprintf("%#v", u) +} + +type UserPreferencesUpdateParams struct { + Status v3.PreferenceStatus `json:"status,omitempty"` + // The Channels a user has chosen to receive notifications through for this topic + CustomRouting []v3.ChannelClassification `json:"custom_routing,omitempty"` + DefaultStatus v3.PreferenceStatus `json:"default_status,omitempty"` + HasCustomRouting *bool `json:"has_custom_routing,omitempty"` +} diff --git a/users/preferences/client.go b/users/preferences/client.go new file mode 100644 index 0000000..0cdcbd8 --- /dev/null +++ b/users/preferences/client.go @@ -0,0 +1,206 @@ +// This file was auto-generated by Fern from our API Definition. + +package preferences + +import ( + bytes "bytes" + context "context" + json "encoding/json" + errors "errors" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + users "github.com/trycourier/courier-go/v3/users" + io "io" + http "net/http" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +// Fetch all user preferences. +func (c *Client) List( + ctx context.Context, + // A unique identifier associated with the user whose preferences you wish to retrieve. + userId string, + opts ...option.RequestOption, +) (*users.UserPreferencesListResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"users/%v/preferences", userId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *users.UserPreferencesListResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Fetch user preferences for a specific subscription topic. +func (c *Client) Get( + ctx context.Context, + // A unique identifier associated with the user whose preferences you wish to retrieve. + userId string, + // A unique identifier associated with a subscription topic. + topicId string, + opts ...option.RequestOption, +) (*users.UserPreferencesGetResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"users/%v/preferences/%v", userId, topicId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 404: + value := new(v3.NotFoundError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *users.UserPreferencesGetResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Update or Create user preferences for a specific subscription topic. +func (c *Client) Update( + ctx context.Context, + // A unique identifier associated with the user whose preferences you wish to retrieve. + userId string, + // A unique identifier associated with a subscription topic. + topicId string, + request *users.UserPreferencesUpdateParams, + opts ...option.RequestOption, +) (*users.UserPreferencesUpdateResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"users/%v/preferences/%v", userId, topicId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *users.UserPreferencesUpdateResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + Request: request, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} diff --git a/users/tenants.go b/users/tenants.go new file mode 100644 index 0000000..c61df9a --- /dev/null +++ b/users/tenants.go @@ -0,0 +1,151 @@ +// This file was auto-generated by Fern from our API Definition. + +package users + +import ( + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" +) + +type AddUserToSingleTenantsParams struct { + Profile *AddUserToSingleTenantsParamsProfile `json:"profile,omitempty"` +} + +type AddUserToMultipleTenantsParams struct { + Tenants []*UserTenantAssociation `json:"tenants,omitempty"` +} + +type ListTenantsForUserParams struct { + // The number of accounts to return + // (defaults to 20, maximum value of 100) + Limit *int `json:"-"` + // Value of next_page from previous response + StartingAfter *int `json:"-"` +} + +type AddUserToSingleTenantsParamsProfile struct { + Title string `json:"title"` + // Email Address + Email string `json:"email"` + // A valid phone number + PhoneNumber string `json:"phone_number"` + // The user's preferred ISO 639-1 language code. + Locale string `json:"locale"` + // Additional provider specific fields may be specified. + AdditionalFields map[string]interface{} `json:"additional_fields,omitempty"` + + _rawJSON json.RawMessage +} + +func (a *AddUserToSingleTenantsParamsProfile) UnmarshalJSON(data []byte) error { + type unmarshaler AddUserToSingleTenantsParamsProfile + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *a = AddUserToSingleTenantsParamsProfile(value) + a._rawJSON = json.RawMessage(data) + return nil +} + +func (a *AddUserToSingleTenantsParamsProfile) String() string { + if len(a._rawJSON) > 0 { + if value, err := core.StringifyJSON(a._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(a); err == nil { + return value + } + return fmt.Sprintf("%#v", a) +} + +type ListTenantsForUserResponse struct { + Items *UserTenantAssociation `json:"items,omitempty"` + // Set to true when there are more pages that can be retrieved. + HasMore bool `json:"has_more"` + // A url that may be used to generate these results. + Url string `json:"url"` + // A url that may be used to generate fetch the next set of results. + // Defined only when `has_more` is set to true + NextUrl *string `json:"next_url,omitempty"` + // A pointer to the next page of results. Defined + // only when `has_more` is set to true + Cursor *string `json:"cursor,omitempty"` + // Always set to `list`. Represents the type of this object. + type_ string + + _rawJSON json.RawMessage +} + +func (l *ListTenantsForUserResponse) Type() string { + return l.type_ +} + +func (l *ListTenantsForUserResponse) UnmarshalJSON(data []byte) error { + type unmarshaler ListTenantsForUserResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *l = ListTenantsForUserResponse(value) + l.type_ = "list" + l._rawJSON = json.RawMessage(data) + return nil +} + +func (l *ListTenantsForUserResponse) MarshalJSON() ([]byte, error) { + type embed ListTenantsForUserResponse + var marshaler = struct { + embed + Type string `json:"type"` + }{ + embed: embed(*l), + Type: "list", + } + return json.Marshal(marshaler) +} + +func (l *ListTenantsForUserResponse) String() string { + if len(l._rawJSON) > 0 { + if value, err := core.StringifyJSON(l._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(l); err == nil { + return value + } + return fmt.Sprintf("%#v", l) +} + +type UserTenantAssociation struct { + // Tenant ID the user association is tied to. + TenantId string `json:"tenant_id"` + Profile map[string]interface{} `json:"profile,omitempty"` + + _rawJSON json.RawMessage +} + +func (u *UserTenantAssociation) UnmarshalJSON(data []byte) error { + type unmarshaler UserTenantAssociation + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *u = UserTenantAssociation(value) + u._rawJSON = json.RawMessage(data) + return nil +} + +func (u *UserTenantAssociation) String() string { + if len(u._rawJSON) > 0 { + if value, err := core.StringifyJSON(u._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(u); err == nil { + return value + } + return fmt.Sprintf("%#v", u) +} diff --git a/users/tenants/client.go b/users/tenants/client.go new file mode 100644 index 0000000..348e474 --- /dev/null +++ b/users/tenants/client.go @@ -0,0 +1,194 @@ +// This file was auto-generated by Fern from our API Definition. + +package tenants + +import ( + context "context" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + users "github.com/trycourier/courier-go/v3/users" + http "net/http" + url "net/url" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +// This endpoint is used to add a user to +// multiple tenants in one call. +// A custom profile can also be supplied for each tenant. +// This profile will be merged with the user's main +// profile when sending to the user with that tenant. +func (c *Client) AddMultple( + ctx context.Context, + // The user's ID. This can be any uniquely identifiable string. + userId string, + request *users.AddUserToMultipleTenantsParams, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"users/%v/tenants", userId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + Request: request, + }, + ); err != nil { + return err + } + return nil +} + +// This endpoint is used to add a single tenant. +// +// A custom profile can also be supplied with the tenant. +// This profile will be merged with the user's main profile +// when sending to the user with that tenant. +func (c *Client) Add( + ctx context.Context, + // Id of the user to be added to the supplied tenant. + userId string, + // Id of the tenant the user should be added to. + tenantId string, + request *users.AddUserToSingleTenantsParams, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"users/%v/tenants/%v", userId, tenantId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + Request: request, + }, + ); err != nil { + return err + } + return nil +} + +// Removes a user from the supplied tenant. +func (c *Client) Remove( + ctx context.Context, + // Id of the user to be removed from the supplied tenant. + userId string, + // Id of the tenant the user should be removed from. + tenantId string, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"users/%v/tenants/%v", userId, tenantId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodDelete, + Headers: headers, + Client: options.HTTPClient, + }, + ); err != nil { + return err + } + return nil +} + +// Returns a paginated list of user tenant associations. +func (c *Client) List( + ctx context.Context, + // Id of the user to retrieve all associated tenants for. + userId string, + request *users.ListTenantsForUserParams, + opts ...option.RequestOption, +) (*users.ListTenantsForUserResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"users/%v/tenants", userId) + + queryParams := make(url.Values) + if request.Limit != nil { + queryParams.Add("limit", fmt.Sprintf("%v", *request.Limit)) + } + if request.StartingAfter != nil { + queryParams.Add("starting_after", fmt.Sprintf("%v", *request.StartingAfter)) + } + if len(queryParams) > 0 { + endpointURL += "?" + queryParams.Encode() + } + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + var response *users.ListTenantsForUserResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + }, + ); err != nil { + return nil, err + } + return response, nil +} diff --git a/users/tokens.go b/users/tokens.go new file mode 100644 index 0000000..5b70ed0 --- /dev/null +++ b/users/tokens.go @@ -0,0 +1,122 @@ +// This file was auto-generated by Fern from our API Definition. + +package users + +import ( + json "encoding/json" + fmt "fmt" + core "github.com/trycourier/courier-go/v3/core" +) + +// A list of tokens registered with the user. +type GetAllTokensResponse = []*UserToken + +type GetUserTokenResponse struct { + // Full body of the token. Must match token in URL. + Token *string `json:"token,omitempty"` + ProviderKey ProviderKey `json:"provider_key,omitempty"` + // ISO 8601 formatted date the token expires. Defaults to 2 months. Set to false to disable expiration. + ExpiryDate *ExpiryDate `json:"expiry_date,omitempty"` + // Properties sent to the provider along with the token + Properties interface{} `json:"properties,omitempty"` + // Information about the device the token is associated with. + Device *Device `json:"device,omitempty"` + // Information about the device the token is associated with. + Tracking *Tracking `json:"tracking,omitempty"` + Status *TokenStatus `json:"status,omitempty"` + // The reason for the token status. + StatusReason *string `json:"status_reason,omitempty"` + + _rawJSON json.RawMessage +} + +func (g *GetUserTokenResponse) UnmarshalJSON(data []byte) error { + type unmarshaler GetUserTokenResponse + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *g = GetUserTokenResponse(value) + g._rawJSON = json.RawMessage(data) + return nil +} + +func (g *GetUserTokenResponse) String() string { + if len(g._rawJSON) > 0 { + if value, err := core.StringifyJSON(g._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(g); err == nil { + return value + } + return fmt.Sprintf("%#v", g) +} + +type PatchUserTokenOpts struct { + Patch []*PatchOperation `json:"patch,omitempty"` + + _rawJSON json.RawMessage +} + +func (p *PatchUserTokenOpts) UnmarshalJSON(data []byte) error { + type unmarshaler PatchUserTokenOpts + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *p = PatchUserTokenOpts(value) + p._rawJSON = json.RawMessage(data) + return nil +} + +func (p *PatchUserTokenOpts) String() string { + if len(p._rawJSON) > 0 { + if value, err := core.StringifyJSON(p._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(p); err == nil { + return value + } + return fmt.Sprintf("%#v", p) +} + +type UserToken struct { + // Full body of the token. Must match token in URL. + Token *string `json:"token,omitempty"` + ProviderKey ProviderKey `json:"provider_key,omitempty"` + // ISO 8601 formatted date the token expires. Defaults to 2 months. Set to false to disable expiration. + ExpiryDate *ExpiryDate `json:"expiry_date,omitempty"` + // Properties sent to the provider along with the token + Properties interface{} `json:"properties,omitempty"` + // Information about the device the token is associated with. + Device *Device `json:"device,omitempty"` + // Information about the device the token is associated with. + Tracking *Tracking `json:"tracking,omitempty"` + + _rawJSON json.RawMessage +} + +func (u *UserToken) UnmarshalJSON(data []byte) error { + type unmarshaler UserToken + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *u = UserToken(value) + u._rawJSON = json.RawMessage(data) + return nil +} + +func (u *UserToken) String() string { + if len(u._rawJSON) > 0 { + if value, err := core.StringifyJSON(u._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(u); err == nil { + return value + } + return fmt.Sprintf("%#v", u) +} diff --git a/users/tokens/client.go b/users/tokens/client.go new file mode 100644 index 0000000..860d261 --- /dev/null +++ b/users/tokens/client.go @@ -0,0 +1,316 @@ +// This file was auto-generated by Fern from our API Definition. + +package tokens + +import ( + bytes "bytes" + context "context" + json "encoding/json" + errors "errors" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" + option "github.com/trycourier/courier-go/v3/option" + users "github.com/trycourier/courier-go/v3/users" + io "io" + http "net/http" +) + +type Client struct { + baseURL string + caller *core.Caller + header http.Header +} + +func NewClient(opts ...option.RequestOption) *Client { + options := core.NewRequestOptions(opts...) + return &Client{ + baseURL: options.BaseURL, + caller: core.NewCaller(options.HTTPClient), + header: options.ToHeader(), + } +} + +// Adds multiple tokens to a user and overwrites matching existing tokens. +func (c *Client) AddMultiple( + ctx context.Context, + // The user's ID. This can be any uniquely identifiable string. + userId string, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"users/%v/tokens", userId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return err + } + return nil +} + +// Adds a single token to a user and overwrites a matching existing token. +func (c *Client) Add( + ctx context.Context, + // The user's ID. This can be any uniquely identifiable string. + userId string, + // The full token string. + token string, + request *users.UserToken, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"users/%v/tokens/%v", userId, token) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPut, + Headers: headers, + Client: options.HTTPClient, + Request: request, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return err + } + return nil +} + +// Apply a JSON Patch (RFC 6902) to the specified token. +func (c *Client) Update( + ctx context.Context, + // The user's ID. This can be any uniquely identifiable string. + userId string, + // The full token string. + token string, + request *users.PatchUserTokenOpts, + opts ...option.RequestOption, +) error { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"users/%v/tokens/%v", userId, token) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodPatch, + Headers: headers, + Client: options.HTTPClient, + Request: request, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return err + } + return nil +} + +// Get single token available for a `:token` +func (c *Client) Get( + ctx context.Context, + // The user's ID. This can be any uniquely identifiable string. + userId string, + // The full token string. + token string, + opts ...option.RequestOption, +) (*users.GetUserTokenResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"users/%v/tokens/%v", userId, token) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response *users.GetUserTokenResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} + +// Gets all tokens available for a :user_id +func (c *Client) List( + ctx context.Context, + // The user's ID. This can be any uniquely identifiable string. + userId string, + opts ...option.RequestOption, +) (users.GetAllTokensResponse, error) { + options := core.NewRequestOptions(opts...) + + baseURL := "https://api.courier.com" + if c.baseURL != "" { + baseURL = c.baseURL + } + if options.BaseURL != "" { + baseURL = options.BaseURL + } + endpointURL := fmt.Sprintf(baseURL+"/"+"users/%v/tokens", userId) + + headers := core.MergeHeaders(c.header.Clone(), options.ToHeader()) + + errorDecoder := func(statusCode int, body io.Reader) error { + raw, err := io.ReadAll(body) + if err != nil { + return err + } + apiError := core.NewAPIError(statusCode, errors.New(string(raw))) + decoder := json.NewDecoder(bytes.NewReader(raw)) + switch statusCode { + case 400: + value := new(v3.BadRequestError) + value.APIError = apiError + if err := decoder.Decode(value); err != nil { + return apiError + } + return value + } + return apiError + } + + var response users.GetAllTokensResponse + if err := c.caller.Call( + ctx, + &core.CallParams{ + URL: endpointURL, + Method: http.MethodGet, + Headers: headers, + Client: options.HTTPClient, + Response: &response, + ErrorDecoder: errorDecoder, + }, + ); err != nil { + return nil, err + } + return response, nil +} diff --git a/users/types.go b/users/types.go new file mode 100644 index 0000000..5c57669 --- /dev/null +++ b/users/types.go @@ -0,0 +1,451 @@ +// This file was auto-generated by Fern from our API Definition. + +package users + +import ( + json "encoding/json" + fmt "fmt" + v3 "github.com/trycourier/courier-go/v3" + core "github.com/trycourier/courier-go/v3/core" +) + +type TopicPreference struct { + // The Channels a user has chosen to receive notifications through for this topic + CustomRouting []v3.ChannelClassification `json:"custom_routing,omitempty"` + DefaultStatus v3.PreferenceStatus `json:"default_status,omitempty"` + HasCustomRouting *bool `json:"has_custom_routing,omitempty"` + Status v3.PreferenceStatus `json:"status,omitempty"` + TopicId string `json:"topic_id"` + TopicName string `json:"topic_name"` + + _rawJSON json.RawMessage +} + +func (t *TopicPreference) UnmarshalJSON(data []byte) error { + type unmarshaler TopicPreference + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *t = TopicPreference(value) + t._rawJSON = json.RawMessage(data) + return nil +} + +func (t *TopicPreference) String() string { + if len(t._rawJSON) > 0 { + if value, err := core.StringifyJSON(t._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(t); err == nil { + return value + } + return fmt.Sprintf("%#v", t) +} + +type DeleteUserTokenOpts struct { + UserId string `json:"user_id"` + Token string `json:"token"` + + _rawJSON json.RawMessage +} + +func (d *DeleteUserTokenOpts) UnmarshalJSON(data []byte) error { + type unmarshaler DeleteUserTokenOpts + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *d = DeleteUserTokenOpts(value) + d._rawJSON = json.RawMessage(data) + return nil +} + +func (d *DeleteUserTokenOpts) String() string { + if len(d._rawJSON) > 0 { + if value, err := core.StringifyJSON(d._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(d); err == nil { + return value + } + return fmt.Sprintf("%#v", d) +} + +type Device struct { + // Id of the application the token is used for + AppId *string `json:"app_id,omitempty"` + // Id of the advertising identifier + AdId *string `json:"ad_id,omitempty"` + // Id of the device the token is associated with + DeviceId *string `json:"device_id,omitempty"` + // The device platform i.e. android, ios, web + Platform *string `json:"platform,omitempty"` + // The device manufacturer + Manufacturer *string `json:"manufacturer,omitempty"` + // The device model + Model *string `json:"model,omitempty"` + + _rawJSON json.RawMessage +} + +func (d *Device) UnmarshalJSON(data []byte) error { + type unmarshaler Device + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *d = Device(value) + d._rawJSON = json.RawMessage(data) + return nil +} + +func (d *Device) String() string { + if len(d._rawJSON) > 0 { + if value, err := core.StringifyJSON(d._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(d); err == nil { + return value + } + return fmt.Sprintf("%#v", d) +} + +type ExpiryDate struct { + typeName string + String string + Boolean bool +} + +func NewExpiryDateFromString(value string) *ExpiryDate { + return &ExpiryDate{typeName: "string", String: value} +} + +func NewExpiryDateFromBoolean(value bool) *ExpiryDate { + return &ExpiryDate{typeName: "boolean", Boolean: value} +} + +func (e *ExpiryDate) UnmarshalJSON(data []byte) error { + var valueString string + if err := json.Unmarshal(data, &valueString); err == nil { + e.typeName = "string" + e.String = valueString + return nil + } + var valueBoolean bool + if err := json.Unmarshal(data, &valueBoolean); err == nil { + e.typeName = "boolean" + e.Boolean = valueBoolean + return nil + } + return fmt.Errorf("%s cannot be deserialized as a %T", data, e) +} + +func (e ExpiryDate) MarshalJSON() ([]byte, error) { + switch e.typeName { + default: + return nil, fmt.Errorf("invalid type %s in %T", e.typeName, e) + case "string": + return json.Marshal(e.String) + case "boolean": + return json.Marshal(e.Boolean) + } +} + +type ExpiryDateVisitor interface { + VisitString(string) error + VisitBoolean(bool) error +} + +func (e *ExpiryDate) Accept(visitor ExpiryDateVisitor) error { + switch e.typeName { + default: + return fmt.Errorf("invalid type %s in %T", e.typeName, e) + case "string": + return visitor.VisitString(e.String) + case "boolean": + return visitor.VisitBoolean(e.Boolean) + } +} + +type GetUserTokenOpts struct { + UserId string `json:"user_id"` + Token string `json:"token"` + + _rawJSON json.RawMessage +} + +func (g *GetUserTokenOpts) UnmarshalJSON(data []byte) error { + type unmarshaler GetUserTokenOpts + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *g = GetUserTokenOpts(value) + g._rawJSON = json.RawMessage(data) + return nil +} + +func (g *GetUserTokenOpts) String() string { + if len(g._rawJSON) > 0 { + if value, err := core.StringifyJSON(g._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(g); err == nil { + return value + } + return fmt.Sprintf("%#v", g) +} + +type GetUserTokensOpts struct { + UserId string `json:"user_id"` + + _rawJSON json.RawMessage +} + +func (g *GetUserTokensOpts) UnmarshalJSON(data []byte) error { + type unmarshaler GetUserTokensOpts + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *g = GetUserTokensOpts(value) + g._rawJSON = json.RawMessage(data) + return nil +} + +func (g *GetUserTokensOpts) String() string { + if len(g._rawJSON) > 0 { + if value, err := core.StringifyJSON(g._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(g); err == nil { + return value + } + return fmt.Sprintf("%#v", g) +} + +type PatchOp string + +const ( + PatchOpReplace PatchOp = "replace" + PatchOpAdd PatchOp = "add" + PatchOpRemove PatchOp = "remove" + PatchOpCopy PatchOp = "copy" + PatchOpMove PatchOp = "move" + PatchOpTest PatchOp = "test" +) + +func NewPatchOpFromString(s string) (PatchOp, error) { + switch s { + case "replace": + return PatchOpReplace, nil + case "add": + return PatchOpAdd, nil + case "remove": + return PatchOpRemove, nil + case "copy": + return PatchOpCopy, nil + case "move": + return PatchOpMove, nil + case "test": + return PatchOpTest, nil + } + var t PatchOp + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (p PatchOp) Ptr() *PatchOp { + return &p +} + +type PatchOperation struct { + // The operation to perform. + Op string `json:"op"` + // The JSON path specifying the part of the profile to operate on. + Path string `json:"path"` + // The value for the operation. + Value *string `json:"value,omitempty"` + + _rawJSON json.RawMessage +} + +func (p *PatchOperation) UnmarshalJSON(data []byte) error { + type unmarshaler PatchOperation + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *p = PatchOperation(value) + p._rawJSON = json.RawMessage(data) + return nil +} + +func (p *PatchOperation) String() string { + if len(p._rawJSON) > 0 { + if value, err := core.StringifyJSON(p._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(p); err == nil { + return value + } + return fmt.Sprintf("%#v", p) +} + +type ProviderKey string + +const ( + ProviderKeyFirebaseFcm ProviderKey = "firebase-fcm" + ProviderKeyApn ProviderKey = "apn" + ProviderKeyExpo ProviderKey = "expo" + ProviderKeyOnesignal ProviderKey = "onesignal" +) + +func NewProviderKeyFromString(s string) (ProviderKey, error) { + switch s { + case "firebase-fcm": + return ProviderKeyFirebaseFcm, nil + case "apn": + return ProviderKeyApn, nil + case "expo": + return ProviderKeyExpo, nil + case "onesignal": + return ProviderKeyOnesignal, nil + } + var t ProviderKey + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (p ProviderKey) Ptr() *ProviderKey { + return &p +} + +type PutUserTokenOpts struct { + UserId string `json:"user_id"` + Token *UserToken `json:"token,omitempty"` + + _rawJSON json.RawMessage +} + +func (p *PutUserTokenOpts) UnmarshalJSON(data []byte) error { + type unmarshaler PutUserTokenOpts + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *p = PutUserTokenOpts(value) + p._rawJSON = json.RawMessage(data) + return nil +} + +func (p *PutUserTokenOpts) String() string { + if len(p._rawJSON) > 0 { + if value, err := core.StringifyJSON(p._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(p); err == nil { + return value + } + return fmt.Sprintf("%#v", p) +} + +type PutUserTokensOpts struct { + UserId string `json:"user_id"` + Tokens []*UserToken `json:"tokens,omitempty"` + + _rawJSON json.RawMessage +} + +func (p *PutUserTokensOpts) UnmarshalJSON(data []byte) error { + type unmarshaler PutUserTokensOpts + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *p = PutUserTokensOpts(value) + p._rawJSON = json.RawMessage(data) + return nil +} + +func (p *PutUserTokensOpts) String() string { + if len(p._rawJSON) > 0 { + if value, err := core.StringifyJSON(p._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(p); err == nil { + return value + } + return fmt.Sprintf("%#v", p) +} + +type TokenStatus string + +const ( + TokenStatusActive TokenStatus = "active" + TokenStatusUnknown TokenStatus = "unknown" + TokenStatusFailed TokenStatus = "failed" + TokenStatusRevoked TokenStatus = "revoked" +) + +func NewTokenStatusFromString(s string) (TokenStatus, error) { + switch s { + case "active": + return TokenStatusActive, nil + case "unknown": + return TokenStatusUnknown, nil + case "failed": + return TokenStatusFailed, nil + case "revoked": + return TokenStatusRevoked, nil + } + var t TokenStatus + return "", fmt.Errorf("%s is not a valid %T", s, t) +} + +func (t TokenStatus) Ptr() *TokenStatus { + return &t +} + +type Tracking struct { + // The operating system version + OsVersion *string `json:"os_version,omitempty"` + // The IP address of the device + Ip *string `json:"ip,omitempty"` + // The latitude of the device + Lat *string `json:"lat,omitempty"` + // The longitude of the device + Long *string `json:"long,omitempty"` + + _rawJSON json.RawMessage +} + +func (t *Tracking) UnmarshalJSON(data []byte) error { + type unmarshaler Tracking + var value unmarshaler + if err := json.Unmarshal(data, &value); err != nil { + return err + } + *t = Tracking(value) + t._rawJSON = json.RawMessage(data) + return nil +} + +func (t *Tracking) String() string { + if len(t._rawJSON) > 0 { + if value, err := core.StringifyJSON(t._rawJSON); err == nil { + return value + } + } + if value, err := core.StringifyJSON(t); err == nil { + return value + } + return fmt.Sprintf("%#v", t) +} diff --git a/v2/api.go b/v2/api.go deleted file mode 100644 index 05917e8..0000000 --- a/v2/api.go +++ /dev/null @@ -1,118 +0,0 @@ -package courier - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" -) - -// APIConfiguration represents the core data needed to communicate with the Courier API -type APIConfiguration struct { - AuthToken string - BaseURL string - SDKVersion string -} - -// HTTPError is a customer error returned when the API doesn't respond with a 2XX -type HTTPError struct { - StatusCode int - ErrorMessage *string -} - -func (err *HTTPError) Error() string { - if err.ErrorMessage == nil { - return fmt.Sprintf("HTTP Error %d: %s", err.StatusCode, "") - } - return fmt.Sprintf("HTTP Error %d: %s", err.StatusCode, *err.ErrorMessage) -} - -// SendRequestWithJSON wraps HTTPSendBytes -func (api *APIConfiguration) SendRequestWithJSON(ctx context.Context, method string, relativePath string, body interface{}, response interface{}) error { - jsonBody, err := json.Marshal(body) - if err != nil { - return err - } - - bytes, err := api.SendRequestWithBytes(ctx, method, relativePath, jsonBody) - if err != nil { - return err - } - - err = json.Unmarshal(bytes, &response) - if err != nil { - return err - } - - return nil -} - -// SendRequestWithMaps wraps HTTPSendBytes -func (api *APIConfiguration) SendRequestWithMaps(ctx context.Context, method string, relativePath string, body map[string]interface{}) (map[string]json.RawMessage, error) { - jsonBody, err := json.Marshal(body) - if err != nil { - return nil, err - } - - bytes, err := api.SendRequestWithBytes(ctx, method, relativePath, jsonBody) - if err != nil { - return nil, err - } - - var objmap map[string]json.RawMessage - err = json.Unmarshal(bytes, &objmap) - if err != nil { - return nil, err - } - return objmap, nil -} - -// SendRequestWithBytes wraps SendRequestWithReader -func (api *APIConfiguration) SendRequestWithBytes(ctx context.Context, method string, relativePath string, body []byte) ([]byte, error) { - buf := bytes.NewReader(body) - return api.SendRequestWithReader(ctx, method, relativePath, buf) -} - -// SendRequestWithReader wraps HTTPRequest -func (api *APIConfiguration) SendRequestWithReader(ctx context.Context, method string, relativePath string, body io.Reader) ([]byte, error) { - fullyQualifiedURL := api.BaseURL + relativePath - if method == "GET" { - body = nil - } - req, err := http.NewRequestWithContext(ctx, method, fullyQualifiedURL, body) - if err != nil { - return nil, err - } - return api.ExecuteRequest(req) -} - -// ExecuteRequest issues an HTTP request and sets headers expected by the Courier API -func (api *APIConfiguration) ExecuteRequest(req *http.Request) ([]byte, error) { - req.Header.Set("Authorization", "Bearer "+api.AuthToken) - req.Header.Set("Content-Type", "application/json") - req.Header.Set("User-Agent", "courier-go/"+api.SDKVersion) - - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - return nil, err - } - - defer resp.Body.Close() - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - // Success is indicated with 2xx status codes - success := resp.StatusCode >= 200 && resp.StatusCode < 300 - if !success { - errMessage := string(body[:]) - return nil, &HTTPError{resp.StatusCode, &errMessage} - } - return body, nil -} diff --git a/v2/audiences.go b/v2/audiences.go deleted file mode 100644 index 381597d..0000000 --- a/v2/audiences.go +++ /dev/null @@ -1,215 +0,0 @@ -package courier - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "net/http" -) - -type SingleFilter struct { - Operator string `json:"operator"` - Path string `json:"path"` - Value string `json:"value"` -} - -type NestedFilter struct { - Operator string `json:"operator"` - Rules []SingleFilter `json:"rules"` -} - -type Audience struct { - Description string `json:"description,omitempty"` - Filter interface{} `json:"filter"` - Name string `json:"name,omitempty"` -} - -type AudienceResponseBody struct { - Id string `json:"id"` - Description string `json:"description"` - CreatedAt string `json:"created_at"` - Filter interface{} `json:"filter"` - Name string `json:"name"` - UpdatedAt string `json:"updated_at"` -} - -type AudienceResponse struct { - Audience AudienceResponseBody `json:"audience"` -} - -type AudienceMember struct { - AudienceId string `json:"audience_id"` - AddedAt string `json:"added_at"` - AudienceVersion int `json:"audience_version"` - MemberId string `json:"member_id"` - Reason string `json:"reason"` -} - -type GetAudienceMembersResponse struct { - Items []*AudienceMember `json:"items"` - Paging *PagingResponse `json:"paging"` -} - -type GetAudiencesResponse struct { - Items []*AudienceResponseBody `json:"items"` - Paging *PagingResponse -} - -func (c *Client) PutAudience(ctx context.Context, audienceId string, audience Audience) (*AudienceResponse, error) { - if audienceId == "" { - return nil, errors.New("Audience ID is required") - } - - _, singleFilterOk := audience.Filter.(SingleFilter) - _, nestedFilterOk := audience.Filter.(NestedFilter) - - if !singleFilterOk && !nestedFilterOk { - return nil, errors.New("Audience filter must be of type SingleFilter or NestFilter") - } - - reqBodyBytes := new(bytes.Buffer) - json.NewEncoder(reqBodyBytes).Encode(audience) - - jsonBody, err := json.Marshal(audience) - - if err != nil { - return nil, err - } - - bytes, err := c.API.SendRequestWithBytes(ctx, http.MethodPut, fmt.Sprintf("/audiences/%s", audienceId), jsonBody) - - if err != nil { - return nil, err - } - - var data AudienceResponse - - err = json.Unmarshal(bytes, &data) - - if err != nil { - return nil, err - } - - return &data, nil -} - -func (c *Client) GetAudience(ctx context.Context, audienceId string) (*AudienceResponseBody, error) { - if audienceId == "" { - return nil, errors.New("Audience ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/audiences/%s", audienceId) - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - - if err != nil { - return nil, err - } - - bytes, err := c.API.ExecuteRequest(req) - - if err != nil { - return nil, errors.New(fmt.Sprintf("AudienceId %s, not found", audienceId)) - } - - var data AudienceResponseBody - - err = json.Unmarshal(bytes, &data) - - if err != nil { - return nil, err - } - - return &data, nil -} - -func (c *Client) GetAudienceMembers(ctx context.Context, audienceId string, cursor string) (*GetAudienceMembersResponse, error) { - if audienceId == "" { - return nil, errors.New("Audience ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/audiences/%s/members", audienceId) - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - - if err != nil { - return nil, err - } - - q := req.URL.Query() - if cursor != "" { - q.Add("cursor", cursor) - } - - bytes, err := c.API.ExecuteRequest(req) - - if err != nil { - return nil, err - } - - var data GetAudienceMembersResponse - - err = json.Unmarshal(bytes, &data) - - if err != nil { - return nil, err - } - - return &data, nil -} - -func (c *Client) GetAudiences(ctx context.Context, cursor string) (*GetAudiencesResponse, error) { - - url := fmt.Sprintf(c.API.BaseURL + "/audiences") - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - - if err != nil { - return nil, err - } - - q := req.URL.Query() - if cursor != "" { - q.Add("cursor", cursor) - } - - bytes, err := c.API.ExecuteRequest(req) - - if err != nil { - return nil, err - } - - var data GetAudiencesResponse - - err = json.Unmarshal(bytes, &data) - - if err != nil { - return nil, err - } - - return &data, nil -} - -func (c *Client) DeleteAudience(ctx context.Context, audienceId string) error { - if audienceId == "" { - return errors.New("Audience ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/audiences/%s", audienceId) - - req, err := http.NewRequestWithContext(ctx, "DELETE", url, nil) - - if err != nil { - return err - } - - _, err = c.API.ExecuteRequest(req) - - if err != nil { - return errors.New(fmt.Sprintf("AudienceId %s, not found", audienceId)) - } - - return nil -} diff --git a/v2/audiences_test.go b/v2/audiences_test.go deleted file mode 100644 index 4bb11b1..0000000 --- a/v2/audiences_test.go +++ /dev/null @@ -1,198 +0,0 @@ -package courier_test - -import ( - "context" - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/trycourier/courier-go/v2" -) - -func TestPutAudience(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, "/audiences/software-engineers-from-sf", req.URL.String()) - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "audience": { - "id": "software-engineers-from-sf", - "name": "Software Engineers From SF", - "description": "Updated descriptionss", - "created_at": "2022-03-22T19:07:32.066Z", - "updated_at": "2022-03-24T00:32:11.122Z", - "filter": { - "path": "title", - "value": "Software Engineer", - "operator": "EQ" - } - } - }` - _, _ = rw.Write([]byte(rsp)) - - })) - defer server.Close() - - t.Run("Put Audience Happy Path", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - - audiencePutResponse, err := client.PutAudience(context.Background(), "software-engineers-from-sf", courier.Audience{ - Description: "Updated descriptionss", - Name: "Software Engineers From SF", - Filter: courier.SingleFilter{ - Operator: "EQ", - Path: "title", - Value: "Software Engineer", - }, - }) - assert.Nil(t, err) - - assert.Equal(t, "software-engineers-from-sf", audiencePutResponse.Audience.Id) - }) -} - -func TestGetAudience(t *testing.T) { - expectedResponseID := "123456789" - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, "/audiences/123456789", req.URL.String()) - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"id\" : \"%s\" }", expectedResponseID))) - if writeErr != nil { - t.Error(writeErr) - } - })) - defer server.Close() - - t.Run("Get Audience Happy Path", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - response, err := client.GetAudience(context.Background(), "123456789") - assert.Nil(t, err) - assert.Equal(t, expectedResponseID, response.Id) - }) - - t.Run("should throw Audience ID required if empty", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - _, err := client.GetAudience(context.Background(), "") - assert.Equal(t, err.Error(), "Audience ID is required") - }) -} - -func TestGetAudienceMembers(t *testing.T) { - expectedMemberId := "test-member-id" - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, "/audiences/123456789/members", req.URL.String()) - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "items": [ - { - "added_at": "2022-03-22T19:13:13.137Z", - "audience_id": "software-engineers-from-sf", - "audience_version": 3, - "member_id": "test-member-id", - "reason": "EQ('title', 'Software Engineer') => true" - } - ], - "paging": { - "cursor": null, - "more": false - } - }` - _, _ = rw.Write([]byte(rsp)) - })) - defer server.Close() - - t.Run("Get Audience Members Happy Path", func(t *testing.T) { - expectedAudienceVersion := 3 - client := courier.CreateClient("key", &server.URL) - response, err := client.GetAudienceMembers(context.Background(), "123456789", "") - assert.Nil(t, err) - assert.Equal(t, expectedMemberId, response.Items[0].MemberId) - assert.Equal(t, expectedAudienceVersion, response.Items[0].AudienceVersion) - }) -} - -func TestAudienceMembersError(t *testing.T) { - expectedResponseID := "123456789" - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"id\" : \"%s\" }", expectedResponseID))) - if writeErr != nil { - t.Error(writeErr) - } - })) - defer server.Close() - - t.Run("should throw Audience ID required if empty", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - _, err := client.GetAudience(context.Background(), "") - assert.Equal(t, err.Error(), "Audience ID is required") - }) -} - -func TestGetAudiences(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, "/audiences", req.URL.String()) - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "items": [ - { - "created_at": "2022-03-22T19:07:32.066Z", - "description": "Updated descriptionss", - "id": "software-engineers-from-sf", - "name": "Software Engineers From SF", - "filter": { - "path": "title", - "value": "Software Engineer", - "operator": "EQ" - }, - "updated_at": "2022-03-24T05:30:58.659Z" - } - ], - "paging": { - "cursor": null, - "more": false - } - }` - _, _ = rw.Write([]byte(rsp)) - })) - defer server.Close() - - t.Run("Get Audiences Happy path", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - response, err := client.GetAudiences(context.Background(), "") - assert.Nil(t, err) - assert.Equal(t, "software-engineers-from-sf", response.Items[0].Id) - assert.Equal(t, "Software Engineers From SF", response.Items[0].Name) - }) -} - -func TestDeleteAudience(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, "/audiences/123456789", req.URL.String()) - rw.Header().Add("Content-Type", "application/json") - rw.WriteHeader(http.StatusNoContent) - })) - defer server.Close() - - t.Run("Delete Audience Happy Path", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - err := client.DeleteAudience(context.Background(), "123456789") - assert.NoError(t, err) - }) - - t.Run("should throw Audience ID required if empty", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - err := client.DeleteAudience(context.Background(), "") - assert.EqualError(t, err, "Audience ID is required") - }) -} diff --git a/v2/audit_events.go b/v2/audit_events.go deleted file mode 100644 index 338bc3a..0000000 --- a/v2/audit_events.go +++ /dev/null @@ -1,92 +0,0 @@ -package courier - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "net/http" -) - -// AuditEventActor is the type for audit event actor entity -type AuditEventActor struct { - Email string `json:"email"` - Id string `json:"id"` -} - -// AuditEventTarget is the type for audit event target entity -type AuditEventTarget struct { - Email string `json:"email"` - Id string `json:"id"` -} - -// AuditEvent is the type for audit event entity -type AuditEvent struct { - AuditEventId string `json:"auditEventId"` - Source string `json:"source"` - Timestamp string `json:"timestamp"` - Type string `json:"type"` - Actor *AuditEventActor - Target *AuditEventTarget -} - -// ListAuditEventsResponse is type for the GET /audit-events response -type ListAuditEventsResponse struct { - Results []AuditEvent `json:"results"` - Paging *PagingResponse -} - -// GetAuditEvent calls the GET /audit-events/:auditEventId endpoint of the Courier API -func (c *Client) GetAuditEvent(ctx context.Context, auditEventID string) (*AuditEvent, error) { - if auditEventID == "" { - return nil, errors.New("audit Event ID is required") - } - url := fmt.Sprintf(c.API.BaseURL+"/audit-events/%s", auditEventID) - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data AuditEvent - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// ListAuditEvents calls the GET /audit-events endpoint of the Courier API -func (c *Client) ListAuditEvents(ctx context.Context, cursor string) (*ListAuditEventsResponse, error) { - url := fmt.Sprintf(c.API.BaseURL + "/audit-events") - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - q := req.URL.Query() - if cursor != "" { - q.Add("cursor", cursor) - } - req.URL.RawQuery = q.Encode() - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data ListAuditEventsResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} diff --git a/v2/audit_events_test.go b/v2/audit_events_test.go deleted file mode 100644 index 08f44bf..0000000 --- a/v2/audit_events_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package courier_test - -import ( - "context" - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/trycourier/courier-go/v2" -) - -func TestGetAuditEvent(t *testing.T) { - expectedResponseID := "123456789" - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, "/audit-events/123456789", req.URL.String()) - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"auditEventId\" : \"%s\" }", expectedResponseID))) - if writeErr != nil { - t.Error(writeErr) - } - })) - defer server.Close() - - t.Run("Get Audit Event Happy Path", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - response, err := client.GetAuditEvent(context.Background(), "123456789") - assert.Nil(t, err) - assert.Equal(t, expectedResponseID, response.AuditEventId) - }) - - t.Run("should throw Audit Event ID required if empty", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - _, err := client.GetAuditEvent(context.Background(), "") - assert.Equal(t, err.Error(), "audit Event ID is required") - }) -} - -func TestListAuditEvents(t *testing.T) { - expectedAuditEventId := "ZX3xXUMNKL4y2NkiKgstl" - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, "/audit-events", req.URL.String()) - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "results": [ - { - "actor": { - "email": "foo@bar.com", - "id": "foo-user" - }, - "auditEventId": "ZX3xXUMNKL4y2NkiKgstl", - "source": "courier.studio", - "target": {}, - "timestamp": "2022-07-22T22:33:59.552Z", - "type": "notification:published" - } - ], - "paging": { - "cursor": null, - "more": false - } - }` - _, _ = rw.Write([]byte(rsp)) - })) - defer server.Close() - - t.Run("List Audit Events Happy Path", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - response, err := client.ListAuditEvents(context.Background(), "") - assert.Nil(t, err) - assert.Equal(t, expectedAuditEventId, response.Results[0].AuditEventId) - assert.Equal(t, "foo-user", response.Results[0].Actor.Id) - }) -} diff --git a/v2/automations.go b/v2/automations.go deleted file mode 100644 index 7d666d8..0000000 --- a/v2/automations.go +++ /dev/null @@ -1,84 +0,0 @@ -package courier - -import ( - "context" - "encoding/json" -) - -type AutomationStep struct { - Action string `json:"action"` - Brand string `json:"brand,omitempty"` - CancelationToken string `json:"cancelation_token,omitempty"` - Data interface{} `json:"data,omitempty"` - Duration string `json:"duration,omitempty"` - If string `json:"if,omitempty"` - List string `json:"list,omitempty"` - Override interface{} `json:"override,omitempty"` - Profile interface{} `json:"profile,omitempty"` - Recipient string `json:"recipient,omitempty"` - Ref string `json:"ref,omitempty"` - Template string `json:"template,omitempty"` - Until string `json:"until,omitempty"` -} - -type Automation struct { - CancelationToken string `json:"cancelation_token,omitempty"` - Steps []AutomationStep `json:"steps"` -} - -type AutomationInvokeBody struct { - Automation Automation `json:"automation"` - Brand string `json:"brand,omitempty"` - Data interface{} `json:"data,omitempty"` - Profile interface{} `json:"profile,omitempty"` - Recipient string `json:"recipient,omitempty"` - Template string `json:"template,omitempty"` -} - -type AutomationTemplateInvokeBody struct { - Brand string `json:"brand,omitempty"` - Data interface{} `json:"data,omitempty"` - Profile interface{} `json:"profile,omitempty"` - Recipient string `json:"recipient,omitempty"` - Template string `json:"template,omitempty"` -} - -// Calls the POST /automations/invoke endpoint of the Courier API -func (c *Client) InvokeAutomation(ctx context.Context, body interface{}) (string, error) { - bodyMap, err := toJSONMap(body) - if err != nil { - return "", err - } - - response, err := c.API.SendRequestWithMaps(ctx, "POST", "/automations/invoke", bodyMap) - if err != nil { - return "", err - } - - var runID string - err = json.Unmarshal(response["runId"], &runID) - if err != nil { - return "", err - } - return runID, nil -} - -// Calls the POST /automations/:templateId/invoke endpoint of the Courier API -func (c *Client) InvokeAutomationTemplate(ctx context.Context, templateId string, body interface{}) (string, error) { - bodyMap, err := toJSONMap(body) - if err != nil { - return "", err - } - - response, err := c.API.SendRequestWithMaps(ctx, "POST", "/automations/"+templateId+"/invoke", bodyMap) - if err != nil { - return "", err - } - - var runID string - err = json.Unmarshal(response["runId"], &runID) - if err != nil { - return "", err - } - return runID, nil -} diff --git a/v2/automations_test.go b/v2/automations_test.go deleted file mode 100644 index e600089..0000000 --- a/v2/automations_test.go +++ /dev/null @@ -1,174 +0,0 @@ -package courier_test - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/trycourier/courier-go/v2" -) - -func TestInvokeAutomation(t *testing.T) { - type AutomationStep struct { - Action string - } - type Automation struct { - Steps []AutomationStep - } - type Data struct { - Foo string - } - type Profile struct { - Email string - } - - type RequestBody struct { - Automation Automation - Brand string - Data Data - Profile Profile - Recipient string - Template string - } - - var requestBody RequestBody - - expectedResponseID := "123456789" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/automations/invoke", req.URL.String()) - - decoder := json.NewDecoder(req.Body) - err := decoder.Decode(&requestBody) - if err != nil { - t.Error(err) - } - - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"runId\" : \"%s\" }", expectedResponseID))) - if writeErr != nil { - t.Error(writeErr) - } - - })) - defer server.Close() - - t.Run("invokes automation", func(t *testing.T) { - - client := courier.CreateClient("key", &server.URL) - - brand := "brand" - data := &Data{ - Foo: "bar", - } - profile := &Profile{ - Email: "foo@bar.com", - } - recipient := "recpient" - template := "template" - - runID, err := client.InvokeAutomation(context.Background(), courier.AutomationInvokeBody{ - Automation: courier.Automation{ - Steps: []courier.AutomationStep{ - courier.AutomationStep{ - Action: "send", - }, - }, - }, - Brand: brand, - Data: data, - Profile: profile, - Recipient: recipient, - Template: template, - }) - - assert.Nil(t, err) - assert.Equal(t, expectedResponseID, runID) - assert.Equal(t, 1, len(requestBody.Automation.Steps)) - assert.Equal(t, "send", requestBody.Automation.Steps[0].Action) - assert.Equal(t, brand, requestBody.Brand) - assert.Equal(t, data.Foo, requestBody.Data.Foo) - assert.Equal(t, profile.Email, requestBody.Profile.Email) - assert.Equal(t, recipient, requestBody.Recipient) - assert.Equal(t, template, requestBody.Template) - }) -} - -func TestInvokeAutomationTemplate(t *testing.T) { - type Data struct { - Foo string - } - type Profile struct { - Email string - } - - type RequestBody struct { - Brand string - Data Data - Profile Profile - Recipient string - Template string - } - templateId := "template001" - - var requestBody RequestBody - - expectedResponseID := "123456789" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/automations/"+templateId+"/invoke", req.URL.String()) - - decoder := json.NewDecoder(req.Body) - err := decoder.Decode(&requestBody) - if err != nil { - t.Error(err) - } - - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"runId\" : \"%s\" }", expectedResponseID))) - if writeErr != nil { - t.Error(writeErr) - } - - })) - defer server.Close() - - t.Run("invokes automation template", func(t *testing.T) { - - client := courier.CreateClient("key", &server.URL) - - brand := "brand" - data := &Data{ - Foo: "bar", - } - profile := &Profile{ - Email: "foo@bar.com", - } - recipient := "recpient" - template := "template" - - runID, err := client.InvokeAutomationTemplate(context.Background(), templateId, courier.AutomationTemplateInvokeBody{ - Brand: brand, - Data: data, - Profile: profile, - Recipient: recipient, - Template: template, - }) - - assert.Nil(t, err) - assert.Equal(t, expectedResponseID, runID) - assert.Equal(t, brand, requestBody.Brand) - assert.Equal(t, data.Foo, requestBody.Data.Foo) - assert.Equal(t, profile.Email, requestBody.Profile.Email) - assert.Equal(t, recipient, requestBody.Recipient) - assert.Equal(t, template, requestBody.Template) - }) -} diff --git a/v2/brands.go b/v2/brands.go deleted file mode 100644 index 9fde5d6..0000000 --- a/v2/brands.go +++ /dev/null @@ -1,202 +0,0 @@ -package courier - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "net/http" -) - -type BrandColors struct { - Primary string `json:"primary,omitempty"` - Secondary string `json:"secondary,omitempty"` - Tertiary string `json:"tertiary,omitempty"` -} - -type BrandEmail struct { - Header interface{} `json:"header,omitempty"` - Footer interface{} `json:"footer,omitempty"` -} - -type BrandSettings struct { - Colors BrandColors `json:"colors,omitempty"` - Email BrandEmail `json:"email,omitempty"` -} - -type BrandSnippetItem struct { - Format string `json:"format,omitempty"` - Name string `json:"name,omitempty"` - Value string `json:"value,omitempty"` -} - -type BrandSnippets struct { - Items []*BrandSnippetItem `json:"items,omitempty"` -} - -type BrandResponse struct { - ID string - Name string - Created int64 - Published int64 - Updated int64 - Settings BrandSettings - Snippets BrandSnippets - Version string -} - -type BrandsResponse struct { - Paging *PagingResponse - Results []*BrandResponse -} - -type PostBrandBody struct { - ID string `json:"id,omitempty"` - Name string `json:"name"` - Settings BrandSettings `json:"settings"` - Snippets BrandSnippets `json:"snippets,omitempty"` -} - -type PutBrandBody struct { - Name string `json:"name"` - Settings BrandSettings `json:"settings"` - Snippets BrandSnippets `json:"snippets,omitempty"` -} - -// GetBrands calls the GET /brands endpoint of the Courier API -func (c *Client) GetBrands(ctx context.Context, cursor string) (*BrandsResponse, error) { - url := c.API.BaseURL + "/brands" - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - q := req.URL.Query() - if cursor != "" { - q.Add("cursor", cursor) - } - req.URL.RawQuery = q.Encode() - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data BrandsResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// GetBrand calls the GET /brands/{brand_id} endpoint of the Courier API -func (c *Client) GetBrand(ctx context.Context, brandID string) (*BrandResponse, error) { - if brandID == "" { - return nil, errors.New("Brand ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/brands/%s", brandID) - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data BrandResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// PostBrand calls the POST /brands endpoint of the Courier API -func (c *Client) PostBrand(ctx context.Context, body PostBrandBody) (*BrandResponse, error) { - payload, err := json.Marshal(body) - if err != nil { - return nil, err - } - - url := c.API.BaseURL + "/brands" - - req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(payload)) - if err != nil { - return nil, err - } - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data BrandResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// PutBrand calls the PUT /brands/{brand_id} endpoint of the Courier API -func (c *Client) PutBrand(ctx context.Context, brandID string, body PutBrandBody) (*BrandResponse, error) { - if brandID == "" { - return nil, errors.New("Brand ID is required") - } - - payload, err := json.Marshal(body) - if err != nil { - return nil, err - } - - url := fmt.Sprintf(c.API.BaseURL+"/brands/%s", brandID) - - req, err := http.NewRequestWithContext(ctx, "PUT", url, bytes.NewReader(payload)) - if err != nil { - return nil, err - } - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data BrandResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// DeleteBrand calls the DELETE /brands/{brand_id} endpoint of the Courier API -func (c *Client) DeleteBrand(ctx context.Context, brandID string) error { - if brandID == "" { - return errors.New("Brand ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/brands/%s", brandID) - - req, err := http.NewRequestWithContext(ctx, "DELETE", url, nil) - if err != nil { - return err - } - - _, err = c.API.ExecuteRequest(req) - if err != nil { - return err - } - - return nil -} diff --git a/v2/brands_test.go b/v2/brands_test.go deleted file mode 100644 index d80eb48..0000000 --- a/v2/brands_test.go +++ /dev/null @@ -1,209 +0,0 @@ -package courier_test - -import ( - "context" - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/trycourier/courier-go/v2" -) - -func TestGetBrands(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/brands", req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "Paging": { - "Cursor": null, - "More": false - }, - "Results": [ - { - "ID": "VYXZGN7TY94NHDG7A7P9F534DFBK", - "Name": "tejas-test", - "Created": 1606098535741, - "Published": 1606098535741, - "Updated": 1606098535741, - "Settings": { - "Colors": { - "Primary": "blue", - "Secondary": "", - "Tertiary": "" - }, - "Email": { - "Header": null, - "Footer": {} - } - }, - "Snippets": {}, - "Version": "2020-11-23T02:28:55.741Z" - } - ] - }` - _, _ = rw.Write([]byte(rsp)) - - })) - defer server.Close() - - t.Run("Get Brands", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - rsp, err := client.GetBrands(context.Background(), "") - assert.Nil(t, err) - assert.Equal(t, "VYXZGN7TY94NHDG7A7P9F534DFBK", rsp.Results[0].ID) - }) -} - -func TestGetBrand(t *testing.T) { - brandID := "VYXZGN7TY94NHDG7A7P9F534DFBK" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/brands/"+brandID, req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "ID": "%s", - "Name": "tejas-test", - "Created": 1606098535741, - "Published": 1606098535741, - "Updated": 1606098535741, - "Settings": { - "Colors": { - "Primary": "blue", - "Secondary": "", - "Tertiary": "" - }, - "Email": { - "Header": null, - "Footer": {} - } - }, - "Snippets": {}, - "Version": "2020-11-23T02:28:55.741Z" - }` - _, _ = rw.Write([]byte(fmt.Sprintf(rsp, brandID))) - - })) - defer server.Close() - - t.Run("Get Brand", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - rsp, err := client.GetBrand(context.Background(), brandID) - assert.Nil(t, err) - assert.Equal(t, brandID, rsp.ID) - }) -} - -func TestPostBrand(t *testing.T) { - brandName := "my-brand-new-brand" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/brands", req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "created": 1611967387647, - "ID": "YVXV0VMM6Q4AK3NQ7CWEFGGVM6G4", - "name": "%s", - "published": 1611967387647, - "settings": { - "colors": {}, - "email": { - "footer": { - "markdown": null - } - } - }, - "snippets": {}, - "updated": 1611967387647, - "version": "2021-01-30T00:43:07.647Z" - }` - _, _ = rw.Write([]byte(fmt.Sprintf(rsp, brandName))) - - })) - defer server.Close() - - t.Run("Post Brand", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - rsp, err := client.PostBrand(context.Background(), courier.PostBrandBody{ - Name: brandName, - }) - assert.Nil(t, err) - assert.Equal(t, brandName, rsp.Name) - }) -} - -func TestPutBrand(t *testing.T) { - brandID := "VYXZGN7TY94NHDG7A7P9F534DFBK" - brandUpdatedName := "my-brand-updated" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/brands/"+brandID, req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "ID": "%s", - "Name": "%s", - "Created": 1611970081707, - "Published": 1611970081707, - "Updated": 1611970081707, - "Settings": { - "colors": {}, - "email": { - "footer": { - "markdown": null - } - } - }, - "Snippets": {}, - "Version": "2021-01-30T01:28:01.707Z" - }` - _, _ = rw.Write([]byte(fmt.Sprintf(rsp, brandID, brandUpdatedName))) - - })) - defer server.Close() - - t.Run("Put Brand", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - rsp, err := client.PutBrand(context.Background(), brandID, courier.PutBrandBody{ - Name: brandUpdatedName, - }) - assert.Nil(t, err) - assert.Equal(t, brandUpdatedName, rsp.Name) - }) -} - -func TestDeleteBrand(t *testing.T) { - brandID := "VYXZGN7TY94NHDG7A7P9F534DFBK" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/brands/"+brandID, req.URL.String()) - - rw.WriteHeader(http.StatusNoContent) - - })) - defer server.Close() - - t.Run("Delete brand", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - client.DeleteBrand(context.Background(), brandID) - }) -} diff --git a/v2/bulk.go b/v2/bulk.go deleted file mode 100644 index f1413d0..0000000 --- a/v2/bulk.go +++ /dev/null @@ -1,152 +0,0 @@ -package courier - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "net/http" -) - -// Job can be used to cast GET /bulk/jobId response to -type Job struct { - Definition interface{} `json:"definition"` - Enqueued int `json:"enqueued"` - Failures int `json:"failures"` - Received int `json:"received"` - Status string `json:"status"` -} - -// CreateJobBody can be used as request body to POST /bulk -type CreateJobBody struct { - Message interface{} `json:"message"` -} - -// IngestJobBody can be used as request body to POST /bulk/:jobId -type IngestJobBody struct { - Users []interface{} `json:"users"` -} - -// GetBulkJobResponse is type for the GET /bulk/:jobId response -type GetBulkJobResponse struct { - Job interface{} `json:"job"` -} - -// GetBulkJobUsersResponse is type for the GET /bulk/:jobId/users response -type GetBulkJobUsersResponse struct { - Items []interface{} `json:"items"` - Paging *PagingResponse -} - -// IngestBulkJobResponse can be used to deserialize POST /bulk/:jobId response -type IngestBulkJobResponse struct { - Errors []interface{} `json:"errors"` - Total int `json:"total"` -} - -// CreateJob calls the POST /bulk endpoint of the Courier API -func (c *Client) CreateJob(ctx context.Context, body interface{}) (string, error) { - bodyMap, err := toJSONMap(body) - if err != nil { - return "", err - } - - response, err := c.API.SendRequestWithMaps(ctx, "POST", "/bulk", bodyMap) - if err != nil { - return "", err - } - - var jobID string - err = json.Unmarshal(response["jobId"], &jobID) - if err != nil { - return "", err - } - return jobID, nil -} - -// IngestJob calls the POST /bulk/:jobId endpoint of the Courier API -func (c *Client) IngestJob(ctx context.Context, jobID string, body interface{}) (*IngestBulkJobResponse, error) { - jsonBody, err := json.Marshal(body) - if err != nil { - return nil, err - } - - bytes, err := c.API.SendRequestWithBytes(ctx, "POST", "/bulk/"+jobID, jsonBody) - if err != nil { - return nil, err - } - - var data IngestBulkJobResponse - - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// RunJob calls the POST /bulk/:jobId/run endpoint of the Courier API -func (c *Client) RunJob(ctx context.Context, jobID string) error { - _, err := c.API.SendRequestWithBytes(ctx, "POST", "/bulk/"+jobID+"/run", nil) - return err -} - -// GetJob calls the GET /bulk/:jobId endpoint of the Courier API -func (c *Client) GetJob(ctx context.Context, jobID string) (*GetBulkJobResponse, error) { - if jobID == "" { - return nil, errors.New("Job ID is required") - } - url := fmt.Sprintf(c.API.BaseURL+"/bulk/%s", jobID) - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data GetBulkJobResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// GetJobUsers calls the GET /bulk/:jobId/users endpoint of the Courier API -func (c *Client) GetJobUsers(ctx context.Context, jobID string, cursor string) (*GetBulkJobUsersResponse, error) { - if jobID == "" { - return nil, errors.New("Job ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/bulk/%s/users", jobID) - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - q := req.URL.Query() - if cursor != "" { - q.Add("cursor", cursor) - } - req.URL.RawQuery = q.Encode() - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data GetBulkJobUsersResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} diff --git a/v2/bulk_test.go b/v2/bulk_test.go deleted file mode 100644 index b53410c..0000000 --- a/v2/bulk_test.go +++ /dev/null @@ -1,177 +0,0 @@ -package courier_test - -import ( - "context" - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/trycourier/courier-go/v2" -) - -func TestCreateJob(t *testing.T) { - expectedResponseID := "123456789" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/bulk", req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"jobId\" : \"%s\" }", expectedResponseID))) - if writeErr != nil { - t.Error(writeErr) - } - - })) - defer server.Close() - - t.Run("create job", func(t *testing.T) { - - client := courier.CreateClient("key", &server.URL) - - jobID, err := client.CreateJob(context.Background(), courier.CreateJobBody{ - Message: map[string]string{ - "event": "foo", - }, - }) - - assert.Nil(t, err) - assert.Equal(t, expectedResponseID, jobID) - }) -} - -func TestIngestJob(t *testing.T) { - jobId := "job001" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/bulk/"+jobId, req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - - rsp := ` - { - "errors": [], - "total": 1 - }` - _, _ = rw.Write([]byte(rsp)) - })) - defer server.Close() - - t.Run("ingest job", func(t *testing.T) { - - client := courier.CreateClient("key", &server.URL) - - response, err := client.IngestJob(context.Background(), "job001", courier.IngestJobBody{ - Users: []interface{}{ - map[string]string{"recipient": "johndoe"}, - }, - }) - - assert.Nil(t, err) - assert.Equal(t, 0, len(response.Errors)) - assert.Equal(t, 1, response.Total) - }) -} - -func TestRunJob(t *testing.T) { - jobId := "job001" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/bulk/"+jobId+"/run", req.URL.String()) - - rw.WriteHeader(http.StatusAccepted) - })) - defer server.Close() - - t.Run("run job", func(t *testing.T) { - - client := courier.CreateClient("key", &server.URL) - - err := client.RunJob(context.Background(), "job001") - - assert.Nil(t, err) - }) -} - -func TestGetJob(t *testing.T) { - jobId := "job001" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/bulk/"+jobId, req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - - rsp := ` - { - "job": { - "definition": { - "event": "foo" - }, - "enqueued": 1, - "failures": 0, - "received": 1, - "status": "COMPLETED" - } - }` - _, _ = rw.Write([]byte(rsp)) - })) - defer server.Close() - - t.Run("get job", func(t *testing.T) { - - client := courier.CreateClient("key", &server.URL) - - response, err := client.GetJob(context.Background(), "job001") - - assert.Nil(t, err) - assert.NotNil(t, response.Job) - }) -} - -func TestGetJobUsers(t *testing.T) { - jobId := "job001" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/bulk/"+jobId+"/users", req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - - rsp := ` - { - "items": [ - { - "recipient": "johndoe" - } - ], - "paging": { - "cursor": null, - "more": false - } - }` - _, _ = rw.Write([]byte(rsp)) - })) - defer server.Close() - - t.Run("get job users", func(t *testing.T) { - - client := courier.CreateClient("key", &server.URL) - - response, err := client.GetJobUsers(context.Background(), "job001", "") - - assert.Nil(t, err) - assert.Equal(t, 1, len(response.Items)) - assert.Nil(t, response.Paging.Cursor) - assert.Equal(t, false, response.Paging.More) - }) -} diff --git a/v2/courier.go b/v2/courier.go deleted file mode 100644 index 8ebf8a6..0000000 --- a/v2/courier.go +++ /dev/null @@ -1,26 +0,0 @@ -package courier - -const version = "2.12.0" - -// Client lets you communicate with the Courier API -type Client struct { - API *APIConfiguration -} - -// CreateClient creates a new client for communicating with the Courier API -func CreateClient(authToken string, baseURL *string) *Client { - var url string - if baseURL == nil { - url = "https://api.courier.com" - } else { - url = *baseURL - } - - return &Client{ - API: &APIConfiguration{ - AuthToken: authToken, - BaseURL: url, - SDKVersion: version, - }, - } -} diff --git a/v2/examples/audit-events/get_audit_event.go b/v2/examples/audit-events/get_audit_event.go deleted file mode 100644 index d330426..0000000 --- a/v2/examples/audit-events/get_audit_event.go +++ /dev/null @@ -1,19 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func getAuditEvent() { - client := courier.CreateClient("", nil) - - data, err := client.GetAuditEvent(context.Background(), "123") - - if err != nil { - log.Fatalln(err) - } - log.Println(data) -} diff --git a/v2/examples/audit-events/list_audit_events.go b/v2/examples/audit-events/list_audit_events.go deleted file mode 100644 index 71efa83..0000000 --- a/v2/examples/audit-events/list_audit_events.go +++ /dev/null @@ -1,21 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func listAuditEvents() { - client := courier.CreateClient("", nil) - - data, err := client.ListAuditEvents(context.Background(), - "", // optional cursor - ) - - if err != nil { - log.Fatalln(err) - } - log.Println(data) -} diff --git a/v2/examples/automations/invoke.go b/v2/examples/automations/invoke.go deleted file mode 100644 index d0adb87..0000000 --- a/v2/examples/automations/invoke.go +++ /dev/null @@ -1,32 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func invokeAutomation() { - client := courier.CreateClient("", nil) - - runID, err := client.InvokeAutomation(context.Background(), courier.AutomationInvokeBody{ - Automation: courier.Automation{ - Steps: []courier.AutomationStep{ - courier.AutomationStep{ - Action: "send", - }, - }, - }, - Brand: "", // optional brand ID - Data: nil, // optional data map - Profile: nil, // optional profile map - Recipient: "", // optional recipient ID - Template: "", // optional notification template ID - }) - - if err != nil { - log.Fatalln(err) - } - log.Println(runID) -} diff --git a/v2/examples/automations/invoke_template.go b/v2/examples/automations/invoke_template.go deleted file mode 100644 index 23e4e42..0000000 --- a/v2/examples/automations/invoke_template.go +++ /dev/null @@ -1,25 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func invokeAutomationTemplate() { - client := courier.CreateClient("", nil) - - runID, err := client.InvokeAutomationTemplate(context.Background(), "", courier.AutomationTemplateInvokeBody{ - Brand: "", // optional brand ID - Data: nil, // optional data map - Profile: nil, // optional profile map - Recipient: "", // optional recipient ID - Template: "", // optional notification template ID - }) - - if err != nil { - log.Fatalln(err) - } - log.Println(runID) -} diff --git a/v2/examples/brands/delete_brand.go b/v2/examples/brands/delete_brand.go deleted file mode 100644 index 7399bf1..0000000 --- a/v2/examples/brands/delete_brand.go +++ /dev/null @@ -1,13 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func deleteBrand() { - client := courier.CreateClient("", nil) - - client.DeleteBrand(context.Background(), "my-brand") -} diff --git a/v2/examples/brands/get_brand.go b/v2/examples/brands/get_brand.go deleted file mode 100644 index fc8002b..0000000 --- a/v2/examples/brands/get_brand.go +++ /dev/null @@ -1,19 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func getBrand() { - client := courier.CreateClient("", nil) - - data, err := client.GetBrand(context.Background(), "my-brand") - - if err != nil { - log.Fatalln(err) - } - log.Println(data) -} diff --git a/v2/examples/brands/get_brands.go b/v2/examples/brands/get_brands.go deleted file mode 100644 index 62d5b59..0000000 --- a/v2/examples/brands/get_brands.go +++ /dev/null @@ -1,21 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func getBrands() { - client := courier.CreateClient("", nil) - - data, err := client.GetBrands(context.Background(), - "", // optional cursor - ) - - if err != nil { - log.Fatalln(err) - } - log.Println(data) -} diff --git a/v2/examples/brands/post_brand.go b/v2/examples/brands/post_brand.go deleted file mode 100644 index 2e5d0ac..0000000 --- a/v2/examples/brands/post_brand.go +++ /dev/null @@ -1,15 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func postBrand() { - client := courier.CreateClient("", nil) - - client.PostBrand(context.Background(), courier.PostBrandBody{ - Name: "my-brand", - }) -} diff --git a/v2/examples/brands/put_brand.go b/v2/examples/brands/put_brand.go deleted file mode 100644 index 1c42704..0000000 --- a/v2/examples/brands/put_brand.go +++ /dev/null @@ -1,15 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func putBrand() { - client := courier.CreateClient("", nil) - - client.PutBrand(context.Background(), "my-brand", courier.PutBrandBody{ - Name: "my-updated-brand", - }) -} diff --git a/v2/examples/bulk/create_job.go b/v2/examples/bulk/create_job.go deleted file mode 100644 index 4df9e18..0000000 --- a/v2/examples/bulk/create_job.go +++ /dev/null @@ -1,24 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func createJob() { - client := courier.CreateClient("", nil) - - jobID, err := client.CreateJob(context.Background(), courier.CreateJobBody{ - Message: map[string]string{ - "event": "foo", - // more message properties - }, - }) - - if err != nil { - log.Fatalln(err) - } - log.Println(jobID) -} diff --git a/v2/examples/bulk/get_job.go b/v2/examples/bulk/get_job.go deleted file mode 100644 index 716f124..0000000 --- a/v2/examples/bulk/get_job.go +++ /dev/null @@ -1,19 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func getJob() { - client := courier.CreateClient("", nil) - - data, err := client.GetJob(context.Background(), "job123") - - if err != nil { - log.Fatalln(err) - } - log.Println(data) -} diff --git a/v2/examples/bulk/get_job_users.go b/v2/examples/bulk/get_job_users.go deleted file mode 100644 index 256a5b7..0000000 --- a/v2/examples/bulk/get_job_users.go +++ /dev/null @@ -1,22 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func getJobUsers() { - client := courier.CreateClient("", nil) - - data, err := client.GetJobUsers(context.Background(), - "job123", // required job ID - "", // optional cursor - ) - - if err != nil { - log.Fatalln(err) - } - log.Println(data) -} diff --git a/v2/examples/bulk/ingest_job.go b/v2/examples/bulk/ingest_job.go deleted file mode 100644 index a296efc..0000000 --- a/v2/examples/bulk/ingest_job.go +++ /dev/null @@ -1,25 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func ingestUsers() { - client := courier.CreateClient("", nil) - - data, err := client.IngestJob(context.Background(), "job123", courier.IngestJobBody{ - Users: []interface{}{ - map[string]string{"recipient": "johndoe"}, - // more user properties - }, - }) - - if err != nil { - log.Fatalln(err) - } - - log.Println(data) -} diff --git a/v2/examples/bulk/run_job.go b/v2/examples/bulk/run_job.go deleted file mode 100644 index febaf5d..0000000 --- a/v2/examples/bulk/run_job.go +++ /dev/null @@ -1,13 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func runJob() { - client := courier.CreateClient("", nil) - - client.RunJob(context.Background(), "job123") -} diff --git a/v2/examples/lists/delete_list.go b/v2/examples/lists/delete_list.go deleted file mode 100644 index fde19b3..0000000 --- a/v2/examples/lists/delete_list.go +++ /dev/null @@ -1,13 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func deleteList() { - client := courier.CreateClient("", nil) - - client.DeleteList(context.Background(), "my-list") -} diff --git a/v2/examples/lists/get_list.go b/v2/examples/lists/get_list.go deleted file mode 100644 index 0711ddd..0000000 --- a/v2/examples/lists/get_list.go +++ /dev/null @@ -1,19 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func getList() { - client := courier.CreateClient("", nil) - - data, err := client.GetList(context.Background(), "my-list") - - if err != nil { - log.Fatalln(err) - } - log.Println(data) -} diff --git a/v2/examples/lists/get_list_subscriptions.go b/v2/examples/lists/get_list_subscriptions.go deleted file mode 100644 index 6dbbf94..0000000 --- a/v2/examples/lists/get_list_subscriptions.go +++ /dev/null @@ -1,19 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func getListSubscriptions() { - client := courier.CreateClient("", nil) - - data, err := client.GetListSubscriptions(context.Background(), "my-list", "") - - if err != nil { - log.Fatalln(err) - } - log.Println(data) -} diff --git a/v2/examples/lists/get_lists.go b/v2/examples/lists/get_lists.go deleted file mode 100644 index f93fcda..0000000 --- a/v2/examples/lists/get_lists.go +++ /dev/null @@ -1,22 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func getLists() { - client := courier.CreateClient("", nil) - - data, err := client.GetLists(context.Background(), - "", // optional cursor - "", // optional pattern - ) - - if err != nil { - log.Fatalln(err) - } - log.Println(data) -} diff --git a/v2/examples/lists/list_subscribe.go b/v2/examples/lists/list_subscribe.go deleted file mode 100644 index d641345..0000000 --- a/v2/examples/lists/list_subscribe.go +++ /dev/null @@ -1,13 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func listSubscribe() { - client := courier.CreateClient("", nil) - - client.ListSubscribe(context.Background(), "my-list", "my-recipient", courier.ListSubscriptionRecipientBody{}) -} diff --git a/v2/examples/lists/list_unsubscribe.go b/v2/examples/lists/list_unsubscribe.go deleted file mode 100644 index 02ad010..0000000 --- a/v2/examples/lists/list_unsubscribe.go +++ /dev/null @@ -1,13 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func listUnsubscribe() { - client := courier.CreateClient("", nil) - - client.ListUnsubscribe(context.Background(), "my-list", "my-recipient") -} diff --git a/v2/examples/lists/post_list_subscriptions.go b/v2/examples/lists/post_list_subscriptions.go deleted file mode 100644 index 95fe080..0000000 --- a/v2/examples/lists/post_list_subscriptions.go +++ /dev/null @@ -1,19 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func postListSubscriptions() { - client := courier.CreateClient("", nil) - - client.PostListSubscriptions(context.Background(), "my-list", courier.ListSubscriptionBody{ - Recipients: []courier.ListRecipient{ - courier.ListRecipient{ - RecipientID: "0460766e-8463-4905-ae98-b72c7aef41d6", - }, - }, - }) -} diff --git a/v2/examples/lists/put_list.go b/v2/examples/lists/put_list.go deleted file mode 100644 index 8a4e29a..0000000 --- a/v2/examples/lists/put_list.go +++ /dev/null @@ -1,18 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func putList() { - client := courier.CreateClient("", nil) - - client.PutList(context.Background(), - "my-list", - courier.PutListBody{ - Name: "Besties", - }, - ) -} diff --git a/v2/examples/lists/put_list_subscriptions.go b/v2/examples/lists/put_list_subscriptions.go deleted file mode 100644 index a833a93..0000000 --- a/v2/examples/lists/put_list_subscriptions.go +++ /dev/null @@ -1,19 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func putListSubscriptions() { - client := courier.CreateClient("", nil) - - client.PutListSubscriptions(context.Background(), "my-list", courier.ListSubscriptionBody{ - Recipients: []courier.ListRecipient{ - courier.ListRecipient{ - RecipientID: "0460766e-8463-4905-ae98-b72c7aef41d6", - }, - }, - }) -} diff --git a/v2/examples/lists/restore_list.go b/v2/examples/lists/restore_list.go deleted file mode 100644 index cfad0e1..0000000 --- a/v2/examples/lists/restore_list.go +++ /dev/null @@ -1,13 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func restoreList() { - client := courier.CreateClient("", nil) - - client.RestoreList(context.Background(), "my-list") -} diff --git a/v2/examples/notifications/cancel_notification_submission.go b/v2/examples/notifications/cancel_notification_submission.go deleted file mode 100644 index d01d7fc..0000000 --- a/v2/examples/notifications/cancel_notification_submission.go +++ /dev/null @@ -1,13 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func cancelNotificationSubmission() { - client := courier.CreateClient("", nil) - - client.CancelNotificationSubmission(context.Background(), "my-notification", "my-submission") -} diff --git a/v2/examples/notifications/get_notification_content.go b/v2/examples/notifications/get_notification_content.go deleted file mode 100644 index ba5775f..0000000 --- a/v2/examples/notifications/get_notification_content.go +++ /dev/null @@ -1,19 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func getNotificationContent() { - client := courier.CreateClient("", nil) - - data, err := client.GetNotificationContent(context.Background(), "my-notification") - - if err != nil { - log.Fatalln(err) - } - log.Println(data) -} diff --git a/v2/examples/notifications/get_notification_draft_content.go b/v2/examples/notifications/get_notification_draft_content.go deleted file mode 100644 index 7ac914d..0000000 --- a/v2/examples/notifications/get_notification_draft_content.go +++ /dev/null @@ -1,19 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func getNotificationDraftContent() { - client := courier.CreateClient("", nil) - - data, err := client.GetNotificationDraftContent(context.Background(), "my-notification") - - if err != nil { - log.Fatalln(err) - } - log.Println(data) -} diff --git a/v2/examples/notifications/get_notification_submission_checks.go b/v2/examples/notifications/get_notification_submission_checks.go deleted file mode 100644 index 8a8afed..0000000 --- a/v2/examples/notifications/get_notification_submission_checks.go +++ /dev/null @@ -1,19 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func getNotificationSubmissionChecks() { - client := courier.CreateClient("", nil) - - data, err := client.GetNotificationSubmissionChecks(context.Background(), "my-notification", "my-submission") - - if err != nil { - log.Fatalln(err) - } - log.Println(data) -} diff --git a/v2/examples/notifications/get_notifications.go b/v2/examples/notifications/get_notifications.go deleted file mode 100644 index 91d0fc5..0000000 --- a/v2/examples/notifications/get_notifications.go +++ /dev/null @@ -1,21 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func getNotifications() { - client := courier.CreateClient("", nil) - - data, err := client.GetNotifications(context.Background(), - "", // optional cursor - ) - - if err != nil { - log.Fatalln(err) - } - log.Println(data) -} diff --git a/v2/examples/notifications/post_notification_draft_variations.go b/v2/examples/notifications/post_notification_draft_variations.go deleted file mode 100644 index 864d5f8..0000000 --- a/v2/examples/notifications/post_notification_draft_variations.go +++ /dev/null @@ -1,23 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func postNotificationDraftVariations() { - client := courier.CreateClient("", nil) - - client.PostNotificationDraftVariations(context.Background(), "my-notification", courier.NotificationVariationsRequestBody{ - Blocks: []interface{}{ - map[string]string{"id": "block_00d0bcb0-aba1-443f-a8dd-daac505500fe"}, - map[string]string{"type": "text"}, - // ...locales - }, - Channels: []interface{}{ - map[string]string{"id": "channel_79d25574-83be-4da1-a5c3-3d4e2ab5f154"}, - // ...locales - }, - }) -} diff --git a/v2/examples/notifications/post_notification_varations.go b/v2/examples/notifications/post_notification_varations.go deleted file mode 100644 index 59ac52b..0000000 --- a/v2/examples/notifications/post_notification_varations.go +++ /dev/null @@ -1,23 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func postNotificationVariations() { - client := courier.CreateClient("", nil) - - client.PostNotificationVariations(context.Background(), "my-notification", courier.NotificationVariationsRequestBody{ - Blocks: []interface{}{ - map[string]string{"id": "block_00d0bcb0-aba1-443f-a8dd-daac505500fe"}, - map[string]string{"type": "text"}, - // ...locales - }, - Channels: []interface{}{ - map[string]string{"id": "channel_79d25574-83be-4da1-a5c3-3d4e2ab5f154"}, - // ...locales - }, - }) -} diff --git a/v2/examples/notifications/put_notification_submission_checks.go b/v2/examples/notifications/put_notification_submission_checks.go deleted file mode 100644 index 1b98761..0000000 --- a/v2/examples/notifications/put_notification_submission_checks.go +++ /dev/null @@ -1,21 +0,0 @@ -package examples - -import ( - "context" - - "github.com/trycourier/courier-go/v2" -) - -func putNotificationSubmissionChecks() { - client := courier.CreateClient("", nil) - - client.PutNotificationSubmissionChecks(context.Background(), "my-notification", "my-submission", courier.NotificationSubmissionChecksRequest{ - Checks: []courier.SubmissionCheck{ - courier.SubmissionCheck{ - ID: "my-check", - Status: "RESOLVED", - Type: "custom", - }, - }, - }) -} diff --git a/v2/examples/send/send_message.go b/v2/examples/send/send_message.go deleted file mode 100644 index 2047668..0000000 --- a/v2/examples/send/send_message.go +++ /dev/null @@ -1,26 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func sendMessage() { - client := courier.CreateClient("", nil) - - requestID, err := client.SendMessage(context.Background(), courier.SendMessageRequestBody{ - Message: map[string]interface{}{ - "template": "my-template", - "to": map[string]string{ - "email": "foo@bar.com", - }, - }, - }) - - if err != nil { - log.Fatalln(err) - } - log.Println(requestID) -} diff --git a/v2/examples/send/send_message_idempotent.go b/v2/examples/send/send_message_idempotent.go deleted file mode 100644 index 93f0ca0..0000000 --- a/v2/examples/send/send_message_idempotent.go +++ /dev/null @@ -1,38 +0,0 @@ -package examples - -import ( - "context" - "log" - "time" - - "github.com/trycourier/courier-go/v2" -) - -func sendIdempotentMessage() { - client := courier.CreateClient("", nil) - expiration := time.Now().Add(time.Hour * 24) - requestID, err := client.SendMessageWithOptions(context.Background(), - map[string]interface{}{ - "message": map[string]interface{}{ - "to": map[string]string{ - "email": "foo@example.com", - }, - "content": map[string]string{ - "title": "Welcome!", - "body": "Thanks for signing up Harry Potter", - }, - "routing": map[string]interface{}{ - "method": "single", - "channels": []string{"email"}, - }, - }, - }, - "POST", - courier.WithIdempotencyKey("fake-key-6"), - courier.WithIdempotencyKeyExpiration(expiration), - ) - if err != nil { - log.Fatalln(err) - } - log.Println(requestID) -} diff --git a/v2/examples/send/send_message_timeout.go b/v2/examples/send/send_message_timeout.go deleted file mode 100644 index 7f6b93b..0000000 --- a/v2/examples/send/send_message_timeout.go +++ /dev/null @@ -1,35 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func sendMessageTimeout() { - client := courier.CreateClient("", nil) - - requestID, err := client.SendMessage(context.Background(), courier.SendMessageRequestBody{ - Message: map[string]interface{}{ - "template": "my-template", - "to": map[string]string{ - "email": "foo@bar.com", - }, - "timeout": map[string]interface{}{ - "message": int64(3600000), // 1 hour in milliseconds - "channel": map[string]int64{ - "email": int64(300000), - }, - "provider": map[string]int64{ - "sendgrid": int64(0), // disable retry - }, - }, - }, - }) - - if err != nil { - log.Fatalln(err) - } - log.Println(requestID) -} diff --git a/v2/examples/send/send_message_with_granular_metadata.go b/v2/examples/send/send_message_with_granular_metadata.go deleted file mode 100644 index 079b692..0000000 --- a/v2/examples/send/send_message_with_granular_metadata.go +++ /dev/null @@ -1,49 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func sendMessageWithGranularMetadata() { - client := courier.CreateClient("", nil) - - requestID, err := client.SendMessage(context.Background(), courier.SendMessageRequestBody{ - Message: map[string]interface{}{ - "template": "my-template", - "to": map[string]string{ - "email": "foo@bar.com", - }, - "metadata": map[string]interface{}{ - "utm": map[string]string{ - "source": "go", - }, - }, - "channels": map[string]interface{}{ - "email": map[string]interface{}{ - "metadata": map[string]interface{}{ - "utm": map[string]string{ - "medium": "email", - }, - }, - }, - }, - "providers": map[string]interface{}{ - "sendgrid": map[string]interface{}{ - "metadata": map[string]interface{}{ - "utm": map[string]string{ - "campaign": "sendgrid", - }, - }, - }, - }, - }, - }) - - if err != nil { - log.Fatalln(err) - } - log.Println(requestID) -} diff --git a/v2/examples/send/send_message_with_metadata.go b/v2/examples/send/send_message_with_metadata.go deleted file mode 100644 index add333c..0000000 --- a/v2/examples/send/send_message_with_metadata.go +++ /dev/null @@ -1,33 +0,0 @@ -package examples - -import ( - "context" - "log" - - "github.com/trycourier/courier-go/v2" -) - -func sendMessageWithMetadata() { - client := courier.CreateClient("", nil) - - requestID, err := client.SendMessage(context.Background(), courier.SendMessageRequestBody{ - Message: map[string]interface{}{ - "template": "my-template", - "to": map[string]string{ - "email": "foo@bar.com", - }, - "metadata": map[string]interface{}{ - "utm": map[string]string{ - "source": "go", - }, - "tags": []string{"tag-1", "tag-2"}, - "trace_id": "Wassup?", - }, - }, - }) - - if err != nil { - log.Fatalln(err) - } - log.Println(requestID) -} diff --git a/v2/go.mod b/v2/go.mod deleted file mode 100644 index c97efc2..0000000 --- a/v2/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module github.com/trycourier/courier-go/v2 - -go 1.13 - -require github.com/stretchr/testify v1.5.1 diff --git a/v2/go.sum b/v2/go.sum deleted file mode 100644 index c0565d7..0000000 --- a/v2/go.sum +++ /dev/null @@ -1,12 +0,0 @@ -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/v2/lib.go b/v2/lib.go deleted file mode 100644 index b3bea42..0000000 --- a/v2/lib.go +++ /dev/null @@ -1,18 +0,0 @@ -package courier - -import "encoding/json" - -func toJSONMap(input interface{}) (map[string]interface{}, error) { - var m map[string]interface{} - temp, err := json.Marshal(input) - if err != nil { - return nil, err - } - - err = json.Unmarshal(temp, &m) - if err != nil { - return nil, err - } - - return m, nil -} diff --git a/v2/lists.go b/v2/lists.go deleted file mode 100644 index c82cdd3..0000000 --- a/v2/lists.go +++ /dev/null @@ -1,288 +0,0 @@ -package courier - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "net/http" -) - -type ListResponse struct { - ID string - Name string - Created string - Updated string -} - -type ListsResponse struct { - Paging *PagingResponse - Items []*ListResponse -} - -type PutListBody struct { - Name string `json:"name"` - Preferences interface{} `json:"preferences,omitempty"` -} - -type ListSubscriptionItem struct { - RecipientID string - Created string - Preferences interface{} -} - -type ListSubscriptionsResponse struct { - Paging *PagingResponse - Items []*ListSubscriptionItem -} - -type ListRecipient struct { - RecipientID string `json:"recipientId,omitempty"` - Preferences interface{} `json:"preferences,omitempty"` -} - -type ListSubscriptionBody struct { - Recipients []ListRecipient `json:"recipients"` -} - -type ListSubscriptionRecipientBody struct { - Preferences interface{} `json:"preferences,omitempty"` -} - -// GetLists calls the GET /lists endpoint of the Courier API -func (c *Client) GetLists(ctx context.Context, cursor string, pattern string) (*ListsResponse, error) { - url := c.API.BaseURL + "/lists" - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - q := req.URL.Query() - if cursor != "" { - q.Add("cursor", cursor) - } - if pattern != "" { - q.Add("pattern", pattern) - } - req.URL.RawQuery = q.Encode() - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data ListsResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// GetList calls the GET /lists/{list_id} endpoint of the Courier API -func (c *Client) GetList(ctx context.Context, listID string) (*ListResponse, error) { - if listID == "" { - return nil, errors.New("List ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/lists/%s", listID) - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data ListResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// PutList calls the PUT /lists/{list_id} endpoint of the Courier API -func (c *Client) PutList(ctx context.Context, listID string, body interface{}) error { - bodyMap, err := toJSONMap(body) - if err != nil { - return err - } - - _, err = c.API.SendRequestWithMaps(ctx, "PUT", "/lists/"+listID, bodyMap) - if err != nil { - return err - } - - return nil -} - -// DeleteList calls the DELETE /lists/{list_id} endpoint of the Courier API -func (c *Client) DeleteList(ctx context.Context, listID string) error { - if listID == "" { - return errors.New("List ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/lists/%s", listID) - - req, err := http.NewRequestWithContext(ctx, "DELETE", url, nil) - if err != nil { - return err - } - - _, err = c.API.ExecuteRequest(req) - if err != nil { - return err - } - - return nil -} - -// RestoreList calls the PUT /lists/{list_id}/restore endpoint of the Courier API -func (c *Client) RestoreList(ctx context.Context, listID string) error { - if listID == "" { - return errors.New("List ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/lists/%s/restore", listID) - - req, err := http.NewRequestWithContext(ctx, "PUT", url, nil) - if err != nil { - return err - } - - _, err = c.API.ExecuteRequest(req) - if err != nil { - return err - } - - return nil -} - -// GetListSubscriptions calls the GET /lists/{list_id}/subscriptions endpoint of the Courier API -func (c *Client) GetListSubscriptions(ctx context.Context, listID string, cursor string) (*ListSubscriptionsResponse, error) { - if listID == "" { - return nil, errors.New("List ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/lists/%s/subscriptions", listID) - - if cursor != "" { - url = url + "?cursor=" + cursor - } - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data ListSubscriptionsResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// PutListSubscriptions calls the PUT /lists/{list_id}/subscriptions endpoint of the Courier API -func (c *Client) PutListSubscriptions(ctx context.Context, listID string, body interface{}) error { - if listID == "" { - return errors.New("List ID is required") - } - - bodyMap, err := toJSONMap(body) - if err != nil { - return err - } - - _, err = c.API.SendRequestWithMaps(ctx, "PUT", "/lists/"+listID+"/subscriptions", bodyMap) - if err != nil { - return err - } - - return nil -} - -// PostListSubscriptions calls the POST /lists/{list_id}/subscriptions endpoint of the Courier API -func (c *Client) PostListSubscriptions(ctx context.Context, listID string, body interface{}) error { - if listID == "" { - return errors.New("List ID is required") - } - - bodyMap, err := toJSONMap(body) - if err != nil { - return err - } - - _, err = c.API.SendRequestWithMaps(ctx, "POST", "/lists/"+listID+"/subscriptions", bodyMap) - if err != nil { - return err - } - - return nil -} - -// ListSubscribe calls the PUT /lists/{list_id}/subscriptions/{recipient_id} endpoint of the Courier API -func (c *Client) ListSubscribe(ctx context.Context, listID string, recipientID string, body interface{}) error { - if listID == "" { - return errors.New("List ID is required") - } - - if recipientID == "" { - return errors.New("Recipient ID is required") - } - - _, err := toJSONMap(body) - if err != nil { - return err - } - - jsonBody, err := json.Marshal(body) - if err != nil { - return err - } - - _, err = c.API.SendRequestWithBytes(ctx, "PUT", "/lists/"+listID+"/subscriptions/"+recipientID, jsonBody) - if err != nil { - return err - } - - return nil -} - -// ListUnsubscribe calls the PUT /lists/{list_id}/subscriptions/{recipient_id} endpoint of the Courier API -func (c *Client) ListUnsubscribe(ctx context.Context, listID string, recipientID string) error { - if listID == "" { - return errors.New("List ID is required") - } - - if recipientID == "" { - return errors.New("Recipient ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/lists/%s/subscriptions/%s", listID, recipientID) - - req, err := http.NewRequestWithContext(ctx, "DELETE", url, nil) - if err != nil { - return err - } - - _, err = c.API.ExecuteRequest(req) - if err != nil { - return err - } - - return nil -} diff --git a/v2/lists_test.go b/v2/lists_test.go deleted file mode 100644 index a124565..0000000 --- a/v2/lists_test.go +++ /dev/null @@ -1,262 +0,0 @@ -package courier_test - -import ( - "context" - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/trycourier/courier-go/v2" -) - -func TestGetLists(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/lists", req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "Paging": { - "Cursor": null, - "More": false - }, - "Items": [ - { - "ID": "my-list", - "Name": "My Awesome List", - "Created": "2020-11-22T21:30:23.879Z", - "Updated": "2020-11-24T20:06:12.332Z" - } - ] - }` - _, _ = rw.Write([]byte(rsp)) - - })) - defer server.Close() - - t.Run("Get Lists", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - rsp, err := client.GetLists(context.Background(), "", "") - assert.Nil(t, err) - assert.Equal(t, "my-list", rsp.Items[0].ID) - }) -} - -func TestGetList(t *testing.T) { - listID := "my-list" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/lists/"+listID, req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "ID": "%s", - "Name": "", - "Created": "2020-11-22T21:30:23.879Z", - "Updated": "2020-11-24T20:06:12.332Z" - }` - _, _ = rw.Write([]byte(fmt.Sprintf(rsp, listID))) - - })) - defer server.Close() - - t.Run("Get List", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - rsp, err := client.GetList(context.Background(), listID) - assert.Nil(t, err) - assert.Equal(t, listID, rsp.ID) - }) -} - -func TestPutList(t *testing.T) { - listID := "my-list" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/lists/"+listID, req.URL.String()) - - rw.WriteHeader(http.StatusNoContent) - - })) - defer server.Close() - - t.Run("Put List", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - client.PutList(context.Background(), listID, courier.PutListBody{ - Name: "Besties", - }) - }) -} - -func TestDeleteList(t *testing.T) { - listID := "my-list" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/lists/"+listID, req.URL.String()) - - rw.WriteHeader(http.StatusNoContent) - - })) - defer server.Close() - - t.Run("Delete List", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - client.DeleteList(context.Background(), listID) - }) -} - -func TestRestoreList(t *testing.T) { - listID := "my-list" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/lists/"+listID+"/restore", req.URL.String()) - - rw.WriteHeader(http.StatusNoContent) - - })) - defer server.Close() - - t.Run("Restore List", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - client.RestoreList(context.Background(), listID) - }) -} - -func TestGetListSubscriptions(t *testing.T) { - listID := "my-list" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/lists/"+listID+"/subscriptions", req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "Paging": { - "Cursor": null, - "More": false - }, - "Items": [ - { - "RecipientID": "5ed558d4-d2eb-4e0f-984a-81a0f04054b1", - "Created": "2020-11-24T20:06:12.352Z" - } - ] - }` - _, _ = rw.Write([]byte(rsp)) - - })) - defer server.Close() - - t.Run("Get list subscriptions", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - rsp, err := client.GetListSubscriptions(context.Background(), listID, "") - assert.Nil(t, err) - assert.Equal(t, 1, len(rsp.Items)) - assert.Equal(t, "5ed558d4-d2eb-4e0f-984a-81a0f04054b1", rsp.Items[0].RecipientID) - }) -} - -func TestPutListSubscriptions(t *testing.T) { - listID := "my-list" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/lists/"+listID+"/subscriptions", req.URL.String()) - - rw.WriteHeader(http.StatusNoContent) - - })) - defer server.Close() - - t.Run("Put list subscriptions", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - client.PutListSubscriptions(context.Background(), listID, courier.ListSubscriptionBody{ - Recipients: []courier.ListRecipient{ - courier.ListRecipient{ - RecipientID: "0460766e-8463-4905-ae98-b72c7aef41d6", - }, - }, - }) - }) -} - -func TestPostListSubscriptions(t *testing.T) { - listID := "my-list" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/lists/"+listID+"/subscriptions", req.URL.String()) - - rw.WriteHeader(http.StatusNoContent) - - })) - defer server.Close() - - t.Run("Post list subscriptions", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - client.PostListSubscriptions(context.Background(), listID, courier.ListSubscriptionBody{ - Recipients: []courier.ListRecipient{ - courier.ListRecipient{ - RecipientID: "0460766e-8463-4905-ae98-b72c7aef41d6", - }, - }, - }) - }) -} - -func TestListSubscribe(t *testing.T) { - listID := "my-list" - recipientID := "foo" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/lists/"+listID+"/subscriptions/"+recipientID, req.URL.String()) - - rw.WriteHeader(http.StatusNoContent) - - })) - defer server.Close() - - t.Run("subscribe to a list", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - client.ListSubscribe(context.Background(), listID, recipientID, courier.ListSubscriptionRecipientBody{}) - }) -} - -func TestListUnsubscribe(t *testing.T) { - listID := "my-list" - recipientID := "foo" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/lists/"+listID+"/subscriptions/"+recipientID, req.URL.String()) - - rw.WriteHeader(http.StatusNoContent) - - })) - defer server.Close() - - t.Run("unsubscribe from a list", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - client.ListUnsubscribe(context.Background(), listID, recipientID) - }) -} diff --git a/v2/messages.go b/v2/messages.go deleted file mode 100644 index e3f4ce5..0000000 --- a/v2/messages.go +++ /dev/null @@ -1,68 +0,0 @@ -package courier - -import ( - "context" - "fmt" -) - -// ProvidersChannelResponse represents the channel section of the ProvidersResponse -type ProvidersChannelResponse struct { - Key string - Name string - Template string -} - -// ProvidersResponse represents the providers section of the MessageResponse -type ProvidersResponse struct { - Channel *ProvidersChannelResponse - Error string - Status string - Delivered int64 - Sent int64 - Clicked int64 - Provider string - ProviderResponse interface{} - Reference interface{} -} - -// MessageResponse represents the return of the /messages/* endpoints on the Courier API -type MessageResponse struct { - ID string - Event string - Notification string - Status string - Error string - Reason string - Recipient string - JobId string - ListId string - ListMessageId string - RunId string - Enqueued int64 - Delivered int64 - Sent int64 - Clicked int64 - Opened int64 - CanceledAt int64 - Providers []*ProvidersResponse -} - -// GetMessage calls the /messages/:id endpoint of the Courier API -func (c *Client) GetMessage(ctx context.Context, messageID string) (*MessageResponse, error) { - var response MessageResponse - err := c.API.SendRequestWithJSON(ctx, "GET", "/messages/"+messageID, nil, &response) - if err != nil { - return nil, err - } - return &response, nil -} - -// CancelMessage calls the /messages/:id/cancel endpoint of the Courier API -func (c *Client) CancelMessage(ctx context.Context, messageID string) (*MessageResponse, error) { - var response MessageResponse - err := c.API.SendRequestWithJSON(ctx, "POST", fmt.Sprintf("/messages/%s/cancel", messageID), nil, &response) - if err != nil { - return nil, err - } - return &response, nil -} diff --git a/v2/messages_test.go b/v2/messages_test.go deleted file mode 100644 index ba81796..0000000 --- a/v2/messages_test.go +++ /dev/null @@ -1,99 +0,0 @@ -package courier_test - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/trycourier/courier-go/v2" -) - -func TestMessages_GetMessage(t *testing.T) { - requestMessageID := "1-23456789" - status := "CLICKED" - sent := int64(1589563865697) - var expectedURL string - var rsp courier.MessageResponse - - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, expectedURL, req.URL.String()) - - rw.WriteHeader(http.StatusOK) - rw.Header().Add("Content-Type", "application/json") - bytes, err := json.Marshal(rsp) - assert.Nil(t, err) - _, _ = rw.Write(bytes) - }), - ) - defer server.Close() - - t.Run("makes requests for message ID", func(t *testing.T) { - rsp = createResponse(requestMessageID, sent, status) - defer func() { rsp = courier.MessageResponse{} }() // reset response between tests - - expectedURL = "/messages/" + requestMessageID - - client := courier.CreateClient("key", &server.URL) - response, err := client.GetMessage(context.Background(), requestMessageID) - assert.Nil(t, err) - - assert.Equal(t, requestMessageID, response.ID) - assert.Equal(t, sent, response.Sent) - assert.Equal(t, status, response.Status) - }) - - t.Run("makes requests to cancel a message", func(t *testing.T) { - rsp = createResponse(requestMessageID, sent, status) - defer func() { rsp = courier.MessageResponse{} }() // reset response between tests - - canceledAt := int64(4567890) - rsp.CanceledAt = canceledAt - - expectedURL = fmt.Sprintf("/messages/%s/cancel", requestMessageID) - - client := courier.CreateClient("key", &server.URL) - response, err := client.CancelMessage(context.Background(), requestMessageID) - assert.Nil(t, err) - - assert.Equal(t, requestMessageID, response.ID) - assert.Equal(t, sent, response.Sent) - assert.Equal(t, status, response.Status) - assert.Equal(t, canceledAt, response.CanceledAt) - }) -} - -func createResponse(requestMessageID string, sent int64, status string) courier.MessageResponse { - return courier.MessageResponse{ - ID: requestMessageID, - Clicked: 1589563890843, - Delivered: 1589563972000, - Enqueued: 1589563863773, - Event: "GEFGNB2GNQ4MZVHW4WV4R8Q8ZVN5", - Notification: "GEFGNB2GNQ4MZVHW4WV4R8Q8ZVN5", - Providers: []*courier.ProvidersResponse{ - { - Channel: &courier.ProvidersChannelResponse{ - Key: "sendgrid", - Template: "5e95b992-3505-4f66-8808-f91d5d0fe8c9", - }, - Clicked: 1589563890843, - Delivered: 1589563972000, - Provider: "sendgrid", - Reference: map[string]string{ - "message_id": "Xx14o44jToS8StSTPLGsTw.filterdrecv-p3iad2-8ddf98858-7qsdm-19-5EBED1D9-D3.0", - "x-message-id": "Xx14o44jToS8StSTPLGsTw", - }, - Sent: 1589563865697, - Status: "DELIVERED", - }, - }, - Recipient: "tony@trycourier.com", - Sent: sent, - Status: status, - } -} diff --git a/v2/notifications.go b/v2/notifications.go deleted file mode 100644 index 4d53746..0000000 --- a/v2/notifications.go +++ /dev/null @@ -1,229 +0,0 @@ -package courier - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "net/http" -) - -type NotificationResponse struct { - ID string - Title string -} - -type NotificationsResponse struct { - Paging *PagingResponse - Results []*NotificationResponse -} - -type NotificationContentResponse struct { - Blocks []interface{} `json:"blocks"` - Channels []interface{} `json:"channels,omitempty"` - Checksum string `json:"checksum"` -} - -type NotificationVariationsRequestBody struct { - Blocks []interface{} `json:"blocks,omitempty"` - Channels []interface{} `json:"channels,omitempty"` -} - -type SubmissionCheck struct { - ID string `json:"id"` - Status string `json:"status"` - Type string `json:"type"` - Updated int `json:"updated,omitempty"` -} - -type NotificationSubmissionChecksResponse struct { - Checks []*SubmissionCheck -} - -type NotificationSubmissionChecksRequest struct { - Checks []SubmissionCheck `json:"checks"` -} - -// GetNotifications calls the GET /notifications endpoint of the Courier API -func (c *Client) GetNotifications(ctx context.Context, cursor string) (*NotificationsResponse, error) { - url := c.API.BaseURL + "/notifications" - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - q := req.URL.Query() - if cursor != "" { - q.Add("cursor", cursor) - } - req.URL.RawQuery = q.Encode() - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data NotificationsResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// GetNotificationContent calls the GET /notifications/{notification_id}/content endpoint of the Courier API -func (c *Client) GetNotificationContent(ctx context.Context, notificationID string) (*NotificationContentResponse, error) { - if notificationID == "" { - return nil, errors.New("Notification ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/notifications/%s/content", notificationID) - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data NotificationContentResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// GetNotificationDraftContent calls the GET /notifications/{notification_id}/draft/content endpoint of the Courier API -func (c *Client) GetNotificationDraftContent(ctx context.Context, notificationID string) (*NotificationContentResponse, error) { - if notificationID == "" { - return nil, errors.New("Notification ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/notifications/%s/draft/content", notificationID) - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data NotificationContentResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// PostNotificationVariations calls the POST /notifications/{notification_id}/variations endpoint of the Courier API -func (c *Client) PostNotificationVariations(ctx context.Context, notificationID string, body interface{}) error { - bodyMap, err := toJSONMap(body) - if err != nil { - return err - } - - _, err = c.API.SendRequestWithMaps(ctx, "POST", "/notifications/"+notificationID+"/variations", bodyMap) - if err != nil { - return err - } - - return nil -} - -// PostNotificationDraftVariations calls the POST /notifications/{notification_id}/draft/variations endpoint of the Courier API -func (c *Client) PostNotificationDraftVariations(ctx context.Context, notificationID string, body interface{}) error { - bodyMap, err := toJSONMap(body) - if err != nil { - return err - } - - _, err = c.API.SendRequestWithMaps(ctx, "POST", "/notifications/"+notificationID+"/draft/variations", bodyMap) - if err != nil { - return err - } - - return nil -} - -// GetNotificationSubmissionChecks calls the GET /notifications/{notification_id}/{submission_id}/checks endpoint of the Courier API -func (c *Client) GetNotificationSubmissionChecks(ctx context.Context, notificationID string, submissionID string) (*NotificationSubmissionChecksResponse, error) { - if notificationID == "" { - return nil, errors.New("Notification ID is required") - } - - if submissionID == "" { - return nil, errors.New("Submission ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/notifications/%s/%s/checks", notificationID, submissionID) - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data NotificationSubmissionChecksResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// PutNotificationSubmissionChecks calls the PUT /notifications/{notification_id}/{submission_id}/checks endpoint of the Courier API -func (c *Client) PutNotificationSubmissionChecks(ctx context.Context, notificationID string, submissionID string, body interface{}) error { - bodyMap, err := toJSONMap(body) - if err != nil { - return err - } - - _, err = c.API.SendRequestWithMaps(ctx, "PUT", "/notifications/"+notificationID+"/"+submissionID+"/checks", bodyMap) - if err != nil { - return err - } - - return nil -} - -// CancelNotificationSubmission calls the DELETE /notifications/{notification_id}/{submission_id}/checks endpoint of the Courier API -func (c *Client) CancelNotificationSubmission(ctx context.Context, notificationID string, submissionID string) error { - if notificationID == "" { - return errors.New("Notification ID is required") - } - - if submissionID == "" { - return errors.New("Submission ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/notifications/%s/%s/checks", notificationID, submissionID) - - req, err := http.NewRequestWithContext(ctx, "DELETE", url, nil) - if err != nil { - return err - } - - _, err = c.API.ExecuteRequest(req) - if err != nil { - return err - } - - return nil -} diff --git a/v2/notifications_test.go b/v2/notifications_test.go deleted file mode 100644 index 1f1351f..0000000 --- a/v2/notifications_test.go +++ /dev/null @@ -1,302 +0,0 @@ -package courier_test - -import ( - "context" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/trycourier/courier-go/v2" -) - -func TestGetNotifications(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/notifications", req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - - rsp := ` - { - "Paging": { - "Cursor": null, - "More": false - }, - "Results": [ - { - "ID": "my-notification", - "Title": "My Awesome Notification" - } - ] - }` - _, _ = rw.Write([]byte(rsp)) - - })) - defer server.Close() - - t.Run("Get Notifications", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - rsp, err := client.GetNotifications(context.Background(), "") - assert.Nil(t, err) - assert.Equal(t, "my-notification", rsp.Results[0].ID) - assert.Equal(t, "My Awesome Notification", rsp.Results[0].Title) - }) -} - -func TestGetNotificationContent(t *testing.T) { - notificationID := "my-notification" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/notifications/"+notificationID+"/content", req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - - rsp := ` - { - "blocks": [{ - "id": "block_00d0bcb0-aba1-443f-a8dd-daac505500fe", - "type": "text", - "content": "text block", - "checksum": "block-checksum", - "locales": { - "fr_FR": "french text block" - } - }], - "channels": [{ - "id": "channel_79d25574-83be-4da1-a5c3-3d4e2ab5f154", - "type": "email", - "content": { - "subject": "Hey hey!" - }, - "checksum": "channel-checksum", - "locales": { - "fr_FR": { - "subject": "French hey!" - } - } - }] - }` - _, _ = rw.Write([]byte(rsp)) - - })) - defer server.Close() - - t.Run("Get Notification Content", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - rsp, err := client.GetNotificationContent(context.Background(), notificationID) - assert.Nil(t, err) - assert.Equal(t, 1, len(rsp.Blocks)) - assert.Equal(t, 1, len(rsp.Channels)) - }) -} - -func TestGetNotificationDraftContent(t *testing.T) { - notificationID := "my-notification" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/notifications/"+notificationID+"/draft/content", req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - - rsp := ` - { - "blocks": [{ - "id": "block_00d0bcb0-aba1-443f-a8dd-daac505500fe", - "type": "text", - "content": "text block", - "checksum": "block-checksum", - "locales": { - "fr_FR": "french text block" - } - }], - "channels": [{ - "id": "channel_79d25574-83be-4da1-a5c3-3d4e2ab5f154", - "type": "email", - "content": { - "subject": "Hey hey!" - }, - "checksum": "channel-checksum", - "locales": { - "fr_FR": { - "subject": "French hey!" - } - } - }] - }` - _, _ = rw.Write([]byte(rsp)) - - })) - defer server.Close() - - t.Run("Get Notification Draft Content", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - rsp, err := client.GetNotificationDraftContent(context.Background(), notificationID) - assert.Nil(t, err) - assert.Equal(t, 1, len(rsp.Blocks)) - assert.Equal(t, 1, len(rsp.Channels)) - }) -} - -func TestPostNotificationVariations(t *testing.T) { - notificationID := "my-notification" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/notifications/"+notificationID+"/variations", req.URL.String()) - - rw.WriteHeader(http.StatusNoContent) - - })) - defer server.Close() - - t.Run("Post Notification Variations", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - client.PostNotificationVariations(context.Background(), notificationID, courier.NotificationVariationsRequestBody{ - Blocks: []interface{}{ - map[string]string{"id": "block_00d0bcb0-aba1-443f-a8dd-daac505500fe"}, - map[string]string{"type": "text"}, - // ...locales - }, - Channels: []interface{}{ - map[string]string{"id": "channel_79d25574-83be-4da1-a5c3-3d4e2ab5f154"}, - // ...locales - }, - }) - }) -} - -func TestPostNotificationDraftVariations(t *testing.T) { - notificationID := "my-notification" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/notifications/"+notificationID+"/draft/variations", req.URL.String()) - - rw.WriteHeader(http.StatusNoContent) - - })) - defer server.Close() - - t.Run("Post Notification Draft Variations", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - client.PostNotificationDraftVariations(context.Background(), notificationID, courier.NotificationVariationsRequestBody{ - Blocks: []interface{}{ - map[string]string{"id": "block_00d0bcb0-aba1-443f-a8dd-daac505500fe"}, - map[string]string{"type": "text"}, - // ...locales - }, - Channels: []interface{}{ - map[string]string{"id": "channel_79d25574-83be-4da1-a5c3-3d4e2ab5f154"}, - // ...locales - }, - }) - }) -} - -func TestGetNotificationSubmissionChecks(t *testing.T) { - notificationID := "my-notification" - submissionID := "my-submission" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/notifications/"+notificationID+"/"+submissionID+"/checks", req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - - rsp := ` - { - "Checks": [ - { - "ID": "my-check", - "Status": "PENDING", - "Type": "custom", - "Updated": 1629169195778 - } - ] - }` - _, _ = rw.Write([]byte(rsp)) - - })) - defer server.Close() - - t.Run("Get Notification Submission Checks", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - rsp, err := client.GetNotificationSubmissionChecks(context.Background(), notificationID, submissionID) - assert.Nil(t, err) - assert.Equal(t, "my-check", rsp.Checks[0].ID) - assert.Equal(t, "PENDING", rsp.Checks[0].Status) - assert.Equal(t, "custom", rsp.Checks[0].Type) - assert.Equal(t, 1629169195778, rsp.Checks[0].Updated) - }) -} - -func TestPutNotificationSubmissionChecks(t *testing.T) { - notificationID := "my-notification" - submissionID := "my-submission" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/notifications/"+notificationID+"/"+submissionID+"/checks", req.URL.String()) - - rw.Header().Add("Content-Type", "application/json") - - rsp := ` - { - "Checks": [ - { - "ID": "my-check", - "Status": "RESOLVED", - "Type": "custom", - "Updated": 1629169195779 - } - ] - }` - _, _ = rw.Write([]byte(rsp)) - - })) - defer server.Close() - - t.Run("Put Notification Submission Checks", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - client.PutNotificationSubmissionChecks(context.Background(), notificationID, submissionID, courier.NotificationSubmissionChecksRequest{ - Checks: []courier.SubmissionCheck{ - courier.SubmissionCheck{ - ID: "my-check", - Status: "RESOLVED", - Type: "custom", - }, - }, - }) - }) -} - -func TestCancelNotificationSubmission(t *testing.T) { - notificationID := "my-notification" - submissionID := "my-submission" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/notifications/"+notificationID+"/"+submissionID+"/checks", req.URL.String()) - - rw.WriteHeader(http.StatusNoContent) - - })) - defer server.Close() - - t.Run("Delete Notification Submission", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - client.CancelNotificationSubmission(context.Background(), notificationID, submissionID) - }) -} diff --git a/v2/profiles.go b/v2/profiles.go deleted file mode 100644 index 9739a9d..0000000 --- a/v2/profiles.go +++ /dev/null @@ -1,23 +0,0 @@ -package courier - -import ( - "context" - "encoding/json" -) - -// GetProfile calls the GET /profiles/:id endpoint of the Courier API -func (c *Client) GetProfile(ctx context.Context, id string) (map[string]json.RawMessage, error) { - return c.API.SendRequestWithMaps(ctx, "GET", "/profiles/"+id, nil) -} - -// MergeProfileBytes calls the POST /profiles/:id endpoint of the Courier API -func (c *Client) MergeProfileBytes(ctx context.Context, id string, profile []byte) error { - _, err := c.API.SendRequestWithBytes(ctx, "POST", "/profiles/"+id, profile) - return err -} - -// UpdateProfileBytes calls the PUT /profiles/:id endpoint of the Courier API -func (c *Client) UpdateProfileBytes(ctx context.Context, id string, profile []byte) error { - _, err := c.API.SendRequestWithBytes(ctx, "PUT", "/profiles/"+id, profile) - return err -} diff --git a/v2/profiles_test.go b/v2/profiles_test.go deleted file mode 100644 index 54f38e0..0000000 --- a/v2/profiles_test.go +++ /dev/null @@ -1,102 +0,0 @@ -package courier_test - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "log" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/trycourier/courier-go/v2" -) - -func TestProfiles_GetProfile(t *testing.T) { - profileID := "example" - foo := "bar" - url := "/profiles/" + profileID - - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, url, req.URL.String()) - rw.WriteHeader(http.StatusOK) - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "profile": { - "foo": "%s" - } - }` - _, _ = rw.Write([]byte(fmt.Sprintf(rsp, foo))) - }), - ) - defer server.Close() - - t.Run("makes requests for message ID", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - response, err := client.GetProfile(context.Background(), profileID) - assert.Nil(t, err) - - var profile map[string]string - err = json.Unmarshal(response["profile"], &profile) - assert.Nil(t, err) - - assert.Equal(t, "bar", profile["foo"]) - }) -} - -func TestProfiles_ProfilePOST(t *testing.T) { - type RequestBody struct { - Profile interface{} - } - - var requestBody RequestBody - recipientID := "123456789" - url := "/profiles/" + recipientID - - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, url, req.URL.String()) - - buf := new(bytes.Buffer) - buf.ReadFrom(req.Body) - bodyJSON := buf.String() - log.Println("profiles_test.go: TestProfiles_MergeProfile") - log.Println(bodyJSON) - - err := json.Unmarshal(buf.Bytes(), &requestBody) - if err != nil { - t.Error(err) - } - - rw.WriteHeader(http.StatusOK) - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"status\" : \"%s\" }", "SUCCESS"))) - if writeErr != nil { - t.Error(writeErr) - } - }), - ) - defer server.Close() - - t.Run("sends request", func(t *testing.T) { - profile := make(map[string]interface{}) - profile["email"] = "foo@bar.com" - - body := make(map[string]interface{}) - body["profile"] = profile - - bytes, err := json.Marshal(body) - if err != nil { - t.Error(err) - } - - client := courier.CreateClient("key", &server.URL) - _, err = client.API.SendRequestWithBytes(context.Background(), "POST", "/profiles/"+recipientID, bytes) - - assert.Nil(t, err) - }) -} diff --git a/v2/send.go b/v2/send.go deleted file mode 100644 index f185abf..0000000 --- a/v2/send.go +++ /dev/null @@ -1,149 +0,0 @@ -package courier - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "net/http" - "strconv" - "time" -) - -// SendBody is the JSON body expected by Courier's /send endpoint -type SendBody struct { - Profile interface{} `json:"profile"` - Data interface{} `json:"data"` - Override interface{} `json:"override,omitempty"` - Brand string `json:"brand,omitempty"` -} - -// SendMessageRequestBody is the JSON body expected by -// Courier's /send endpoint that accepts a message object -type SendMessageRequestBody struct { - Message interface{} `json:"message"` -} - -// Send calls the /send endpoint of the Courier API (passing a struct) -func (c *Client) Send(ctx context.Context, eventID, recipientID string, body interface{}) (string, error) { - bodyMap, err := toJSONMap(body) - if err != nil { - return "", err - } - return c.SendMap(ctx, eventID, recipientID, bodyMap) -} - -// SendMap calls the /send endpoint of the Courier API (passing maps) -func (c *Client) SendMap(ctx context.Context, eventID, recipientID string, body map[string]interface{}) (string, error) { - // these are required, so we accept them as separate params - body["event"] = eventID - body["recipient"] = recipientID - - response, err := c.API.SendRequestWithMaps(ctx, "POST", "/send", body) - if err != nil { - return "", err - } - - var messageID string - err = json.Unmarshal(response["messageId"], &messageID) - if err != nil { - return "", err - } - return messageID, nil -} - -// SendMessage calls the enhanced /send endpoint of the Courier API with a message struct -func (c *Client) SendMessage(ctx context.Context, body SendMessageRequestBody) (string, error) { - bodyMap, err := toJSONMap(body) - if err != nil { - return "", err - } - return c.SendMessageMap(ctx, bodyMap) -} - -// SendMessageMap calls the enhanced /send endpoint of the Courier API with maps -func (c *Client) SendMessageMap(ctx context.Context, body map[string]interface{}) (string, error) { - response, err := c.API.SendRequestWithMaps(ctx, "POST", "/send", body) - if err != nil { - return "", err - } - - var requestID string - err = json.Unmarshal(response["requestId"], &requestID) - if err != nil { - return "", err - } - return requestID, nil -} - -type Option interface { - apply(r *http.Request) error -} - -type reqFunc func(r *http.Request) error - -func (fn reqFunc) apply(r *http.Request) error { - return fn(r) -} - -func (c *Client) newSendRequest(ctx context.Context, body io.Reader, method string, opts ...Option) (*http.Request, error) { - fullyQualifiedURL := fmt.Sprintf("%s/send", c.API.BaseURL) - req, err := http.NewRequestWithContext(ctx, method, fullyQualifiedURL, body) - if err != nil { - return nil, err - } - - for _, opt := range opts { - if err := opt.apply(req); err != nil { - return req, err - } - } - return req, err -} - -func withHeader(header, value string) Option { - return reqFunc(func(r *http.Request) error { - if header != "" && value != "" { - r.Header.Add(header, value) - } - return nil - }) -} - -func WithIdempotencyKey(value string) Option { - return withHeader("Idempotency-Key", value) -} - -func WithIdempotencyKeyExpiration(expiration time.Time) Option { - return withHeader("x-idempotency-expiration", strconv.FormatInt(expiration.UnixMilli(), 10)) -} - -func (c *Client) SendMessageWithOptions(ctx context.Context, body map[string]interface{}, method string, opts ...Option) (string, error) { - if method == "GET" { - body = nil - } - bytesBody, err := json.Marshal(body) - if err != nil { - return "", err - } - buf := bytes.NewReader(bytesBody) - - req, err := c.newSendRequest(ctx, buf, method, opts...) - if err != nil { - return "", err - } - - res, err := c.API.ExecuteRequest(req) - if err != nil { - return "", err - } - - var payload map[string]string - err = json.Unmarshal(res, &payload) - if err != nil { - return "", err - } - - return payload["requestId"], nil -} diff --git a/v2/send_test.go b/v2/send_test.go deleted file mode 100644 index 98a0ec6..0000000 --- a/v2/send_test.go +++ /dev/null @@ -1,568 +0,0 @@ -package courier_test - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "log" - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/trycourier/courier-go/v2" -) - -func TestSend_SendMap(t *testing.T) { - type Data struct { - Foo string - } - type Profile struct { - Email string - } - type RequestBody struct { - Event string - Recipient string - Profile Profile - Data Data - } - - var requestBody RequestBody - url := "/send" - messageID := "123456789" - - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, url, req.URL.String()) - - buf := new(bytes.Buffer) - buf.ReadFrom(req.Body) - bodyJSON := buf.String() - log.Println("send_test.go: TestSendMap") - log.Println(bodyJSON) - - err := json.Unmarshal(buf.Bytes(), &requestBody) - if err != nil { - t.Error(err) - } - - rw.WriteHeader(http.StatusOK) - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"messageId\" : \"%s\" }", messageID))) - if writeErr != nil { - t.Error(writeErr) - } - }), - ) - defer server.Close() - - t.Run("sends request", func(t *testing.T) { - eventID := "event-id" - recipientID := "recipient-id" - - profile := make(map[string]interface{}) - profile["email"] = "foo@bar.com" - - data := make(map[string]interface{}) - data["foo"] = "bar" - - body := make(map[string]interface{}) - body["profile"] = profile - body["data"] = data - - client := courier.CreateClient("key", &server.URL) - result, err := client.SendMap(context.Background(), eventID, recipientID, body) - - assert.Nil(t, err) - assert.Equal(t, messageID, result) - assert.Equal(t, eventID, requestBody.Event) - assert.Equal(t, recipientID, requestBody.Recipient) - assert.Equal(t, "foo@bar.com", requestBody.Profile.Email) - assert.Equal(t, "bar", requestBody.Data.Foo) - }) -} - -func TestSend_Send(t *testing.T) { - type RequestData struct { - Foo string - } - type RequestProfile struct { - Email string - } - type RequestBodyOverride struct { - ReplyBroadcast bool `json:"reply_broadcast"` - } - type RequestSlackOverride struct { - Body RequestBodyOverride - } - type RequestOverride struct { - Slack RequestSlackOverride - } - type RequestBody struct { - Event string - Recipient string - Profile RequestProfile - Data RequestData - Override RequestOverride - Brand string - } - type data struct { - Foo string `json:"foo"` - } - type profile struct { - Email string `json:"email"` - } - - var requestBody RequestBody - url := "/send" - messageID := "123456789" - eventID := "event-id" - recipientID := "recipient-id" - - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, url, req.URL.String()) - - buf := new(bytes.Buffer) - buf.ReadFrom(req.Body) - bodyJSON := buf.String() - log.Println("send_test.go: TestSendStruct") - log.Println(bodyJSON) - - err := json.Unmarshal(buf.Bytes(), &requestBody) - if err != nil { - t.Error(err) - } - - rw.WriteHeader(http.StatusOK) - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"messageId\" : \"%s\" }", messageID))) - if writeErr != nil { - t.Error(writeErr) - } - }), - ) - defer server.Close() - - t.Run("sends request", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - result, err := client.Send(context.Background(), eventID, recipientID, courier.SendBody{ - Profile: profile{ - Email: "foo@bar.com", - }, - Data: data{ - Foo: "bar", - }, - }) - - assert.Nil(t, err) - assert.Equal(t, messageID, result) - assert.Equal(t, eventID, requestBody.Event) - assert.Equal(t, recipientID, requestBody.Recipient) - assert.Equal(t, "foo@bar.com", requestBody.Profile.Email) - assert.Equal(t, "bar", requestBody.Data.Foo) - }) - - t.Run("sends request with override", func(t *testing.T) { - type bodyOverride struct { - ReplyBroadcast bool `json:"reply_broadcast"` - } - type slackOverride struct { - Body bodyOverride `json:"body"` - } - type override struct { - Slack slackOverride `json:"slack"` - } - - client := courier.CreateClient("key", &server.URL) - result, err := client.Send(context.Background(), eventID, recipientID, courier.SendBody{ - Profile: profile{ - Email: "foo@bar.com", - }, - Data: data{ - Foo: "bar", - }, - Override: override{ - Slack: slackOverride{ - Body: bodyOverride{ - ReplyBroadcast: true, - }, - }, - }, - }) - - assert.Nil(t, err) - assert.Equal(t, messageID, result) - assert.Equal(t, eventID, requestBody.Event) - assert.Equal(t, recipientID, requestBody.Recipient) - assert.Equal(t, "foo@bar.com", requestBody.Profile.Email) - assert.Equal(t, "bar", requestBody.Data.Foo) - assert.Equal(t, true, requestBody.Override.Slack.Body.ReplyBroadcast) - }) - - t.Run("sends request with brand", func(t *testing.T) { - type data struct { - Foo string `json:"foo"` - } - type profile struct { - Email string `json:"email"` - } - - eventID := "event-id" - recipientID := "recipient-id" - - client := courier.CreateClient("key", &server.URL) - result, err := client.Send(context.Background(), eventID, recipientID, courier.SendBody{ - Profile: profile{ - Email: "foo@bar.com", - }, - Data: data{ - Foo: "bar", - }, - Brand: "dispatcher", - }) - - assert.Nil(t, err) - assert.Equal(t, messageID, result) - assert.Equal(t, eventID, requestBody.Event) - assert.Equal(t, recipientID, requestBody.Recipient) - assert.Equal(t, "foo@bar.com", requestBody.Profile.Email) - assert.Equal(t, "bar", requestBody.Data.Foo) - assert.Equal(t, "dispatcher", requestBody.Brand) - }) -} - -func TestSend_Send_400Error(t *testing.T) { - type RequestData struct { - Foo string - } - type RequestProfile struct { - Email string - } - type RequestBody struct { - Event string - Recipient string - Profile RequestProfile - Data RequestData - } - - var requestBody RequestBody - url := "/send" - messageID := "123456789" - - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, url, req.URL.String()) - - buf := new(bytes.Buffer) - buf.ReadFrom(req.Body) - bodyJSON := buf.String() - log.Println("send_test.go: TestSendStruct") - log.Println(bodyJSON) - - err := json.Unmarshal(buf.Bytes(), &requestBody) - if err != nil { - t.Error(err) - } - - rw.WriteHeader(http.StatusBadRequest) - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"messageId\" : \"%s\" }", messageID))) - if writeErr != nil { - t.Error(writeErr) - } - }), - ) - defer server.Close() - - t.Run("sends request", func(t *testing.T) { - type data struct { - Foo string `json:"foo"` - } - type profile struct { - Email string `json:"email"` - } - - eventID := "event-id" - recipientID := "recipient-id" - - client := courier.CreateClient("key", &server.URL) - _, err := client.Send(context.Background(), eventID, recipientID, courier.SendBody{ - Profile: profile{ - Email: "foo@bar.com", - }, - Data: data{ - Foo: "bar", - }, - }) - - assert.NotNil(t, err) - assert.Equal(t, http.StatusBadRequest, err.(*courier.HTTPError).StatusCode) - }) -} - -func TestSend_SendMessage(t *testing.T) { - var requestBody courier.SendMessageRequestBody - url := "/send" - requestID := "123456789" - - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, url, req.URL.String()) - - buf := new(bytes.Buffer) - buf.ReadFrom(req.Body) - - err := json.Unmarshal(buf.Bytes(), &requestBody) - if err != nil { - t.Error(err) - } - - rw.WriteHeader(http.StatusOK) - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"requestId\" : \"%s\" }", requestID))) - if writeErr != nil { - t.Error(writeErr) - } - }), - ) - defer server.Close() - - t.Run("sends request", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - result, err := client.SendMessage(context.Background(), courier.SendMessageRequestBody{ - Message: map[string]interface{}{ - "template": "my-template", - "to": map[string]string{ - "email": "foo@bar.com", - }, - }, - }) - - assert.Nil(t, err) - assert.Equal(t, requestID, result) - }) -} - -func TestSend_SendMessage_Timeout(t *testing.T) { - var requestBody courier.SendMessageRequestBody - url := "/send" - requestID := "123456789" - - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, url, req.URL.String()) - - buf := new(bytes.Buffer) - buf.ReadFrom(req.Body) - - err := json.Unmarshal(buf.Bytes(), &requestBody) - if err != nil { - t.Error(err) - } - - rw.WriteHeader(http.StatusOK) - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"requestId\" : \"%s\" }", requestID))) - if writeErr != nil { - t.Error(writeErr) - } - }), - ) - defer server.Close() - - t.Run("sends request with timeout", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - result, err := client.SendMessage(context.Background(), courier.SendMessageRequestBody{ - Message: map[string]interface{}{ - "template": "my-template", - "to": map[string]string{ - "email": "foo@bar.com", - }, - "timeout": int64(3600000), // 1 hour in milliseconds - }, - }) - - assert.Nil(t, err) - assert.Equal(t, requestID, result) - }) -} - -func TestSend_SendMessageWithOptions(t *testing.T) { - var requestBody courier.SendMessageRequestBody - url := "/send" - requestID := "123456789" - - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, url, req.URL.String()) - - buf := new(bytes.Buffer) - buf.ReadFrom(req.Body) - - err := json.Unmarshal(buf.Bytes(), &requestBody) - if err != nil { - t.Error(err) - } - - rw.WriteHeader(http.StatusOK) - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"requestId\" : \"%s\" }", requestID))) - if writeErr != nil { - t.Error(writeErr) - } - }), - ) - defer server.Close() - - t.Run("sends request with idempotency key", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - result, err := client.SendMessageWithOptions( - context.Background(), - map[string]interface{}{ - "template": "my-template", - "to": map[string]string{ - "email": "foo@bar.com", - }, - }, - "POST", - courier.WithIdempotencyKey("fake-key"), - ) - - assert.Nil(t, err) - assert.Equal(t, requestID, result) - }) - t.Run("sends request with idempotency key and key expiration", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - expiration := time.Now().Add(time.Hour * 26) - result, err := client.SendMessageWithOptions( - context.Background(), - map[string]interface{}{ - "template": "my-template", - "to": map[string]string{ - "email": "foo@bar.com", - }, - }, - "POST", - courier.WithIdempotencyKey("fake-key"), - courier.WithIdempotencyKeyExpiration(expiration), - ) - - assert.Nil(t, err) - assert.Equal(t, requestID, result) - }) -} - -func TestSend_SendMessage_WithMetadata(t *testing.T) { - var requestBody courier.SendMessageRequestBody - url := "/send" - requestID := "123456789" - - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, url, req.URL.String()) - - buf := new(bytes.Buffer) - buf.ReadFrom(req.Body) - - err := json.Unmarshal(buf.Bytes(), &requestBody) - if err != nil { - t.Error(err) - } - - rw.WriteHeader(http.StatusOK) - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"requestId\" : \"%s\" }", requestID))) - if writeErr != nil { - t.Error(writeErr) - } - }), - ) - defer server.Close() - - t.Run("sends request with metadata.trace_id", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - result, err := client.SendMessage(context.Background(), courier.SendMessageRequestBody{ - Message: map[string]interface{}{ - "template": "my-template", - "to": map[string]string{ - "email": "foo@bar.com", - }, - "metadata": map[string]string{ - "trace_id": "pikachu&eevee", - }, - }, - }) - - assert.Nil(t, err) - assert.Equal(t, requestID, result) - }) -} - -func TestSend_SendMessage_WithGranularMetadata(t *testing.T) { - var requestBody courier.SendMessageRequestBody - url := "/send" - requestID := "123456789" - - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, url, req.URL.String()) - - buf := new(bytes.Buffer) - buf.ReadFrom(req.Body) - - err := json.Unmarshal(buf.Bytes(), &requestBody) - if err != nil { - t.Error(err) - } - - rw.WriteHeader(http.StatusOK) - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"requestId\" : \"%s\" }", requestID))) - if writeErr != nil { - t.Error(writeErr) - } - }), - ) - defer server.Close() - - t.Run("sends request with granular metadata", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - result, err := client.SendMessage(context.Background(), courier.SendMessageRequestBody{ - Message: map[string]interface{}{ - "template": "my-template", - "to": map[string]string{ - "email": "foo@bar.com", - }, - "metadata": map[string]interface{}{ - "utm": map[string]string{ - "source": "go", - }, - }, - "channels": map[string]interface{}{ - "email": map[string]interface{}{ - "metadata": map[string]interface{}{ - "utm": map[string]string{ - "medium": "email", - }, - }, - }, - }, - "providers": map[string]interface{}{ - "sendgrid": map[string]interface{}{ - "metadata": map[string]interface{}{ - "utm": map[string]string{ - "campaign": "sendgrid", - }, - }, - }, - }, - }, - }) - - assert.Nil(t, err) - assert.Equal(t, requestID, result) - }) -} diff --git a/v2/shared.go b/v2/shared.go deleted file mode 100644 index b8df68e..0000000 --- a/v2/shared.go +++ /dev/null @@ -1,6 +0,0 @@ -package courier - -type PagingResponse struct { - Cursor *string - More bool -} diff --git a/v2/tenants.go b/v2/tenants.go deleted file mode 100644 index 4c609f7..0000000 --- a/v2/tenants.go +++ /dev/null @@ -1,140 +0,0 @@ -package courier - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "net/http" -) - -// Account is the type for account entity -type Tenant struct { - Id string `json:"id"` - Name string `json:"name"` - ParentTenantId string `json:"parent_tenant_id,omitempty"` - DefaultPreferences interface{} `json:"default_preferences,omitempty"` - Properties interface{} `json:"properties,omitempty"` - UserProfile interface{} `json:"user_profile,omitempty"` - BrandId string `json:"brand_id,omitempty"` -} - -// ListTenantsResponse is type for the GET /tenants response -type ListTenantsResponse struct { - Items []Tenant `json:"items"` - HasMore bool `json:"has_more"` - Url string `json:"url"` - NextUrl string `json:"next_url,omitempty"` -} - -// GetTenant calls the GET /tenants/:tenantId endpoint of the Courier API -func (c *Client) GetTenant(ctx context.Context, tenantId string) (*Tenant, error) { - if tenantId == "" { - return nil, errors.New("tenant ID is required") - } - url := fmt.Sprintf(c.API.BaseURL+"/tenants/%s", tenantId) - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data Tenant - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// GetAccounts calls the GET /tenants endpoint of the Courier API -func (c *Client) GetTenants(ctx context.Context, limit string, cursor string) (*ListTenantsResponse, error) { - url := fmt.Sprintf(c.API.BaseURL + "/tenants") - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, err - } - - q := req.URL.Query() - if limit != "" { - q.Add("limit", limit) - } - if cursor != "" { - q.Add("cursor", cursor) - } - req.URL.RawQuery = q.Encode() - - bytes, err := c.API.ExecuteRequest(req) - if err != nil { - return nil, err - } - - var data ListTenantsResponse - err = json.Unmarshal(bytes, &data) - if err != nil { - return nil, err - } - - return &data, nil -} - -// Calls the PUT /tenants/:tenantId endpoint of the Courier API -func (c *Client) PutTenant(ctx context.Context, tenantId string, body interface{}) (*Tenant, error) { - if tenantId == "" { - return nil, errors.New("Tenant ID is required") - } - - reqBodyBytes := new(bytes.Buffer) - json.NewEncoder(reqBodyBytes).Encode(body) - - jsonBody, err := json.Marshal(body) - - if err != nil { - return nil, err - } - - bytes, err := c.API.SendRequestWithBytes(ctx, http.MethodPut, fmt.Sprintf("/tenants/%s", tenantId), jsonBody) - - if err != nil { - return nil, err - } - - var data Tenant - - err = json.Unmarshal(bytes, &data) - - if err != nil { - return nil, err - } - - return &data, nil -} - -// DeleteAccount calls the DELETE /accounts/:account_id endpoint of the Courier API -func (c *Client) DeleteTenant(ctx context.Context, tenantId string) error { - if tenantId == "" { - return errors.New("Tenant ID is required") - } - - url := fmt.Sprintf(c.API.BaseURL+"/tenants/%s", tenantId) - - req, err := http.NewRequestWithContext(ctx, "DELETE", url, nil) - if err != nil { - return err - } - - _, err = c.API.ExecuteRequest(req) - if err != nil { - return err - } - - return nil -} diff --git a/v2/tenants_test.go b/v2/tenants_test.go deleted file mode 100644 index daa8ba7..0000000 --- a/v2/tenants_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package courier_test - -import ( - "context" - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/trycourier/courier-go/v2" -) - -func TestGetTenant(t *testing.T) { - expectedResponseID := "123456789" - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, "/tenants/123456789", req.URL.String()) - rw.Header().Add("Content-Type", "application/json") - _, writeErr := rw.Write([]byte(fmt.Sprintf("{ \"id\" : \"%s\" }", expectedResponseID))) - if writeErr != nil { - t.Error(writeErr) - } - })) - defer server.Close() - - t.Run("Get Tenant", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - response, err := client.GetTenant(context.Background(), "123456789") - assert.Nil(t, err) - assert.Equal(t, expectedResponseID, response.Id) - }) -} - -func TestGetTenants(t *testing.T) { - expectedAccountId := "ZX3xXUMNKL4y2NkiKgstl" - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, "/tenants", req.URL.String()) - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "items": [ - { - "id": "ZX3xXUMNKL4y2NkiKgstl", - "name": "my-tenant" - } - ], - "has_more": false, - "url": "/tenants" - }` - _, _ = rw.Write([]byte(rsp)) - })) - defer server.Close() - - t.Run("Get Accounts", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - response, err := client.GetTenants(context.Background(), "", "") - assert.Nil(t, err) - assert.Equal(t, expectedAccountId, response.Items[0].Id) - assert.Equal(t, "my-tenant", response.Items[0].Name) - assert.Equal(t, "/tenants", response.Url) - }) -} - -func TestPutTenant(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - assert.Equal(t, "/tenants/tenant-1", req.URL.String()) - rw.Header().Add("Content-Type", "application/json") - rsp := ` - { - "id": "tenant-1", - "name": "My Tenant" - }` - _, _ = rw.Write([]byte(rsp)) - - })) - defer server.Close() - - t.Run("Put Account", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - - accountPutResponse, err := client.PutTenant(context.Background(), "tenant-1", map[string]string{ - "name": "My Tenant", - }) - assert.Nil(t, err) - - assert.Equal(t, "tenant-1", accountPutResponse.Id) - }) -} - -func TestDeleteAccount(t *testing.T) { - tenantId := "my-tenant" - server := httptest.NewServer(http.HandlerFunc( - - func(rw http.ResponseWriter, req *http.Request) { - - assert.Equal(t, "/tenants/"+tenantId, req.URL.String()) - - rw.WriteHeader(http.StatusNoContent) - - })) - defer server.Close() - - t.Run("Delete Account", func(t *testing.T) { - client := courier.CreateClient("key", &server.URL) - client.DeleteTenant(context.Background(), tenantId) - }) -} diff --git a/v2/webhooks.go b/v2/webhooks.go deleted file mode 100644 index 2a818d2..0000000 --- a/v2/webhooks.go +++ /dev/null @@ -1,7 +0,0 @@ -package courier - -// WebhookResponse represents the payload provided by an outbound webhook -type WebhookResponse struct { - Data MessageResponse `json:"data"` - Type string `json:"type"` -}