Skip to content

Source Snapchat Marketing: update authenticator package #38574

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ data:
connectorSubtype: api
connectorType: source
definitionId: 200330b2-ea62-4d11-ac6d-cfe3e3f8ab2b
dockerImageTag: 0.6.1
dockerImageTag: 0.6.2
dockerRepository: airbyte/source-snapchat-marketing
githubIssueLabel: source-snapchat-marketing
icon: snapchat.svg
Expand Down
472 changes: 382 additions & 90 deletions airbyte-integrations/connectors/source-snapchat-marketing/poetry.lock

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
version = "0.6.1"
version = "0.6.2"
name = "source-snapchat-marketing"
description = "Source implementation for Snapchat Marketing."
authors = [ "Airbyte <[email protected]>",]
Expand All @@ -17,7 +17,7 @@ include = "source_snapchat_marketing"

[tool.poetry.dependencies]
python = "^3.9,<3.12"
airbyte-cdk = "0.80.0"
airbyte-cdk = "0.90.0"

[tool.poetry.scripts]
source-snapchat-marketing = "source_snapchat_marketing.run:run"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
from airbyte_cdk.sources.streams import Stream
from airbyte_cdk.sources.streams.core import IncrementalMixin, package_name_from_class
from airbyte_cdk.sources.streams.http import HttpStream
from airbyte_cdk.sources.streams.http.auth import Oauth2Authenticator
from airbyte_cdk.sources.streams.http.exceptions import DefaultBackoffException
from airbyte_cdk.sources.streams.http.requests_native_auth import Oauth2Authenticator
from airbyte_cdk.sources.utils.schema_helpers import ResourceSchemaLoader

# https://marketingapi.snapchat.com/docs/#core-metrics
Expand Down Expand Up @@ -250,7 +249,7 @@ def stream_slices(self, **kwargs) -> Iterable[Optional[Mapping[str, Any]]]:
self.max_state = self.initial_state

parent_stream = self.parent(
authenticator=self.authenticator,
authenticator=self._session.auth,
start_date=self.start_date,
end_date=self.end_date,
action_report_time=self.action_report_time,
Expand Down Expand Up @@ -379,7 +378,7 @@ def stream_slices(self, **kwargs) -> Iterable[Optional[Mapping[str, Any]]]:
"""Each stream slice represents each entity id from parent stream"""

parent_stream = self.parent(
authenticator=self.authenticator,
authenticator=self._session.auth,
start_date=self.start_date,
end_date=self.end_date,
action_report_time=self.action_report_time,
Expand Down Expand Up @@ -757,44 +756,13 @@ class CampaignsStatsLifetime(Lifetime, Stats):
parent = Campaigns


class SnapchatOauth2Authenticator(Oauth2Authenticator):
@backoff.on_exception(
backoff.expo,
DefaultBackoffException,
on_backoff=lambda details: logger.info(
f"Caught retryable error after {details['tries']} tries. Waiting {details['wait']} seconds then retrying..."
),
max_time=300,
)
def refresh_access_token(self) -> Tuple[str, int]:
"""
returns a tuple of (access_token, token_lifespan_in_seconds)
"""
try:
response = requests.request(
method="POST",
url=self.token_refresh_endpoint,
data=self.get_refresh_request_body(),
headers=self.get_refresh_access_token_headers(),
)
response.raise_for_status()
response_json = response.json()
return response_json["access_token"], response_json["expires_in"]
except requests.exceptions.RequestException as e:
if e.response.status_code == 429 or e.response.status_code >= 500:
raise DefaultBackoffException(request=e.response.request, response=e.response)
raise
except Exception as e:
raise Exception(f"Error while refreshing access token: {e}") from e


# Source
class SourceSnapchatMarketing(AbstractSource):
"""Source Snapchat Marketing helps to retrieve the different Ad data from Snapchat business account"""

def check_connection(self, logger, config) -> Tuple[bool, any]:
try:
auth = SnapchatOauth2Authenticator(
auth = Oauth2Authenticator(
token_refresh_endpoint="https://accounts.snapchat.com/login/oauth2/access_token",
client_id=config["client_id"],
client_secret=config["client_secret"],
Expand All @@ -820,7 +788,7 @@ def streams(self, config: Mapping[str, Any]) -> List[Stream]:
# 2. when timezone is not specified, default account's timezone will be used automatically
default_end_date = pendulum.now().subtract(days=DELAYED_DAYS).to_date_string()
kwargs = {
"authenticator": SnapchatOauth2Authenticator(
"authenticator": Oauth2Authenticator(
token_refresh_endpoint="https://accounts.snapchat.com/login/oauth2/access_token",
client_id=config["client_id"],
client_secret=config["client_secret"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
Ads,
AdsStatsDaily,
AdsStatsLifetime,
Oauth2Authenticator,
Organizations,
SnapchatOauth2Authenticator,
SourceSnapchatMarketing,
)

Expand Down Expand Up @@ -381,7 +381,7 @@ def test_retry_get_access_token(requests_mock):
"https://accounts.snapchat.com/login/oauth2/access_token",
[{"status_code": 429}, {"status_code": 429}, {"status_code": 200, "json": {"access_token": "token", "expires_in": 3600}}],
)
auth = SnapchatOauth2Authenticator(
auth = Oauth2Authenticator(
token_refresh_endpoint="https://accounts.snapchat.com/login/oauth2/access_token",
client_id="client_id",
client_secret="client_secret",
Expand Down
1 change: 1 addition & 0 deletions docs/integrations/sources/snapchat-marketing.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ Snapchat Marketing API has limitations to 1000 items per page.

| Version | Date | Pull Request | Subject |
| :------ | :--------- | :------------------------------------------------------- | :----------------------------------------------------------------------------- |
| 0.6.2 | 2024-15-22 | [38574](https://github.com/airbytehq/airbyte/pull/38574) | Update authenticator package |
| 0.6.1 | 2024-04-24 | [36662](https://github.com/airbytehq/airbyte/pull/36662) | Schema descriptions |
| 0.6.0 | 2024-04-10 | [30586](https://github.com/airbytehq/airbyte/pull/30586) | Add `attribution_windows`,`action_report_time` as optional configurable params |
| 0.5.0 | 2024-03-19 | [36267](https://github.com/airbytehq/airbyte/pull/36267) | Pin airbyte-cdk version to `^0` |
Expand Down
Loading