From f34cc5eed789c7dce75e8211a77ecaa1fa50392e Mon Sep 17 00:00:00 2001 From: speakeasybot Date: Tue, 4 Feb 2025 00:26:39 +0000 Subject: [PATCH] ci: regenerated with OpenAPI Doc , Speakeasy CLI 1.483.0 --- .speakeasy/gen.lock | 42 ++- .speakeasy/gen.yaml | 2 +- .speakeasy/workflow.lock | 14 +- README.md | 1 + RELEASES.md | 12 +- codeSamples.yaml | 27 ++ docs/models/components/analyticstoplinks.md | 1 + .../operations/createpartnerlinklinkprops.md | 35 ++ .../createpartnerlinkrequestbody.md | 13 + .../operations/createpartnerlinktagids.md | 19 + .../operations/createpartnerlinktagnames.md | 19 + docs/sdks/partners/README.md | 58 +++ pyproject.toml | 2 +- src/dub/_version.py | 6 +- .../models/components/analyticstoplinks.py | 38 +- src/dub/models/operations/__init__.py | 18 + .../models/operations/createpartnerlink.py | 333 ++++++++++++++++++ src/dub/partners.py | 302 +++++++++++++++- 18 files changed, 921 insertions(+), 21 deletions(-) create mode 100644 docs/models/operations/createpartnerlinklinkprops.md create mode 100644 docs/models/operations/createpartnerlinkrequestbody.md create mode 100644 docs/models/operations/createpartnerlinktagids.md create mode 100644 docs/models/operations/createpartnerlinktagnames.md create mode 100644 src/dub/models/operations/createpartnerlink.py diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index 58f0d8c..f74e0a0 100755 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,12 +1,12 @@ lockVersion: 2.0.0 id: ab657d60-207e-43a4-8cc8-692a672950ed management: - docChecksum: 35e4c58336f3289dc7d36cd16ac407d9 + docChecksum: 3221eb44e26e0b7b6262f2e3cf1c786a docVersion: 0.0.1 - speakeasyVersion: 1.481.1 - generationVersion: 2.500.5 - releaseVersion: 0.17.8 - configChecksum: 67c5f4804733e08778eedc7f2892453f + speakeasyVersion: 1.483.0 + generationVersion: 2.502.0 + releaseVersion: 0.17.9 + configChecksum: 318ba5ec150e0bcc07c1b4b5ca2fc6d4 repoURL: https://github.com/dubinc/dub-python.git installationURL: https://github.com/dubinc/dub-python.git published: true @@ -192,6 +192,10 @@ generatedFiles: - docs/models/operations/createlinkrequestbody.md - docs/models/operations/createpartnerdiscount.md - docs/models/operations/createpartnerinterval.md + - docs/models/operations/createpartnerlinklinkprops.md + - docs/models/operations/createpartnerlinkrequestbody.md + - docs/models/operations/createpartnerlinktagids.md + - docs/models/operations/createpartnerlinktagnames.md - docs/models/operations/createpartnerrequestbody.md - docs/models/operations/createpartnerresponsebody.md - docs/models/operations/createpartnertagids.md @@ -385,6 +389,7 @@ generatedFiles: - src/dub/models/operations/createembedtoken.py - src/dub/models/operations/createlink.py - src/dub/models/operations/createpartner.py + - src/dub/models/operations/createpartnerlink.py - src/dub/models/operations/createtag.py - src/dub/models/operations/deletecustomer.py - src/dub/models/operations/deletedomain.py @@ -754,7 +759,7 @@ examples: sortBy: "timestamp" responses: "200": - application/json: [{"event": "sale", "eventId": "", "eventName": "", "link": {"id": "", "domain": "remorseful-concentration.biz", "key": "", "url": "https://primary-paintwork.com/", "externalId": "", "tenantId": "", "programId": "", "partnerId": "", "expiresAt": "1761194819564", "expiredUrl": "https://black-poetry.name/", "password": "COyVtOrvIw1vLIJ", "title": "", "description": "despite er boom however when uh-huh", "image": "https://picsum.photos/seed/T1tZJLp1EG/3827/3109", "video": "https://loremflickr.com/2420/1632?lock=7470650813503352", "ios": "", "android": "", "geo": {}, "tagId": "", "tags": [{"id": "", "name": "", "color": "green"}], "webhookIds": [], "comments": "tenement commonly softly boo massive sorrowful", "shortLink": "https://dense-custom.info/", "qrCode": "https://alive-lid.biz", "utm_source": "", "utm_medium": "", "utm_campaign": "", "utm_term": "", "utm_content": "", "userId": "", "workspaceId": "", "clicks": 0, "lastClicked": "", "leads": 0, "sales": 0, "saleAmount": 0, "createdAt": "1726607631112", "updatedAt": "1738481259111", "projectId": ""}, "click": {"id": "", "url": "https://utilized-quit.net/", "country": "Togo", "city": "Cormiermouth", "region": "", "continent": "North America", "device": "Mobile", "browser": "Chrome", "os": "Chrome OS", "referer": "gummy-cope.net", "refererUrl": "https://prickly-bourgeoisie.info/", "ip": "69bd:53cd:cebc:ac4b:d1e8:50e8:ee59:b0b3"}, "customer": {"id": "", "externalId": "", "name": "", "createdAt": "1737363175578"}, "sale": {"amount": 625809, "invoiceId": null, "paymentProcessor": "stripe"}, "saleAmount": 1401.42, "invoice_id": "", "payment_processor": "", "click_id": "", "link_id": "", "domain": "unruly-allegation.name", "key": "", "url": "https://fortunate-swim.info/", "continent": "Australia", "country": "Cook Islands", "city": "South Harryburgh", "device": "Mobile", "browser": "Safari", "os": "WebOS", "qr": 1523.03, "ip": "caf5:04dc:da9e:67cc:af3b:8caf:afbe:e39c"}, {"event": "sale", "eventId": "", "eventName": "", "link": {"id": "", "domain": "right-window.biz", "key": "", "url": "https://physical-experience.org/", "externalId": "", "tenantId": "", "programId": "", "partnerId": "", "expiresAt": "1749886173170", "expiredUrl": "https://indelible-birdbath.net", "password": "4yMlkCXkK5ppW3u", "title": "", "description": "terribly gosh facilitate in", "image": "https://loremflickr.com/2596/954?lock=8527955982122580", "video": "https://loremflickr.com/3336/742?lock=2177640289466521", "ios": "", "android": "", "geo": {}, "tagId": "", "tags": [{"id": "", "name": "", "color": "red"}, {"id": "", "name": "", "color": "pink"}, {"id": "", "name": "", "color": "pink"}], "webhookIds": ["", "", ""], "comments": "up so pro pish clear-cut an mid aw disconnection which wetly typeface usable underneath putrefy ah aha", "shortLink": "https://knowledgeable-season.info", "qrCode": "https://nimble-individual.biz/", "utm_source": "", "utm_medium": "", "utm_campaign": "", "utm_term": "", "utm_content": "", "userId": "", "workspaceId": "", "clicks": 0, "lastClicked": "", "leads": 0, "sales": 0, "saleAmount": 0, "createdAt": "1737101896886", "updatedAt": "1738486980350", "projectId": ""}, "click": {"id": "", "url": "https://perfumed-marketplace.com/", "country": "Burundi", "city": "Stockton", "region": "", "continent": "Asia", "device": "Desktop", "browser": "Chrome", "os": "Symbian", "referer": "well-off-hygienic.org", "refererUrl": "https://ripe-ceramic.org", "ip": "eebc:cce9:cecf:ebeb:dfd9:15f2:a0cc:a3b1"}, "customer": {"id": "", "externalId": "", "name": "", "createdAt": "1721462841708"}, "sale": {"amount": 443316, "invoiceId": null, "paymentProcessor": "paddle"}, "saleAmount": 2634.98, "invoice_id": "", "payment_processor": "", "click_id": "", "link_id": "", "domain": "next-cricket.biz", "key": "", "url": "https://repentant-rust.name/", "continent": "Australia", "country": "Saint Helena", "city": "Luettgenfort", "device": "Mobile", "browser": "Safari", "os": "Chrome OS", "qr": 4390.32, "ip": "54.229.114.129"}] + application/json: [{"event": "sale", "eventId": "", "eventName": "", "link": {"id": "", "domain": "remorseful-concentration.biz", "key": "", "url": "https://primary-paintwork.com/", "externalId": "", "tenantId": "", "programId": "", "partnerId": "", "expiresAt": "1761281161208", "expiredUrl": "https://black-poetry.name/", "password": "COyVtOrvIw1vLIJ", "title": "", "description": "despite er boom however when uh-huh", "image": "https://picsum.photos/seed/T1tZJLp1EG/3827/3109", "video": "https://loremflickr.com/2420/1632?lock=7470650813503352", "ios": "", "android": "", "geo": {}, "tagId": "", "tags": [{"id": "", "name": "", "color": "green"}], "webhookIds": [], "comments": "tenement commonly softly boo massive sorrowful", "shortLink": "https://dense-custom.info/", "qrCode": "https://alive-lid.biz", "utm_source": "", "utm_medium": "", "utm_campaign": "", "utm_term": "", "utm_content": "", "userId": "", "workspaceId": "", "clicks": 0, "lastClicked": "", "leads": 0, "sales": 0, "saleAmount": 0, "createdAt": "1726693972751", "updatedAt": "1738567600750", "projectId": ""}, "click": {"id": "", "url": "https://utilized-quit.net/", "country": "Togo", "city": "Cormiermouth", "region": "", "continent": "North America", "device": "Mobile", "browser": "Chrome", "os": "Chrome OS", "referer": "gummy-cope.net", "refererUrl": "https://prickly-bourgeoisie.info/", "ip": "69bd:53cd:cebc:ac4b:d1e8:50e8:ee59:b0b3"}, "customer": {"id": "", "externalId": "", "name": "", "createdAt": "1737449517209"}, "sale": {"amount": 625809, "invoiceId": null, "paymentProcessor": "stripe"}, "saleAmount": 1401.42, "invoice_id": "", "payment_processor": "", "click_id": "", "link_id": "", "domain": "unruly-allegation.name", "key": "", "url": "https://fortunate-swim.info/", "continent": "Australia", "country": "Cook Islands", "city": "South Harryburgh", "device": "Mobile", "browser": "Safari", "os": "WebOS", "qr": 1523.03, "ip": "caf5:04dc:da9e:67cc:af3b:8caf:afbe:e39c"}, {"event": "sale", "eventId": "", "eventName": "", "link": {"id": "", "domain": "right-window.biz", "key": "", "url": "https://physical-experience.org/", "externalId": "", "tenantId": "", "programId": "", "partnerId": "", "expiresAt": "1749972514791", "expiredUrl": "https://indelible-birdbath.net", "password": "4yMlkCXkK5ppW3u", "title": "", "description": "terribly gosh facilitate in", "image": "https://loremflickr.com/2596/954?lock=8527955982122580", "video": "https://loremflickr.com/3336/742?lock=2177640289466521", "ios": "", "android": "", "geo": {}, "tagId": "", "tags": [{"id": "", "name": "", "color": "red"}, {"id": "", "name": "", "color": "pink"}, {"id": "", "name": "", "color": "pink"}], "webhookIds": ["", "", ""], "comments": "up so pro pish clear-cut an mid aw disconnection which wetly typeface usable underneath putrefy ah aha", "shortLink": "https://knowledgeable-season.info", "qrCode": "https://nimble-individual.biz/", "utm_source": "", "utm_medium": "", "utm_campaign": "", "utm_term": "", "utm_content": "", "userId": "", "workspaceId": "", "clicks": 0, "lastClicked": "", "leads": 0, "sales": 0, "saleAmount": 0, "createdAt": "1737188238485", "updatedAt": "1738573321949", "projectId": ""}, "click": {"id": "", "url": "https://perfumed-marketplace.com/", "country": "Burundi", "city": "Stockton", "region": "", "continent": "Asia", "device": "Desktop", "browser": "Chrome", "os": "Symbian", "referer": "well-off-hygienic.org", "refererUrl": "https://ripe-ceramic.org", "ip": "eebc:cce9:cecf:ebeb:dfd9:15f2:a0cc:a3b1"}, "customer": {"id": "", "externalId": "", "name": "", "createdAt": "1721549183307"}, "sale": {"amount": 443316, "invoiceId": null, "paymentProcessor": "paddle"}, "saleAmount": 2634.98, "invoice_id": "", "payment_processor": "", "click_id": "", "link_id": "", "domain": "next-cricket.biz", "key": "", "url": "https://repentant-rust.name/", "continent": "Australia", "country": "Saint Helena", "city": "Luettgenfort", "device": "Mobile", "browser": "Safari", "os": "Chrome OS", "qr": 4390.32, "ip": "54.229.114.129"}] "400": application/json: {"error": {"code": "bad_request", "message": "The requested resource was not found.", "doc_url": "https://dub.co/docs/api-reference/errors#bad-request"}} "401": @@ -1301,5 +1306,30 @@ examples: application/json: {"error": {"code": "rate_limit_exceeded", "message": "The requested resource was not found.", "doc_url": "https://dub.co/docs/api-reference/errors#rate-limit_exceeded"}} "500": application/json: {"error": {"code": "internal_server_error", "message": "The requested resource was not found.", "doc_url": "https://dub.co/docs/api-reference/errors#internal-server_error"}} + createPartnerLink: + speakeasy-default-create-partner-link: + requestBody: + application/json: {"programId": "", "url": "https://necessary-brief.name", "linkProps": {"externalId": "123456", "tagIds": ["clux0rgak00011..."]}} + responses: + "201": + application/json: {"id": "", "domain": "inferior-louse.org", "key": "", "url": "https://lighthearted-subexpression.net", "trackConversion": false, "externalId": "", "tenantId": "", "programId": "", "partnerId": "", "archived": false, "expiresAt": "1746975924499", "expiredUrl": "https://mammoth-resolve.com", "password": "oCRFmmigZdFo7_S", "proxy": false, "title": "", "description": "triumphantly zowie polite from yippee whether lazily hyena", "image": "https://loremflickr.com/3108/2731?lock=4230767515156707", "video": "https://loremflickr.com/3903/2681?lock=8712371193890444", "rewrite": false, "doIndex": false, "ios": "", "android": "", "geo": {}, "publicStats": false, "tagId": "", "tags": [{"id": "", "name": "", "color": "blue"}, {"id": "", "name": "", "color": "pink"}, {"id": "", "name": "", "color": "brown"}], "webhookIds": [""], "comments": "after boldly yieldingly from irritably nectarine nor vision loyally ew ick muddy rewrite till amount nor", "shortLink": "https://hard-to-find-railway.name", "qrCode": "https://vivacious-impostor.name/", "utm_source": "", "utm_medium": "", "utm_campaign": "", "utm_term": "", "utm_content": "", "userId": "", "workspaceId": "", "clicks": 0, "lastClicked": "", "leads": 0, "sales": 0, "saleAmount": 0, "createdAt": "1730894017035", "updatedAt": "1738583578575", "projectId": ""} + "400": + application/json: {"error": {"code": "bad_request", "message": "The requested resource was not found.", "doc_url": "https://dub.co/docs/api-reference/errors#bad-request"}} + "401": + application/json: {"error": {"code": "unauthorized", "message": "The requested resource was not found.", "doc_url": "https://dub.co/docs/api-reference/errors#unauthorized"}} + "403": + application/json: {"error": {"code": "forbidden", "message": "The requested resource was not found.", "doc_url": "https://dub.co/docs/api-reference/errors#forbidden"}} + "404": + application/json: {"error": {"code": "not_found", "message": "The requested resource was not found.", "doc_url": "https://dub.co/docs/api-reference/errors#not-found"}} + "409": + application/json: {"error": {"code": "conflict", "message": "The requested resource was not found.", "doc_url": "https://dub.co/docs/api-reference/errors#conflict"}} + "410": + application/json: {"error": {"code": "invite_expired", "message": "The requested resource was not found.", "doc_url": "https://dub.co/docs/api-reference/errors#invite-expired"}} + "422": + application/json: {"error": {"code": "unprocessable_entity", "message": "The requested resource was not found.", "doc_url": "https://dub.co/docs/api-reference/errors#unprocessable-entity"}} + "429": + application/json: {"error": {"code": "rate_limit_exceeded", "message": "The requested resource was not found.", "doc_url": "https://dub.co/docs/api-reference/errors#rate-limit_exceeded"}} + "500": + application/json: {"error": {"code": "internal_server_error", "message": "The requested resource was not found.", "doc_url": "https://dub.co/docs/api-reference/errors#internal-server_error"}} examplesVersion: 1.0.0 generatedTests: {} diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index db41834..ebebd35 100755 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -13,7 +13,7 @@ generation: oAuth2ClientCredentialsEnabled: true oAuth2PasswordEnabled: false python: - version: 0.17.8 + version: 0.17.9 additionalDependencies: dev: {} main: {} diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 11c4259..4d47d69 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -1,21 +1,21 @@ -speakeasyVersion: 1.481.1 +speakeasyVersion: 1.483.0 sources: dub: sourceNamespace: dub - sourceRevisionDigest: sha256:f45a09958121f0599f23910009268645adc04b050891c145b8ffc772d32210d7 - sourceBlobDigest: sha256:c2b6e2ed11dd5fe51a0412df7d8a815d3d3d281d73ab77d4e53425c6f2ca3f24 + sourceRevisionDigest: sha256:749625446520134b52b698c2638bd0ff721cdb14f2cfbc6e25e8155d778a5565 + sourceBlobDigest: sha256:341eb83836294446e9cf37fc5ed0667827a975000a58d5e4718aa24a80f44cd8 tags: - latest - - speakeasy-sdk-regen-1738369678 + - speakeasy-sdk-regen-1738628735 - 0.0.1 targets: my-first-target: source: dub sourceNamespace: dub - sourceRevisionDigest: sha256:f45a09958121f0599f23910009268645adc04b050891c145b8ffc772d32210d7 - sourceBlobDigest: sha256:c2b6e2ed11dd5fe51a0412df7d8a815d3d3d281d73ab77d4e53425c6f2ca3f24 + sourceRevisionDigest: sha256:749625446520134b52b698c2638bd0ff721cdb14f2cfbc6e25e8155d778a5565 + sourceBlobDigest: sha256:341eb83836294446e9cf37fc5ed0667827a975000a58d5e4718aa24a80f44cd8 codeSamplesNamespace: code-samples-python-my-first-target - codeSamplesRevisionDigest: sha256:83a6c9d90a663c786aa97079234fe46062871201297068f6ac03c27a8ff64b5b + codeSamplesRevisionDigest: sha256:ef04933274def66d60477666fabfe7fa7291e3d4b989c27b4e4192751b745d0b workflow: workflowVersion: 1.0.0 speakeasyVersion: latest diff --git a/README.md b/README.md index c211105..3fca83c 100644 --- a/README.md +++ b/README.md @@ -259,6 +259,7 @@ asyncio.run(main()) ### [partners](docs/sdks/partners/README.md) * [create](docs/sdks/partners/README.md#create) - Create a new partner +* [create_link](docs/sdks/partners/README.md#create_link) - Create a link for a partner ### [qr_codes](docs/sdks/qrcodes/README.md) diff --git a/RELEASES.md b/RELEASES.md index 91c6d6c..fcaa834 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -806,4 +806,14 @@ Based on: ### Generated - [python v0.17.8] . ### Releases -- [PyPI v0.17.8] https://pypi.org/project/dub/0.17.8 - . \ No newline at end of file +- [PyPI v0.17.8] https://pypi.org/project/dub/0.17.8 - . + +## 2025-02-04 00:25:21 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.483.0 (2.502.0) https://github.com/speakeasy-api/speakeasy +### Generated +- [python v0.17.9] . +### Releases +- [PyPI v0.17.9] https://pypi.org/project/dub/0.17.9 - . \ No newline at end of file diff --git a/codeSamples.yaml b/codeSamples.yaml index fbb0ddd..21a9738 100644 --- a/codeSamples.yaml +++ b/codeSamples.yaml @@ -486,6 +486,33 @@ actions: assert res is not None + # Handle response + print(res) + - target: $["paths"]["/partners/links"]["post"] + update: + x-codeSamples: + - lang: python + label: createPartnerLink + source: |- + from dub import Dub + + with Dub( + token="DUB_API_KEY", + ) as d_client: + + res = d_client.partners.create_link(request={ + "program_id": "", + "url": "https://necessary-brief.name", + "link_props": { + "external_id": "123456", + "tag_ids": [ + "clux0rgak00011...", + ], + }, + }) + + assert res is not None + # Handle response print(res) - target: $["paths"]["/qr"]["get"] diff --git a/docs/models/components/analyticstoplinks.md b/docs/models/components/analyticstoplinks.md index 7b9cb77..720744a 100644 --- a/docs/models/components/analyticstoplinks.md +++ b/docs/models/components/analyticstoplinks.md @@ -12,6 +12,7 @@ | `short_link` | *str* | :heavy_check_mark: | The short link URL | | `url` | *str* | :heavy_check_mark: | The destination URL of the short link | | `created_at` | *str* | :heavy_check_mark: | The creation timestamp of the short link | +| `comments` | *OptionalNullable[str]* | :heavy_minus_sign: | The comments of the short link | | `clicks` | *Optional[float]* | :heavy_minus_sign: | The number of clicks from this link | | `leads` | *Optional[float]* | :heavy_minus_sign: | The number of leads from this link | | `sales` | *Optional[float]* | :heavy_minus_sign: | The number of sales from this link | diff --git a/docs/models/operations/createpartnerlinklinkprops.md b/docs/models/operations/createpartnerlinklinkprops.md new file mode 100644 index 0000000..6d31137 --- /dev/null +++ b/docs/models/operations/createpartnerlinklinkprops.md @@ -0,0 +1,35 @@ +# CreatePartnerLinkLinkProps + +Additional properties that you can pass to the partner's short link. Will be used to override the default link properties for this partner. + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `external_id` | *OptionalNullable[str]* | :heavy_minus_sign: | The ID of the link in your database. If set, it can be used to identify the link in future API requests (must be prefixed with 'ext_' when passed as a query parameter). This key is unique across your workspace. | 123456 | +| `tenant_id` | *OptionalNullable[str]* | :heavy_minus_sign: | The ID of the tenant that created the link inside your system. If set, it can be used to fetch all links for a tenant. | | +| `partner_id` | *OptionalNullable[str]* | :heavy_minus_sign: | The ID of the partner the short link is associated with. | | +| `prefix` | *Optional[str]* | :heavy_minus_sign: | The prefix of the short link slug for randomly-generated keys (e.g. if prefix is `/c/`, generated keys will be in the `/c/:key` format). Will be ignored if `key` is provided. | | +| `archived` | *Optional[bool]* | :heavy_minus_sign: | Whether the short link is archived. Defaults to `false` if not provided. | | +| `tag_ids` | [Optional[operations.CreatePartnerLinkTagIds]](../../models/operations/createpartnerlinktagids.md) | :heavy_minus_sign: | The unique IDs of the tags assigned to the short link. | [
"clux0rgak00011..."
] | +| `tag_names` | [Optional[operations.CreatePartnerLinkTagNames]](../../models/operations/createpartnerlinktagnames.md) | :heavy_minus_sign: | The unique name of the tags assigned to the short link (case insensitive). | | +| `comments` | *OptionalNullable[str]* | :heavy_minus_sign: | The comments for the short link. | | +| `expires_at` | *OptionalNullable[str]* | :heavy_minus_sign: | The date and time when the short link will expire at. | | +| `expired_url` | *OptionalNullable[str]* | :heavy_minus_sign: | The URL to redirect to when the short link has expired. | | +| `password` | *OptionalNullable[str]* | :heavy_minus_sign: | The password required to access the destination URL of the short link. | | +| `proxy` | *Optional[bool]* | :heavy_minus_sign: | Whether the short link uses Custom Social Media Cards feature. Defaults to `false` if not provided. | | +| `title` | *OptionalNullable[str]* | :heavy_minus_sign: | The custom link preview title (og:title). Will be used for Custom Social Media Cards if `proxy` is true. Learn more: https://d.to/og | | +| `description` | *OptionalNullable[str]* | :heavy_minus_sign: | The custom link preview description (og:description). Will be used for Custom Social Media Cards if `proxy` is true. Learn more: https://d.to/og | | +| `image` | *OptionalNullable[str]* | :heavy_minus_sign: | The custom link preview image (og:image). Will be used for Custom Social Media Cards if `proxy` is true. Learn more: https://d.to/og | | +| `video` | *OptionalNullable[str]* | :heavy_minus_sign: | The custom link preview video (og:video). Will be used for Custom Social Media Cards if `proxy` is true. Learn more: https://d.to/og | | +| `rewrite` | *Optional[bool]* | :heavy_minus_sign: | Whether the short link uses link cloaking. Defaults to `false` if not provided. | | +| `ios` | *OptionalNullable[str]* | :heavy_minus_sign: | The iOS destination URL for the short link for iOS device targeting. | | +| `android` | *OptionalNullable[str]* | :heavy_minus_sign: | The Android destination URL for the short link for Android device targeting. | | +| `do_index` | *Optional[bool]* | :heavy_minus_sign: | Allow search engines to index your short link. Defaults to `false` if not provided. Learn more: https://d.to/noindex | | +| `utm_source` | *OptionalNullable[str]* | :heavy_minus_sign: | The UTM source of the short link. If set, this will populate or override the UTM source in the destination URL. | | +| `utm_medium` | *OptionalNullable[str]* | :heavy_minus_sign: | The UTM medium of the short link. If set, this will populate or override the UTM medium in the destination URL. | | +| `utm_campaign` | *OptionalNullable[str]* | :heavy_minus_sign: | The UTM campaign of the short link. If set, this will populate or override the UTM campaign in the destination URL. | | +| `utm_term` | *OptionalNullable[str]* | :heavy_minus_sign: | The UTM term of the short link. If set, this will populate or override the UTM term in the destination URL. | | +| `utm_content` | *OptionalNullable[str]* | :heavy_minus_sign: | The UTM content of the short link. If set, this will populate or override the UTM content in the destination URL. | | +| `ref` | *OptionalNullable[str]* | :heavy_minus_sign: | The referral tag of the short link. If set, this will populate or override the `ref` query parameter in the destination URL. | | \ No newline at end of file diff --git a/docs/models/operations/createpartnerlinkrequestbody.md b/docs/models/operations/createpartnerlinkrequestbody.md new file mode 100644 index 0000000..e55aa00 --- /dev/null +++ b/docs/models/operations/createpartnerlinkrequestbody.md @@ -0,0 +1,13 @@ +# CreatePartnerLinkRequestBody + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| `program_id` | *str* | :heavy_check_mark: | The ID of the program that the partner is enrolled in. | +| `url` | *str* | :heavy_check_mark: | The URL to shorten. Will throw an error if the domain doesn't match the program's default URL domain. | +| `partner_id` | *OptionalNullable[str]* | :heavy_minus_sign: | The ID of the partner to create a link for. Will take precedence over `tenantId` if provided. | +| `tenant_id` | *OptionalNullable[str]* | :heavy_minus_sign: | The ID of the partner in your system. If both `partnerId` and `tenantId` are not provided, an error will be thrown. | +| `key` | *Optional[str]* | :heavy_minus_sign: | The short link slug. If not provided, a random 7-character slug will be generated. | +| `link_props` | [Optional[operations.CreatePartnerLinkLinkProps]](../../models/operations/createpartnerlinklinkprops.md) | :heavy_minus_sign: | Additional properties that you can pass to the partner's short link. Will be used to override the default link properties for this partner. | \ No newline at end of file diff --git a/docs/models/operations/createpartnerlinktagids.md b/docs/models/operations/createpartnerlinktagids.md new file mode 100644 index 0000000..bcfa56c --- /dev/null +++ b/docs/models/operations/createpartnerlinktagids.md @@ -0,0 +1,19 @@ +# CreatePartnerLinkTagIds + +The unique IDs of the tags assigned to the short link. + + +## Supported Types + +### `str` + +```python +value: str = /* values here */ +``` + +### `List[str]` + +```python +value: List[str] = /* values here */ +``` + diff --git a/docs/models/operations/createpartnerlinktagnames.md b/docs/models/operations/createpartnerlinktagnames.md new file mode 100644 index 0000000..54db47c --- /dev/null +++ b/docs/models/operations/createpartnerlinktagnames.md @@ -0,0 +1,19 @@ +# CreatePartnerLinkTagNames + +The unique name of the tags assigned to the short link (case insensitive). + + +## Supported Types + +### `str` + +```python +value: str = /* values here */ +``` + +### `List[str]` + +```python +value: List[str] = /* values here */ +``` + diff --git a/docs/sdks/partners/README.md b/docs/sdks/partners/README.md index 67aac28..fd6c8da 100644 --- a/docs/sdks/partners/README.md +++ b/docs/sdks/partners/README.md @@ -6,6 +6,7 @@ ### Available Operations * [create](#create) - Create a new partner +* [create_link](#create_link) - Create a link for a partner ## create @@ -53,6 +54,63 @@ with Dub( ### Errors +| Error Type | Status Code | Content Type | +| -------------------------- | -------------------------- | -------------------------- | +| errors.BadRequest | 400 | application/json | +| errors.Unauthorized | 401 | application/json | +| errors.Forbidden | 403 | application/json | +| errors.NotFound | 404 | application/json | +| errors.Conflict | 409 | application/json | +| errors.InviteExpired | 410 | application/json | +| errors.UnprocessableEntity | 422 | application/json | +| errors.RateLimitExceeded | 429 | application/json | +| errors.InternalServerError | 500 | application/json | +| errors.SDKError | 4XX, 5XX | \*/\* | + +## create_link + +Create a new link for a partner that is enrolled in your program + +### Example Usage + +```python +from dub import Dub + +with Dub( + token="DUB_API_KEY", +) as d_client: + + res = d_client.partners.create_link(request={ + "program_id": "", + "url": "https://necessary-brief.name", + "link_props": { + "external_id": "123456", + "tag_ids": [ + "clux0rgak00011...", + ], + }, + }) + + assert res is not None + + # Handle response + print(res) + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | +| `request` | [operations.CreatePartnerLinkRequestBody](../../models/operations/createpartnerlinkrequestbody.md) | :heavy_check_mark: | The request object to use for the request. | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Response + +**[components.LinkSchema](../../models/components/linkschema.md)** + +### Errors + | Error Type | Status Code | Content Type | | -------------------------- | -------------------------- | -------------------------- | | errors.BadRequest | 400 | application/json | diff --git a/pyproject.toml b/pyproject.toml index d47951b..d8fe5b8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "dub" -version = "0.17.8" +version = "0.17.9" description = "Python Client SDK Generated by Speakeasy" authors = [{ name = "Speakeasy" },] readme = "README-PYPI.md" diff --git a/src/dub/_version.py b/src/dub/_version.py index fdda442..7bc23eb 100644 --- a/src/dub/_version.py +++ b/src/dub/_version.py @@ -3,10 +3,10 @@ import importlib.metadata __title__: str = "dub" -__version__: str = "0.17.8" +__version__: str = "0.17.9" __openapi_doc_version__: str = "0.0.1" -__gen_version__: str = "2.500.5" -__user_agent__: str = "speakeasy-sdk/python 0.17.8 2.500.5 0.0.1 dub" +__gen_version__: str = "2.502.0" +__user_agent__: str = "speakeasy-sdk/python 0.17.9 2.502.0 0.0.1 dub" try: if __package__ is not None: diff --git a/src/dub/models/components/analyticstoplinks.py b/src/dub/models/components/analyticstoplinks.py index 02cd156..ff809c9 100644 --- a/src/dub/models/components/analyticstoplinks.py +++ b/src/dub/models/components/analyticstoplinks.py @@ -1,8 +1,9 @@ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" from __future__ import annotations -from dub.types import BaseModel +from dub.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL import pydantic +from pydantic import model_serializer from typing import Optional from typing_extensions import Annotated, NotRequired, TypedDict @@ -22,6 +23,8 @@ class AnalyticsTopLinksTypedDict(TypedDict): r"""The destination URL of the short link""" created_at: str r"""The creation timestamp of the short link""" + comments: NotRequired[Nullable[str]] + r"""The comments of the short link""" clicks: NotRequired[float] r"""The number of clicks from this link""" leads: NotRequired[float] @@ -59,6 +62,9 @@ class AnalyticsTopLinks(BaseModel): created_at: Annotated[str, pydantic.Field(alias="createdAt")] r"""The creation timestamp of the short link""" + comments: OptionalNullable[str] = UNSET + r"""The comments of the short link""" + clicks: Optional[float] = 0 r"""The number of clicks from this link""" @@ -70,3 +76,33 @@ class AnalyticsTopLinks(BaseModel): sale_amount: Annotated[Optional[float], pydantic.Field(alias="saleAmount")] = 0 r"""The total amount of sales from this link, in cents""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = ["comments", "clicks", "leads", "sales", "saleAmount"] + nullable_fields = ["comments"] + null_default_fields = [] + + serialized = handler(self) + + m = {} + + for n, f in self.model_fields.items(): + k = f.alias or n + val = serialized.get(k) + serialized.pop(k, None) + + optional_nullable = k in optional_fields and k in nullable_fields + is_set = ( + self.__pydantic_fields_set__.intersection({n}) + or k in null_default_fields + ) # pylint: disable=no-member + + if val is not None and val != UNSET_SENTINEL: + m[k] = val + elif val != UNSET_SENTINEL and ( + not k in optional_fields or (optional_nullable and is_set) + ): + m[k] = val + + return m diff --git a/src/dub/models/operations/__init__.py b/src/dub/models/operations/__init__.py index eb585b0..cd71b53 100644 --- a/src/dub/models/operations/__init__.py +++ b/src/dub/models/operations/__init__.py @@ -75,6 +75,16 @@ LinksTypedDict, Status, ) +from .createpartnerlink import ( + CreatePartnerLinkLinkProps, + CreatePartnerLinkLinkPropsTypedDict, + CreatePartnerLinkRequestBody, + CreatePartnerLinkRequestBodyTypedDict, + CreatePartnerLinkTagIds, + CreatePartnerLinkTagIdsTypedDict, + CreatePartnerLinkTagNames, + CreatePartnerLinkTagNamesTypedDict, +) from .createtag import Color, CreateTagRequestBody, CreateTagRequestBodyTypedDict from .deletecustomer import ( DeleteCustomerRequest, @@ -321,6 +331,14 @@ "CreatePartnerDiscount", "CreatePartnerDiscountTypedDict", "CreatePartnerInterval", + "CreatePartnerLinkLinkProps", + "CreatePartnerLinkLinkPropsTypedDict", + "CreatePartnerLinkRequestBody", + "CreatePartnerLinkRequestBodyTypedDict", + "CreatePartnerLinkTagIds", + "CreatePartnerLinkTagIdsTypedDict", + "CreatePartnerLinkTagNames", + "CreatePartnerLinkTagNamesTypedDict", "CreatePartnerRequestBody", "CreatePartnerRequestBodyTypedDict", "CreatePartnerResponseBody", diff --git a/src/dub/models/operations/createpartnerlink.py b/src/dub/models/operations/createpartnerlink.py new file mode 100644 index 0000000..fddf56d --- /dev/null +++ b/src/dub/models/operations/createpartnerlink.py @@ -0,0 +1,333 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from dub.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL +import pydantic +from pydantic import model_serializer +from typing import List, Optional, Union +from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict + + +CreatePartnerLinkTagIdsTypedDict = TypeAliasType( + "CreatePartnerLinkTagIdsTypedDict", Union[str, List[str]] +) +r"""The unique IDs of the tags assigned to the short link.""" + + +CreatePartnerLinkTagIds = TypeAliasType( + "CreatePartnerLinkTagIds", Union[str, List[str]] +) +r"""The unique IDs of the tags assigned to the short link.""" + + +CreatePartnerLinkTagNamesTypedDict = TypeAliasType( + "CreatePartnerLinkTagNamesTypedDict", Union[str, List[str]] +) +r"""The unique name of the tags assigned to the short link (case insensitive).""" + + +CreatePartnerLinkTagNames = TypeAliasType( + "CreatePartnerLinkTagNames", Union[str, List[str]] +) +r"""The unique name of the tags assigned to the short link (case insensitive).""" + + +class CreatePartnerLinkLinkPropsTypedDict(TypedDict): + r"""Additional properties that you can pass to the partner's short link. Will be used to override the default link properties for this partner.""" + + external_id: NotRequired[Nullable[str]] + r"""The ID of the link in your database. If set, it can be used to identify the link in future API requests (must be prefixed with 'ext_' when passed as a query parameter). This key is unique across your workspace.""" + tenant_id: NotRequired[Nullable[str]] + r"""The ID of the tenant that created the link inside your system. If set, it can be used to fetch all links for a tenant.""" + partner_id: NotRequired[Nullable[str]] + r"""The ID of the partner the short link is associated with.""" + prefix: NotRequired[str] + r"""The prefix of the short link slug for randomly-generated keys (e.g. if prefix is `/c/`, generated keys will be in the `/c/:key` format). Will be ignored if `key` is provided.""" + archived: NotRequired[bool] + r"""Whether the short link is archived. Defaults to `false` if not provided.""" + tag_ids: NotRequired[CreatePartnerLinkTagIdsTypedDict] + r"""The unique IDs of the tags assigned to the short link.""" + tag_names: NotRequired[CreatePartnerLinkTagNamesTypedDict] + r"""The unique name of the tags assigned to the short link (case insensitive).""" + comments: NotRequired[Nullable[str]] + r"""The comments for the short link.""" + expires_at: NotRequired[Nullable[str]] + r"""The date and time when the short link will expire at.""" + expired_url: NotRequired[Nullable[str]] + r"""The URL to redirect to when the short link has expired.""" + password: NotRequired[Nullable[str]] + r"""The password required to access the destination URL of the short link.""" + proxy: NotRequired[bool] + r"""Whether the short link uses Custom Social Media Cards feature. Defaults to `false` if not provided.""" + title: NotRequired[Nullable[str]] + r"""The custom link preview title (og:title). Will be used for Custom Social Media Cards if `proxy` is true. Learn more: https://d.to/og""" + description: NotRequired[Nullable[str]] + r"""The custom link preview description (og:description). Will be used for Custom Social Media Cards if `proxy` is true. Learn more: https://d.to/og""" + image: NotRequired[Nullable[str]] + r"""The custom link preview image (og:image). Will be used for Custom Social Media Cards if `proxy` is true. Learn more: https://d.to/og""" + video: NotRequired[Nullable[str]] + r"""The custom link preview video (og:video). Will be used for Custom Social Media Cards if `proxy` is true. Learn more: https://d.to/og""" + rewrite: NotRequired[bool] + r"""Whether the short link uses link cloaking. Defaults to `false` if not provided.""" + ios: NotRequired[Nullable[str]] + r"""The iOS destination URL for the short link for iOS device targeting.""" + android: NotRequired[Nullable[str]] + r"""The Android destination URL for the short link for Android device targeting.""" + do_index: NotRequired[bool] + r"""Allow search engines to index your short link. Defaults to `false` if not provided. Learn more: https://d.to/noindex""" + utm_source: NotRequired[Nullable[str]] + r"""The UTM source of the short link. If set, this will populate or override the UTM source in the destination URL.""" + utm_medium: NotRequired[Nullable[str]] + r"""The UTM medium of the short link. If set, this will populate or override the UTM medium in the destination URL.""" + utm_campaign: NotRequired[Nullable[str]] + r"""The UTM campaign of the short link. If set, this will populate or override the UTM campaign in the destination URL.""" + utm_term: NotRequired[Nullable[str]] + r"""The UTM term of the short link. If set, this will populate or override the UTM term in the destination URL.""" + utm_content: NotRequired[Nullable[str]] + r"""The UTM content of the short link. If set, this will populate or override the UTM content in the destination URL.""" + ref: NotRequired[Nullable[str]] + r"""The referral tag of the short link. If set, this will populate or override the `ref` query parameter in the destination URL.""" + + +class CreatePartnerLinkLinkProps(BaseModel): + r"""Additional properties that you can pass to the partner's short link. Will be used to override the default link properties for this partner.""" + + external_id: Annotated[ + OptionalNullable[str], pydantic.Field(alias="externalId") + ] = UNSET + r"""The ID of the link in your database. If set, it can be used to identify the link in future API requests (must be prefixed with 'ext_' when passed as a query parameter). This key is unique across your workspace.""" + + tenant_id: Annotated[OptionalNullable[str], pydantic.Field(alias="tenantId")] = ( + UNSET + ) + r"""The ID of the tenant that created the link inside your system. If set, it can be used to fetch all links for a tenant.""" + + partner_id: Annotated[OptionalNullable[str], pydantic.Field(alias="partnerId")] = ( + UNSET + ) + r"""The ID of the partner the short link is associated with.""" + + prefix: Optional[str] = None + r"""The prefix of the short link slug for randomly-generated keys (e.g. if prefix is `/c/`, generated keys will be in the `/c/:key` format). Will be ignored if `key` is provided.""" + + archived: Optional[bool] = None + r"""Whether the short link is archived. Defaults to `false` if not provided.""" + + tag_ids: Annotated[ + Optional[CreatePartnerLinkTagIds], pydantic.Field(alias="tagIds") + ] = None + r"""The unique IDs of the tags assigned to the short link.""" + + tag_names: Annotated[ + Optional[CreatePartnerLinkTagNames], pydantic.Field(alias="tagNames") + ] = None + r"""The unique name of the tags assigned to the short link (case insensitive).""" + + comments: OptionalNullable[str] = UNSET + r"""The comments for the short link.""" + + expires_at: Annotated[OptionalNullable[str], pydantic.Field(alias="expiresAt")] = ( + UNSET + ) + r"""The date and time when the short link will expire at.""" + + expired_url: Annotated[ + OptionalNullable[str], pydantic.Field(alias="expiredUrl") + ] = UNSET + r"""The URL to redirect to when the short link has expired.""" + + password: OptionalNullable[str] = UNSET + r"""The password required to access the destination URL of the short link.""" + + proxy: Optional[bool] = None + r"""Whether the short link uses Custom Social Media Cards feature. Defaults to `false` if not provided.""" + + title: OptionalNullable[str] = UNSET + r"""The custom link preview title (og:title). Will be used for Custom Social Media Cards if `proxy` is true. Learn more: https://d.to/og""" + + description: OptionalNullable[str] = UNSET + r"""The custom link preview description (og:description). Will be used for Custom Social Media Cards if `proxy` is true. Learn more: https://d.to/og""" + + image: OptionalNullable[str] = UNSET + r"""The custom link preview image (og:image). Will be used for Custom Social Media Cards if `proxy` is true. Learn more: https://d.to/og""" + + video: OptionalNullable[str] = UNSET + r"""The custom link preview video (og:video). Will be used for Custom Social Media Cards if `proxy` is true. Learn more: https://d.to/og""" + + rewrite: Optional[bool] = None + r"""Whether the short link uses link cloaking. Defaults to `false` if not provided.""" + + ios: OptionalNullable[str] = UNSET + r"""The iOS destination URL for the short link for iOS device targeting.""" + + android: OptionalNullable[str] = UNSET + r"""The Android destination URL for the short link for Android device targeting.""" + + do_index: Annotated[Optional[bool], pydantic.Field(alias="doIndex")] = None + r"""Allow search engines to index your short link. Defaults to `false` if not provided. Learn more: https://d.to/noindex""" + + utm_source: OptionalNullable[str] = UNSET + r"""The UTM source of the short link. If set, this will populate or override the UTM source in the destination URL.""" + + utm_medium: OptionalNullable[str] = UNSET + r"""The UTM medium of the short link. If set, this will populate or override the UTM medium in the destination URL.""" + + utm_campaign: OptionalNullable[str] = UNSET + r"""The UTM campaign of the short link. If set, this will populate or override the UTM campaign in the destination URL.""" + + utm_term: OptionalNullable[str] = UNSET + r"""The UTM term of the short link. If set, this will populate or override the UTM term in the destination URL.""" + + utm_content: OptionalNullable[str] = UNSET + r"""The UTM content of the short link. If set, this will populate or override the UTM content in the destination URL.""" + + ref: OptionalNullable[str] = UNSET + r"""The referral tag of the short link. If set, this will populate or override the `ref` query parameter in the destination URL.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = [ + "externalId", + "tenantId", + "partnerId", + "prefix", + "archived", + "tagIds", + "tagNames", + "comments", + "expiresAt", + "expiredUrl", + "password", + "proxy", + "title", + "description", + "image", + "video", + "rewrite", + "ios", + "android", + "doIndex", + "utm_source", + "utm_medium", + "utm_campaign", + "utm_term", + "utm_content", + "ref", + ] + nullable_fields = [ + "externalId", + "tenantId", + "partnerId", + "comments", + "expiresAt", + "expiredUrl", + "password", + "title", + "description", + "image", + "video", + "ios", + "android", + "utm_source", + "utm_medium", + "utm_campaign", + "utm_term", + "utm_content", + "ref", + ] + null_default_fields = [] + + serialized = handler(self) + + m = {} + + for n, f in self.model_fields.items(): + k = f.alias or n + val = serialized.get(k) + serialized.pop(k, None) + + optional_nullable = k in optional_fields and k in nullable_fields + is_set = ( + self.__pydantic_fields_set__.intersection({n}) + or k in null_default_fields + ) # pylint: disable=no-member + + if val is not None and val != UNSET_SENTINEL: + m[k] = val + elif val != UNSET_SENTINEL and ( + not k in optional_fields or (optional_nullable and is_set) + ): + m[k] = val + + return m + + +class CreatePartnerLinkRequestBodyTypedDict(TypedDict): + program_id: str + r"""The ID of the program that the partner is enrolled in.""" + url: str + r"""The URL to shorten. Will throw an error if the domain doesn't match the program's default URL domain.""" + partner_id: NotRequired[Nullable[str]] + r"""The ID of the partner to create a link for. Will take precedence over `tenantId` if provided.""" + tenant_id: NotRequired[Nullable[str]] + r"""The ID of the partner in your system. If both `partnerId` and `tenantId` are not provided, an error will be thrown.""" + key: NotRequired[str] + r"""The short link slug. If not provided, a random 7-character slug will be generated.""" + link_props: NotRequired[CreatePartnerLinkLinkPropsTypedDict] + r"""Additional properties that you can pass to the partner's short link. Will be used to override the default link properties for this partner.""" + + +class CreatePartnerLinkRequestBody(BaseModel): + program_id: Annotated[str, pydantic.Field(alias="programId")] + r"""The ID of the program that the partner is enrolled in.""" + + url: str + r"""The URL to shorten. Will throw an error if the domain doesn't match the program's default URL domain.""" + + partner_id: Annotated[OptionalNullable[str], pydantic.Field(alias="partnerId")] = ( + UNSET + ) + r"""The ID of the partner to create a link for. Will take precedence over `tenantId` if provided.""" + + tenant_id: Annotated[OptionalNullable[str], pydantic.Field(alias="tenantId")] = ( + UNSET + ) + r"""The ID of the partner in your system. If both `partnerId` and `tenantId` are not provided, an error will be thrown.""" + + key: Optional[str] = None + r"""The short link slug. If not provided, a random 7-character slug will be generated.""" + + link_props: Annotated[ + Optional[CreatePartnerLinkLinkProps], pydantic.Field(alias="linkProps") + ] = None + r"""Additional properties that you can pass to the partner's short link. Will be used to override the default link properties for this partner.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = ["partnerId", "tenantId", "key", "linkProps"] + nullable_fields = ["partnerId", "tenantId"] + null_default_fields = [] + + serialized = handler(self) + + m = {} + + for n, f in self.model_fields.items(): + k = f.alias or n + val = serialized.get(k) + serialized.pop(k, None) + + optional_nullable = k in optional_fields and k in nullable_fields + is_set = ( + self.__pydantic_fields_set__.intersection({n}) + or k in null_default_fields + ) # pylint: disable=no-member + + if val is not None and val != UNSET_SENTINEL: + m[k] = val + elif val != UNSET_SENTINEL and ( + not k in optional_fields or (optional_nullable and is_set) + ): + m[k] = val + + return m diff --git a/src/dub/partners.py b/src/dub/partners.py index 4b96f42..5f1bade 100644 --- a/src/dub/partners.py +++ b/src/dub/partners.py @@ -3,7 +3,7 @@ from .basesdk import BaseSDK from dub import utils from dub._hooks import HookContext -from dub.models import errors, operations +from dub.models import components, errors, operations from dub.types import BaseModel, OptionalNullable, UNSET from typing import Any, Mapping, Optional, Union, cast @@ -312,3 +312,303 @@ async def create_async( http_res_text, http_res, ) + + def create_link( + self, + *, + request: Optional[ + Union[ + operations.CreatePartnerLinkRequestBody, + operations.CreatePartnerLinkRequestBodyTypedDict, + ] + ] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> Optional[components.LinkSchema]: + r"""Create a link for a partner + + Create a new link for a partner that is enrolled in your program + + :param request: The request object to send. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + if not isinstance(request, BaseModel): + request = utils.unmarshal( + request, Optional[operations.CreatePartnerLinkRequestBody] + ) + request = cast(Optional[operations.CreatePartnerLinkRequestBody], request) + + req = self._build_request( + method="POST", + path="/partners/links", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request, + False, + True, + "json", + Optional[operations.CreatePartnerLinkRequestBody], + ), + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = self.do_request( + hook_ctx=HookContext( + operation_id="createPartnerLink", + oauth2_scopes=[], + security_source=self.sdk_configuration.security, + ), + request=req, + error_status_codes=[ + "400", + "401", + "403", + "404", + "409", + "410", + "422", + "429", + "4XX", + "500", + "5XX", + ], + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "201", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[components.LinkSchema]) + if utils.match_response(http_res, "400", "application/json"): + response_data = utils.unmarshal_json(http_res.text, errors.BadRequestData) + raise errors.BadRequest(data=response_data) + if utils.match_response(http_res, "401", "application/json"): + response_data = utils.unmarshal_json(http_res.text, errors.UnauthorizedData) + raise errors.Unauthorized(data=response_data) + if utils.match_response(http_res, "403", "application/json"): + response_data = utils.unmarshal_json(http_res.text, errors.ForbiddenData) + raise errors.Forbidden(data=response_data) + if utils.match_response(http_res, "404", "application/json"): + response_data = utils.unmarshal_json(http_res.text, errors.NotFoundData) + raise errors.NotFound(data=response_data) + if utils.match_response(http_res, "409", "application/json"): + response_data = utils.unmarshal_json(http_res.text, errors.ConflictData) + raise errors.Conflict(data=response_data) + if utils.match_response(http_res, "410", "application/json"): + response_data = utils.unmarshal_json( + http_res.text, errors.InviteExpiredData + ) + raise errors.InviteExpired(data=response_data) + if utils.match_response(http_res, "422", "application/json"): + response_data = utils.unmarshal_json( + http_res.text, errors.UnprocessableEntityData + ) + raise errors.UnprocessableEntity(data=response_data) + if utils.match_response(http_res, "429", "application/json"): + response_data = utils.unmarshal_json( + http_res.text, errors.RateLimitExceededData + ) + raise errors.RateLimitExceeded(data=response_data) + if utils.match_response(http_res, "500", "application/json"): + response_data = utils.unmarshal_json( + http_res.text, errors.InternalServerErrorData + ) + raise errors.InternalServerError(data=response_data) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.SDKError( + "API error occurred", http_res.status_code, http_res_text, http_res + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.SDKError( + "API error occurred", http_res.status_code, http_res_text, http_res + ) + + content_type = http_res.headers.get("Content-Type") + http_res_text = utils.stream_to_text(http_res) + raise errors.SDKError( + f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", + http_res.status_code, + http_res_text, + http_res, + ) + + async def create_link_async( + self, + *, + request: Optional[ + Union[ + operations.CreatePartnerLinkRequestBody, + operations.CreatePartnerLinkRequestBodyTypedDict, + ] + ] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> Optional[components.LinkSchema]: + r"""Create a link for a partner + + Create a new link for a partner that is enrolled in your program + + :param request: The request object to send. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + + if not isinstance(request, BaseModel): + request = utils.unmarshal( + request, Optional[operations.CreatePartnerLinkRequestBody] + ) + request = cast(Optional[operations.CreatePartnerLinkRequestBody], request) + + req = self._build_request_async( + method="POST", + path="/partners/links", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=False, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request, + False, + True, + "json", + Optional[operations.CreatePartnerLinkRequestBody], + ), + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = await self.do_request_async( + hook_ctx=HookContext( + operation_id="createPartnerLink", + oauth2_scopes=[], + security_source=self.sdk_configuration.security, + ), + request=req, + error_status_codes=[ + "400", + "401", + "403", + "404", + "409", + "410", + "422", + "429", + "4XX", + "500", + "5XX", + ], + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "201", "application/json"): + return utils.unmarshal_json(http_res.text, Optional[components.LinkSchema]) + if utils.match_response(http_res, "400", "application/json"): + response_data = utils.unmarshal_json(http_res.text, errors.BadRequestData) + raise errors.BadRequest(data=response_data) + if utils.match_response(http_res, "401", "application/json"): + response_data = utils.unmarshal_json(http_res.text, errors.UnauthorizedData) + raise errors.Unauthorized(data=response_data) + if utils.match_response(http_res, "403", "application/json"): + response_data = utils.unmarshal_json(http_res.text, errors.ForbiddenData) + raise errors.Forbidden(data=response_data) + if utils.match_response(http_res, "404", "application/json"): + response_data = utils.unmarshal_json(http_res.text, errors.NotFoundData) + raise errors.NotFound(data=response_data) + if utils.match_response(http_res, "409", "application/json"): + response_data = utils.unmarshal_json(http_res.text, errors.ConflictData) + raise errors.Conflict(data=response_data) + if utils.match_response(http_res, "410", "application/json"): + response_data = utils.unmarshal_json( + http_res.text, errors.InviteExpiredData + ) + raise errors.InviteExpired(data=response_data) + if utils.match_response(http_res, "422", "application/json"): + response_data = utils.unmarshal_json( + http_res.text, errors.UnprocessableEntityData + ) + raise errors.UnprocessableEntity(data=response_data) + if utils.match_response(http_res, "429", "application/json"): + response_data = utils.unmarshal_json( + http_res.text, errors.RateLimitExceededData + ) + raise errors.RateLimitExceeded(data=response_data) + if utils.match_response(http_res, "500", "application/json"): + response_data = utils.unmarshal_json( + http_res.text, errors.InternalServerErrorData + ) + raise errors.InternalServerError(data=response_data) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.SDKError( + "API error occurred", http_res.status_code, http_res_text, http_res + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.SDKError( + "API error occurred", http_res.status_code, http_res_text, http_res + ) + + content_type = http_res.headers.get("Content-Type") + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.SDKError( + f"Unexpected response received (code: {http_res.status_code}, type: {content_type})", + http_res.status_code, + http_res_text, + http_res, + )