refactor[source-snapchat-marketing]: migrate to low-code (#39507)
Co-authored-by: Alexandre Girard <alexandre@airbyte.io>
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
[run]
|
||||
omit =
|
||||
source_snapchat_marketing/run.py
|
||||
@@ -2,77 +2,244 @@
|
||||
{
|
||||
"type": "STREAM",
|
||||
"stream": {
|
||||
"stream_state": {
|
||||
"updated_at": "2221-01-01T00:00:00Z"
|
||||
},
|
||||
"stream_descriptor": {
|
||||
"name": "adaccounts"
|
||||
"name": "adaccounts",
|
||||
"namespace": null
|
||||
},
|
||||
"stream_state": {
|
||||
"states": [
|
||||
{
|
||||
"partition": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
},
|
||||
"cursor": {
|
||||
"updated_at": "2221-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STREAM",
|
||||
"stream": {
|
||||
"stream_state": {
|
||||
"updated_at": "2221-01-01T00:00:00Z"
|
||||
},
|
||||
"stream_descriptor": {
|
||||
"name": "creatives"
|
||||
"name": "creatives",
|
||||
"namespace": null
|
||||
},
|
||||
"stream_state": {
|
||||
"states": [
|
||||
{
|
||||
"partition": {
|
||||
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"updated_at": "2221-01-01T00:00:00.000Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"partition": {
|
||||
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"updated_at": "2221-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STREAM",
|
||||
"stream": {
|
||||
"stream_state": {
|
||||
"updated_at": "2221-01-01T00:00:00Z"
|
||||
},
|
||||
"stream_descriptor": {
|
||||
"name": "media"
|
||||
"name": "media",
|
||||
"namespace": null
|
||||
},
|
||||
"stream_state": {
|
||||
"states": [
|
||||
{
|
||||
"partition": {
|
||||
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"updated_at": "2221-01-01T00:00:00.000Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"partition": {
|
||||
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"updated_at": "2221-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STREAM",
|
||||
"stream": {
|
||||
"stream_state": {
|
||||
"updated_at": "2221-01-01T00:00:00Z"
|
||||
},
|
||||
"stream_descriptor": {
|
||||
"name": "campaigns"
|
||||
"name": "campaigns",
|
||||
"namespace": null
|
||||
},
|
||||
"stream_state": {
|
||||
"states": [
|
||||
{
|
||||
"partition": {
|
||||
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"updated_at": "2221-01-01T00:00:00.000Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"partition": {
|
||||
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"updated_at": "2221-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STREAM",
|
||||
"stream": {
|
||||
"stream_state": {
|
||||
"updated_at": "2221-01-01T00:00:00Z"
|
||||
},
|
||||
"stream_descriptor": {
|
||||
"name": "ads"
|
||||
"name": "ads",
|
||||
"namespace": null
|
||||
},
|
||||
"stream_state": {
|
||||
"states": [
|
||||
{
|
||||
"partition": {
|
||||
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"updated_at": "2221-01-01T00:00:00.000Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"partition": {
|
||||
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"updated_at": "2221-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STREAM",
|
||||
"stream": {
|
||||
"stream_state": {
|
||||
"updated_at": "2221-01-01T00:00:00Z"
|
||||
},
|
||||
"stream_descriptor": {
|
||||
"name": "adsquads"
|
||||
"name": "adsquads",
|
||||
"namespace": null
|
||||
},
|
||||
"stream_state": {
|
||||
"states": [
|
||||
{
|
||||
"partition": {
|
||||
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"updated_at": "2221-01-01T00:00:00.000Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"partition": {
|
||||
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"updated_at": "2221-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STREAM",
|
||||
"stream": {
|
||||
"stream_state": {
|
||||
"updated_at": "2221-01-01T00:00:00Z"
|
||||
},
|
||||
"stream_descriptor": {
|
||||
"name": "segments"
|
||||
"name": "segments",
|
||||
"namespace": null
|
||||
},
|
||||
"stream_state": {
|
||||
"states": [
|
||||
{
|
||||
"partition": {
|
||||
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"updated_at": "2221-01-01T00:00:00.000Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"partition": {
|
||||
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"updated_at": "2221-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,44 +2,178 @@
|
||||
{
|
||||
"type": "STREAM",
|
||||
"stream": {
|
||||
"stream_state": {
|
||||
"start_time": "2221-07-05"
|
||||
},
|
||||
"stream_descriptor": {
|
||||
"name": "adaccounts_stats_daily"
|
||||
"name": "adaccounts_stats_daily",
|
||||
"namespace": null
|
||||
},
|
||||
"stream_state": {
|
||||
"states": [
|
||||
{
|
||||
"partition": {
|
||||
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"start_time": "2221-01-01T00:00:00.000-07:00"
|
||||
}
|
||||
},
|
||||
{
|
||||
"partition": {
|
||||
"id": "7a205dba-557f-4f00-82d7-c78853dcad39",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"start_time": "2221-01-01T00:00:00.000-07:00"
|
||||
}
|
||||
},
|
||||
{
|
||||
"partition": {
|
||||
"id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"start_time": "2221-01-01T00:00:00.000-07:00"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STREAM",
|
||||
"stream": {
|
||||
"stream_state": {
|
||||
"start_time": "2221-07-05"
|
||||
},
|
||||
"stream_descriptor": {
|
||||
"name": "ads_stats_daily"
|
||||
"name": "ads_stats_daily",
|
||||
"namespace": null
|
||||
},
|
||||
"stream_state": {
|
||||
"states": [
|
||||
{
|
||||
"partition": {
|
||||
"ad_id": "96e5549f-4065-490e-93dd-ffb9f7973b77",
|
||||
"parent_slice": {
|
||||
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"start_time": "2221-01-01T00:00:00.000-07:00"
|
||||
}
|
||||
},
|
||||
{
|
||||
"partition": {
|
||||
"id": "8831ae74-bd1e-4ea1-9628-76e549041bea",
|
||||
"parent_slice": {
|
||||
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"start_time": "2221-01-01T00:00:00.000-07:00"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STREAM",
|
||||
"stream": {
|
||||
"stream_state": {
|
||||
"start_time": "2221-07-05"
|
||||
},
|
||||
"stream_descriptor": {
|
||||
"name": "adsquads_stats_daily"
|
||||
"name": "adsquads_stats_daily",
|
||||
"namespace": null
|
||||
},
|
||||
"stream_state": {
|
||||
"states": [
|
||||
{
|
||||
"partition": {
|
||||
"adsquad_id": "ac6548b1-419e-4137-8320-e4e536766f72",
|
||||
"parent_slice": {
|
||||
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"start_time": "2221-01-01T00:00:00.000-07:00"
|
||||
}
|
||||
},
|
||||
{
|
||||
"partition": {
|
||||
"id": "87f00f80-8ae6-44ac-ab63-2c976d43de64",
|
||||
"parent_slice": {
|
||||
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"start_time": "2221-01-01T00:00:00.000-07:00"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STREAM",
|
||||
"stream": {
|
||||
"stream_state": {
|
||||
"start_time": "2221-07-05"
|
||||
},
|
||||
"stream_descriptor": {
|
||||
"name": "campaigns_stats_daily"
|
||||
"name": "campaigns_stats_daily",
|
||||
"namespace": null
|
||||
},
|
||||
"stream_state": {
|
||||
"states": [
|
||||
{
|
||||
"partition": {
|
||||
"campaign_id": "3369834f-5bc0-47bd-a4e9-ee48d424d90c",
|
||||
"parent_slice": {
|
||||
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"start_time": "2221-01-01T00:00:00.000-07:00"
|
||||
}
|
||||
},
|
||||
{
|
||||
"partition": {
|
||||
"id": "d180d36e-1212-479b-84a5-8b0663ceaf82",
|
||||
"parent_slice": {
|
||||
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
|
||||
"parent_slice": {
|
||||
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
|
||||
"parent_slice": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cursor": {
|
||||
"start_time": "2221-01-01T00:00:00.000-07:00"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"streams": [
|
||||
{
|
||||
"stream": {
|
||||
"name": "adaccounts_stats_hourly",
|
||||
"json_schema": {},
|
||||
"supported_sync_modes": ["full_refresh", "incremental"],
|
||||
"source_defined_cursor": true,
|
||||
"default_cursor_field": ["start_time"],
|
||||
"source_defined_primary_key": [["id"], ["granularity"], ["start_time"]]
|
||||
},
|
||||
"sync_mode": "incremental",
|
||||
"cursor_field": ["start_time"],
|
||||
"primary_key": [["id"], ["granularity"], ["start_time"]],
|
||||
"destination_sync_mode": "append"
|
||||
},
|
||||
{
|
||||
"stream": {
|
||||
"name": "ads_stats_hourly",
|
||||
"json_schema": {},
|
||||
"supported_sync_modes": ["full_refresh", "incremental"],
|
||||
"source_defined_cursor": true,
|
||||
"default_cursor_field": ["start_time"],
|
||||
"source_defined_primary_key": [["id"], ["granularity"], ["start_time"]]
|
||||
},
|
||||
"sync_mode": "incremental",
|
||||
"cursor_field": ["start_time"],
|
||||
"primary_key": [["id"], ["granularity"], ["start_time"]],
|
||||
"destination_sync_mode": "append"
|
||||
},
|
||||
{
|
||||
"stream": {
|
||||
"name": "adsquads_stats_hourly",
|
||||
"json_schema": {},
|
||||
"supported_sync_modes": ["full_refresh", "incremental"],
|
||||
"source_defined_cursor": true,
|
||||
"default_cursor_field": ["start_time"],
|
||||
"source_defined_primary_key": [["id"], ["granularity"], ["start_time"]]
|
||||
},
|
||||
"sync_mode": "incremental",
|
||||
"cursor_field": ["start_time"],
|
||||
"primary_key": [["id"], ["granularity"], ["start_time"]],
|
||||
"destination_sync_mode": "append"
|
||||
},
|
||||
{
|
||||
"stream": {
|
||||
"name": "campaigns_stats_hourly",
|
||||
"json_schema": {},
|
||||
"supported_sync_modes": ["full_refresh", "incremental"],
|
||||
"source_defined_cursor": true,
|
||||
"default_cursor_field": ["start_time"],
|
||||
"source_defined_primary_key": [["id"], ["granularity"], ["start_time"]]
|
||||
},
|
||||
"sync_mode": "incremental",
|
||||
"cursor_field": ["start_time"],
|
||||
"destination_sync_mode": "append",
|
||||
"primary_key": [["id"], ["granularity"], ["start_time"]]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -22,4 +22,4 @@
|
||||
{"stream": "adsquads_stats_hourly", "data": {"start_time": "2024-05-14T23:00:00.000-07:00", "end_time": "2024-05-15T00:00:00.000-07:00", "id": "87f00f80-8ae6-44ac-ab63-2c976d43de64", "type": "AD_SQUAD", "granularity": "HOUR", "android_installs": 0, "attachment_avg_view_time_millis": 0, "attachment_impressions": 0, "attachment_quartile_1": 0, "attachment_quartile_2": 0, "attachment_quartile_3": 0, "attachment_total_view_time_millis": 0, "attachment_view_completion": 0, "avg_screen_time_millis": 0, "avg_view_time_millis": 0, "impressions": 0, "ios_installs": 0, "quartile_1": 0, "quartile_2": 0, "quartile_3": 0, "screen_time_millis": 0, "swipe_up_percent": 0.0, "swipes": 0, "total_installs": 0, "video_views": 0, "video_views_time_based": 0, "video_views_15s": 0, "view_completion": 0, "view_time_millis": 0, "paid_impressions": 0, "earned_impressions": 0, "total_impressions": 0, "play_time_millis": 0, "shares": 0, "saves": 0, "native_leads": 0, "conversion_purchases": 0, "conversion_purchases_value": 0, "conversion_save": 0, "conversion_start_checkout": 0, "conversion_add_cart": 0, "conversion_view_content": 0, "conversion_add_billing": 0, "conversion_searches": 0, "conversion_level_completes": 0, "conversion_app_opens": 0, "conversion_page_views": 0, "conversion_subscribe": 0, "conversion_ad_click": 0, "conversion_ad_view": 0, "conversion_complete_tutorial": 0, "conversion_invite": 0, "conversion_login": 0, "conversion_share": 0, "conversion_reserve": 0, "conversion_achievement_unlocked": 0, "conversion_add_to_wishlist": 0, "conversion_spend_credits": 0, "conversion_rate": 0, "conversion_start_trial": 0, "conversion_list_view": 0, "custom_event_1": 0, "custom_event_2": 0, "custom_event_3": 0, "custom_event_4": 0, "custom_event_5": 0, "story_opens": 0, "story_completes": 0}, "emitted_at": 1718737703937}
|
||||
{"stream": "adsquads_stats_hourly", "data": {"start_time": "2024-05-15T00:00:00.000-07:00", "end_time": "2024-05-15T01:00:00.000-07:00", "id": "87f00f80-8ae6-44ac-ab63-2c976d43de64", "type": "AD_SQUAD", "granularity": "HOUR", "android_installs": 0, "attachment_avg_view_time_millis": 0, "attachment_impressions": 0, "attachment_quartile_1": 0, "attachment_quartile_2": 0, "attachment_quartile_3": 0, "attachment_total_view_time_millis": 0, "attachment_view_completion": 0, "avg_screen_time_millis": 0, "avg_view_time_millis": 0, "impressions": 0, "ios_installs": 0, "quartile_1": 0, "quartile_2": 0, "quartile_3": 0, "screen_time_millis": 0, "swipe_up_percent": 0.0, "swipes": 0, "total_installs": 0, "video_views": 0, "video_views_time_based": 0, "video_views_15s": 0, "view_completion": 0, "view_time_millis": 0, "paid_impressions": 0, "earned_impressions": 0, "total_impressions": 0, "play_time_millis": 0, "shares": 0, "saves": 0, "native_leads": 0, "conversion_purchases": 0, "conversion_purchases_value": 0, "conversion_save": 0, "conversion_start_checkout": 0, "conversion_add_cart": 0, "conversion_view_content": 0, "conversion_add_billing": 0, "conversion_searches": 0, "conversion_level_completes": 0, "conversion_app_opens": 0, "conversion_page_views": 0, "conversion_subscribe": 0, "conversion_ad_click": 0, "conversion_ad_view": 0, "conversion_complete_tutorial": 0, "conversion_invite": 0, "conversion_login": 0, "conversion_share": 0, "conversion_reserve": 0, "conversion_achievement_unlocked": 0, "conversion_add_to_wishlist": 0, "conversion_spend_credits": 0, "conversion_rate": 0, "conversion_start_trial": 0, "conversion_list_view": 0, "custom_event_1": 0, "custom_event_2": 0, "custom_event_3": 0, "custom_event_4": 0, "custom_event_5": 0, "story_opens": 0, "story_completes": 0}, "emitted_at": 1718737704063}
|
||||
{"stream": "campaigns_stats_hourly", "data": {"start_time": "2024-05-14T21:00:00.000-07:00", "end_time": "2024-05-14T22:00:00.000-07:00", "id": "d180d36e-1212-479b-84a5-8b0663ceaf82", "type": "CAMPAIGN", "granularity": "HOUR", "android_installs": 0, "attachment_avg_view_time_millis": 0, "attachment_impressions": 0, "attachment_quartile_1": 0, "attachment_quartile_2": 0, "attachment_quartile_3": 0, "attachment_total_view_time_millis": 0, "attachment_view_completion": 0, "avg_screen_time_millis": 0, "avg_view_time_millis": 0, "impressions": 0, "ios_installs": 0, "quartile_1": 0, "quartile_2": 0, "quartile_3": 0, "screen_time_millis": 0, "swipe_up_percent": 0.0, "swipes": 0, "total_installs": 0, "video_views": 0, "video_views_time_based": 0, "video_views_15s": 0, "view_completion": 0, "view_time_millis": 0, "paid_impressions": 0, "earned_impressions": 0, "total_impressions": 0, "play_time_millis": 0, "shares": 0, "saves": 0, "native_leads": 0, "conversion_purchases": 0, "conversion_purchases_value": 0, "conversion_save": 0, "conversion_start_checkout": 0, "conversion_add_cart": 0, "conversion_view_content": 0, "conversion_add_billing": 0, "conversion_searches": 0, "conversion_level_completes": 0, "conversion_app_opens": 0, "conversion_page_views": 0, "conversion_subscribe": 0, "conversion_ad_click": 0, "conversion_ad_view": 0, "conversion_complete_tutorial": 0, "conversion_invite": 0, "conversion_login": 0, "conversion_share": 0, "conversion_reserve": 0, "conversion_achievement_unlocked": 0, "conversion_add_to_wishlist": 0, "conversion_spend_credits": 0, "conversion_rate": 0, "conversion_start_trial": 0, "conversion_list_view": 0, "custom_event_1": 0, "custom_event_2": 0, "custom_event_3": 0, "custom_event_4": 0, "custom_event_5": 0, "story_opens": 0, "story_completes": 0}, "emitted_at": 1718737739971}
|
||||
{"stream": "campaigns_stats_hourly", "data": {"start_time": "2024-05-14T22:00:00.000-07:00", "end_time": "2024-05-14T23:00:00.000-07:00", "id": "d180d36e-1212-479b-84a5-8b0663ceaf82", "type": "CAMPAIGN", "granularity": "HOUR", "android_installs": 0, "attachment_avg_view_time_millis": 0, "attachment_impressions": 0, "attachment_quartile_1": 0, "attachment_quartile_2": 0, "attachment_quartile_3": 0, "attachment_total_view_time_millis": 0, "attachment_view_completion": 0, "avg_screen_time_millis": 0, "avg_view_time_millis": 0, "impressions": 0, "ios_installs": 0, "quartile_1": 0, "quartile_2": 0, "quartile_3": 0, "screen_time_millis": 0, "swipe_up_percent": 0.0, "swipes": 0, "total_installs": 0, "video_views": 0, "video_views_time_based": 0, "video_views_15s": 0, "view_completion": 0, "view_time_millis": 0, "paid_impressions": 0, "earned_impressions": 0, "total_impressions": 0, "play_time_millis": 0, "shares": 0, "saves": 0, "native_leads": 0, "conversion_purchases": 0, "conversion_purchases_value": 0, "conversion_save": 0, "conversion_start_checkout": 0, "conversion_add_cart": 0, "conversion_view_content": 0, "conversion_add_billing": 0, "conversion_searches": 0, "conversion_level_completes": 0, "conversion_app_opens": 0, "conversion_page_views": 0, "conversion_subscribe": 0, "conversion_ad_click": 0, "conversion_ad_view": 0, "conversion_complete_tutorial": 0, "conversion_invite": 0, "conversion_login": 0, "conversion_share": 0, "conversion_reserve": 0, "conversion_achievement_unlocked": 0, "conversion_add_to_wishlist": 0, "conversion_spend_credits": 0, "conversion_rate": 0, "conversion_start_trial": 0, "conversion_list_view": 0, "custom_event_1": 0, "custom_event_2": 0, "custom_event_3": 0, "custom_event_4": 0, "custom_event_5": 0, "story_opens": 0, "story_completes": 0}, "emitted_at": 1718737740086}
|
||||
{"stream": "campaigns_stats_hourly", "data": {"start_time": "2024-05-14T22:00:00.000-07:00", "end_time": "2024-05-14T23:00:00.000-07:00", "id": "d180d36e-1212-479b-84a5-8b0663ceaf82", "type": "CAMPAIGN", "granularity": "HOUR", "android_installs": 0, "attachment_avg_view_time_millis": 0, "attachment_impressions": 0, "attachment_quartile_1": 0, "attachment_quartile_2": 0, "attachment_quartile_3": 0, "attachment_total_view_time_millis": 0, "attachment_view_completion": 0, "avg_screen_time_millis": 0, "avg_view_time_millis": 0, "impressions": 0, "ios_installs": 0, "quartile_1": 0, "quartile_2": 0, "quartile_3": 0, "screen_time_millis": 0, "swipe_up_percent": 0.0, "swipes": 0, "total_installs": 0, "video_views": 0, "video_views_time_based": 0, "video_views_15s": 0, "view_completion": 0, "view_time_millis": 0, "paid_impressions": 0, "earned_impressions": 0, "total_impressions": 0, "play_time_millis": 0, "shares": 0, "saves": 0, "native_leads": 0, "conversion_purchases": 0, "conversion_purchases_value": 0, "conversion_save": 0, "conversion_start_checkout": 0, "conversion_add_cart": 0, "conversion_view_content": 0, "conversion_add_billing": 0, "conversion_searches": 0, "conversion_level_completes": 0, "conversion_app_opens": 0, "conversion_page_views": 0, "conversion_subscribe": 0, "conversion_ad_click": 0, "conversion_ad_view": 0, "conversion_complete_tutorial": 0, "conversion_invite": 0, "conversion_login": 0, "conversion_share": 0, "conversion_reserve": 0, "conversion_achievement_unlocked": 0, "conversion_add_to_wishlist": 0, "conversion_spend_credits": 0, "conversion_rate": 0, "conversion_start_trial": 0, "conversion_list_view": 0, "custom_event_1": 0, "custom_event_2": 0, "custom_event_3": 0, "custom_event_4": 0, "custom_event_5": 0, "story_opens": 0, "story_completes": 0}, "emitted_at": 1718737740086}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"documentationUrl": "https://docs.airbyte.com/integrations/sources/snapchat-marketing",
|
||||
"connectionSpecification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Snapchat Marketing Spec",
|
||||
@@ -74,7 +73,10 @@
|
||||
},
|
||||
"advanced_auth": {
|
||||
"auth_flow_type": "oauth2.0",
|
||||
"predicate_key": null,
|
||||
"predicate_value": null,
|
||||
"oauth_config_specification": {
|
||||
"oauth_user_input_from_connector_config_specification": null,
|
||||
"complete_oauth_output_specification": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -8,7 +8,7 @@ data:
|
||||
connectorSubtype: api
|
||||
connectorType: source
|
||||
definitionId: 200330b2-ea62-4d11-ac6d-cfe3e3f8ab2b
|
||||
dockerImageTag: 0.6.2
|
||||
dockerImageTag: 1.0.0
|
||||
dockerRepository: airbyte/source-snapchat-marketing
|
||||
githubIssueLabel: source-snapchat-marketing
|
||||
icon: snapchat.svg
|
||||
@@ -25,10 +25,42 @@ data:
|
||||
oss:
|
||||
enabled: true
|
||||
releaseStage: generally_available
|
||||
releases:
|
||||
breakingChanges:
|
||||
1.0.0:
|
||||
message: >-
|
||||
The source Snapchat Marketing connector is being migrated from the Python CDK to our declarative low-code CDK.
|
||||
Due to changes to the incremental stream state, this migration constitutes a breaking change. Additionally,
|
||||
added incremental functionality to organizations. After updating, please reset your source before resuming syncs.
|
||||
For more information, see our migration documentation for source Snapchat Marketing.
|
||||
upgradeDeadline: "2024-07-16"
|
||||
scopedImpact:
|
||||
- scopeType: stream
|
||||
impactedScopes:
|
||||
- "organizations"
|
||||
- "adaccounts"
|
||||
- "creatives"
|
||||
- "ads"
|
||||
- "adsquads"
|
||||
- "segments"
|
||||
- "media"
|
||||
- "campaigns"
|
||||
- "adaccounts_stats_hourly"
|
||||
- "adaccounts_stats_daily"
|
||||
- "adaccounts_stats_lifetime"
|
||||
- "ads_stats_hourly"
|
||||
- "ads_stats_daily"
|
||||
- "ads_stats_lifetime"
|
||||
- "adsquads_stats_hourly"
|
||||
- "adsquads_stats_daily"
|
||||
- "adsquads_stats_lifetime"
|
||||
- "campaigns_stats_hourly"
|
||||
- "campaigns_stats_daily"
|
||||
- "campaigns_stats_lifetime"
|
||||
documentationUrl: https://docs.airbyte.com/integrations/sources/snapchat-marketing
|
||||
tags:
|
||||
- language:python
|
||||
- cdk:python
|
||||
- cdk:low-code
|
||||
ab_internal:
|
||||
sl: 200
|
||||
ql: 400
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "airbyte-cdk"
|
||||
version = "0.90.0"
|
||||
version = "1.8.0"
|
||||
description = "A framework for writing Airbyte Connectors."
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.9"
|
||||
files = [
|
||||
{file = "airbyte_cdk-0.90.0-py3-none-any.whl", hash = "sha256:bd0aa5843cdc4901f2e482f0e86695ca4e6db83b65c5017799255dd20535cf56"},
|
||||
{file = "airbyte_cdk-0.90.0.tar.gz", hash = "sha256:25cefc010718bada5cce3f87e7ae93068630732c0d34ce5145f8ddf7457d4d3c"},
|
||||
{file = "airbyte_cdk-1.8.0-py3-none-any.whl", hash = "sha256:ca23d7877005fe87ffc4a3a3de29ee55eed625d874eb59b49664b156f9ae9ee2"},
|
||||
{file = "airbyte_cdk-1.8.0.tar.gz", hash = "sha256:ac82fbfd6b650b7ed015900748e30fdd2a4c574caa54d1bcc03cb584a17f1533"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -17,7 +17,7 @@ backoff = "*"
|
||||
cachetools = "*"
|
||||
cryptography = ">=42.0.5,<43.0.0"
|
||||
Deprecated = ">=1.2,<1.3"
|
||||
dpath = ">=2.0.1,<2.1.0"
|
||||
dpath = ">=2.1.6,<3.0.0"
|
||||
genson = "1.2.2"
|
||||
isodate = ">=0.6.1,<0.7.0"
|
||||
Jinja2 = ">=3.1.2,<3.2.0"
|
||||
@@ -42,13 +42,13 @@ vector-db-based = ["cohere (==4.21)", "langchain (==0.1.16)", "openai[embeddings
|
||||
|
||||
[[package]]
|
||||
name = "airbyte-protocol-models"
|
||||
version = "0.11.0"
|
||||
version = "0.12.2"
|
||||
description = "Declares the Airbyte Protocol."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "airbyte_protocol_models-0.11.0-py3-none-any.whl", hash = "sha256:2157757c1af8c13e471ab6a0304fd2f9a2a6af8cc9173937be1348a9553f7c32"},
|
||||
{file = "airbyte_protocol_models-0.11.0.tar.gz", hash = "sha256:1c7e46251b0d5a292b4aa382df24f415ac2a2a2b4719361b3c0f76368a043c23"},
|
||||
{file = "airbyte_protocol_models-0.12.2-py3-none-any.whl", hash = "sha256:1780db5b26285865b858d26502933def8e11919c9436ccf7b8b9cb0170b07c2a"},
|
||||
{file = "airbyte_protocol_models-0.12.2.tar.gz", hash = "sha256:b7c4d9a7c32c0691601c2b9416af090a858e126666e2c8c880d7a1798eb519f0"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -143,13 +143,13 @@ ujson = ["ujson (>=5.7.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2024.2.2"
|
||||
version = "2024.6.2"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"},
|
||||
{file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"},
|
||||
{file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"},
|
||||
{file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -328,43 +328,43 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "cryptography"
|
||||
version = "42.0.7"
|
||||
version = "42.0.8"
|
||||
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"},
|
||||
{file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"},
|
||||
{file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"},
|
||||
{file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"},
|
||||
{file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"},
|
||||
{file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"},
|
||||
{file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"},
|
||||
{file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"},
|
||||
{file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"},
|
||||
{file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"},
|
||||
{file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"},
|
||||
{file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"},
|
||||
{file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"},
|
||||
{file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"},
|
||||
{file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"},
|
||||
{file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"},
|
||||
{file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"},
|
||||
{file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"},
|
||||
{file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -399,13 +399,13 @@ dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"]
|
||||
|
||||
[[package]]
|
||||
name = "dpath"
|
||||
version = "2.0.8"
|
||||
version = "2.2.0"
|
||||
description = "Filesystem-like pathing and searching for dictionaries"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "dpath-2.0.8-py3-none-any.whl", hash = "sha256:f92f595214dd93a00558d75d4b858beee519f4cffca87f02616ad6cd013f3436"},
|
||||
{file = "dpath-2.0.8.tar.gz", hash = "sha256:a3440157ebe80d0a3ad794f1b61c571bef125214800ffdb9afc9424e8250fe9b"},
|
||||
{file = "dpath-2.2.0-py3-none-any.whl", hash = "sha256:b330a375ded0a0d2ed404440f6c6a715deae5313af40bbb01c8a41d891900576"},
|
||||
{file = "dpath-2.2.0.tar.gz", hash = "sha256:34f7e630dc55ea3f219e555726f5da4b4b25f2200319c8e6902c394258dd6a3e"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -501,13 +501,13 @@ jsonpointer = ">=1.9"
|
||||
|
||||
[[package]]
|
||||
name = "jsonpointer"
|
||||
version = "2.4"
|
||||
version = "3.0.0"
|
||||
description = "Identify specific nodes in a JSON document (RFC 6901)"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*"
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"},
|
||||
{file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"},
|
||||
{file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"},
|
||||
{file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -566,13 +566,13 @@ extended-testing = ["jinja2 (>=3,<4)"]
|
||||
|
||||
[[package]]
|
||||
name = "langsmith"
|
||||
version = "0.1.60"
|
||||
version = "0.1.81"
|
||||
description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.8.1"
|
||||
files = [
|
||||
{file = "langsmith-0.1.60-py3-none-any.whl", hash = "sha256:3c3520ea473de0a984237b3e9d638fdf23ef3acc5aec89a42e693225e72d6120"},
|
||||
{file = "langsmith-0.1.60.tar.gz", hash = "sha256:6a145b5454437f9e0f81525f23c4dcdbb8c07b1c91553b8f697456c418d6a599"},
|
||||
{file = "langsmith-0.1.81-py3-none-any.whl", hash = "sha256:3251d823225eef23ee541980b9d9e506367eabbb7f985a086b5d09e8f78ba7e9"},
|
||||
{file = "langsmith-0.1.81.tar.gz", hash = "sha256:585ef3a2251380bd2843a664c9a28da4a7d28432e3ee8bcebf291ffb8e1f0af0"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -651,57 +651,57 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "orjson"
|
||||
version = "3.10.3"
|
||||
version = "3.10.5"
|
||||
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "orjson-3.10.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9fb6c3f9f5490a3eb4ddd46fc1b6eadb0d6fc16fb3f07320149c3286a1409dd8"},
|
||||
{file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:252124b198662eee80428f1af8c63f7ff077c88723fe206a25df8dc57a57b1fa"},
|
||||
{file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f3e87733823089a338ef9bbf363ef4de45e5c599a9bf50a7a9b82e86d0228da"},
|
||||
{file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8334c0d87103bb9fbbe59b78129f1f40d1d1e8355bbed2ca71853af15fa4ed3"},
|
||||
{file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1952c03439e4dce23482ac846e7961f9d4ec62086eb98ae76d97bd41d72644d7"},
|
||||
{file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0403ed9c706dcd2809f1600ed18f4aae50be263bd7112e54b50e2c2bc3ebd6d"},
|
||||
{file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:382e52aa4270a037d41f325e7d1dfa395b7de0c367800b6f337d8157367bf3a7"},
|
||||
{file = "orjson-3.10.3-cp310-none-win32.whl", hash = "sha256:be2aab54313752c04f2cbaab4515291ef5af8c2256ce22abc007f89f42f49109"},
|
||||
{file = "orjson-3.10.3-cp310-none-win_amd64.whl", hash = "sha256:416b195f78ae461601893f482287cee1e3059ec49b4f99479aedf22a20b1098b"},
|
||||
{file = "orjson-3.10.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:73100d9abbbe730331f2242c1fc0bcb46a3ea3b4ae3348847e5a141265479700"},
|
||||
{file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a12eee96e3ab828dbfcb4d5a0023aa971b27143a1d35dc214c176fdfb29b3"},
|
||||
{file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520de5e2ef0b4ae546bea25129d6c7c74edb43fc6cf5213f511a927f2b28148b"},
|
||||
{file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccaa0a401fc02e8828a5bedfd80f8cd389d24f65e5ca3954d72c6582495b4bcf"},
|
||||
{file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7bc9e8bc11bac40f905640acd41cbeaa87209e7e1f57ade386da658092dc16"},
|
||||
{file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3582b34b70543a1ed6944aca75e219e1192661a63da4d039d088a09c67543b08"},
|
||||
{file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c23dfa91481de880890d17aa7b91d586a4746a4c2aa9a145bebdbaf233768d5"},
|
||||
{file = "orjson-3.10.3-cp311-none-win32.whl", hash = "sha256:1770e2a0eae728b050705206d84eda8b074b65ee835e7f85c919f5705b006c9b"},
|
||||
{file = "orjson-3.10.3-cp311-none-win_amd64.whl", hash = "sha256:93433b3c1f852660eb5abdc1f4dd0ced2be031ba30900433223b28ee0140cde5"},
|
||||
{file = "orjson-3.10.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a39aa73e53bec8d410875683bfa3a8edf61e5a1c7bb4014f65f81d36467ea098"},
|
||||
{file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0943a96b3fa09bee1afdfccc2cb236c9c64715afa375b2af296c73d91c23eab2"},
|
||||
{file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e852baafceff8da3c9defae29414cc8513a1586ad93e45f27b89a639c68e8176"},
|
||||
{file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18566beb5acd76f3769c1d1a7ec06cdb81edc4d55d2765fb677e3eaa10fa99e0"},
|
||||
{file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd2218d5a3aa43060efe649ec564ebedec8ce6ae0a43654b81376216d5ebd42"},
|
||||
{file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cf20465e74c6e17a104ecf01bf8cd3b7b252565b4ccee4548f18b012ff2f8069"},
|
||||
{file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7f67aa7f983c4345eeda16054a4677289011a478ca947cd69c0a86ea45e534"},
|
||||
{file = "orjson-3.10.3-cp312-none-win32.whl", hash = "sha256:17e0713fc159abc261eea0f4feda611d32eabc35708b74bef6ad44f6c78d5ea0"},
|
||||
{file = "orjson-3.10.3-cp312-none-win_amd64.whl", hash = "sha256:4c895383b1ec42b017dd2c75ae8a5b862fc489006afde06f14afbdd0309b2af0"},
|
||||
{file = "orjson-3.10.3-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:be2719e5041e9fb76c8c2c06b9600fe8e8584e6980061ff88dcbc2691a16d20d"},
|
||||
{file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0175a5798bdc878956099f5c54b9837cb62cfbf5d0b86ba6d77e43861bcec2"},
|
||||
{file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:978be58a68ade24f1af7758626806e13cff7748a677faf95fbb298359aa1e20d"},
|
||||
{file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16bda83b5c61586f6f788333d3cf3ed19015e3b9019188c56983b5a299210eb5"},
|
||||
{file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ad1f26bea425041e0a1adad34630c4825a9e3adec49079b1fb6ac8d36f8b754"},
|
||||
{file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9e253498bee561fe85d6325ba55ff2ff08fb5e7184cd6a4d7754133bd19c9195"},
|
||||
{file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a62f9968bab8a676a164263e485f30a0b748255ee2f4ae49a0224be95f4532b"},
|
||||
{file = "orjson-3.10.3-cp38-none-win32.whl", hash = "sha256:8d0b84403d287d4bfa9bf7d1dc298d5c1c5d9f444f3737929a66f2fe4fb8f134"},
|
||||
{file = "orjson-3.10.3-cp38-none-win_amd64.whl", hash = "sha256:8bc7a4df90da5d535e18157220d7915780d07198b54f4de0110eca6b6c11e290"},
|
||||
{file = "orjson-3.10.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9059d15c30e675a58fdcd6f95465c1522b8426e092de9fff20edebfdc15e1cb0"},
|
||||
{file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d40c7f7938c9c2b934b297412c067936d0b54e4b8ab916fd1a9eb8f54c02294"},
|
||||
{file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a654ec1de8fdaae1d80d55cee65893cb06494e124681ab335218be6a0691e7"},
|
||||
{file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831c6ef73f9aa53c5f40ae8f949ff7681b38eaddb6904aab89dca4d85099cb78"},
|
||||
{file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b880d7e34542db89f48d14ddecbd26f06838b12427d5a25d71baceb5ba119d"},
|
||||
{file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e5e176c994ce4bd434d7aafb9ecc893c15f347d3d2bbd8e7ce0b63071c52e25"},
|
||||
{file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b69a58a37dab856491bf2d3bbf259775fdce262b727f96aafbda359cb1d114d8"},
|
||||
{file = "orjson-3.10.3-cp39-none-win32.whl", hash = "sha256:b8d4d1a6868cde356f1402c8faeb50d62cee765a1f7ffcfd6de732ab0581e063"},
|
||||
{file = "orjson-3.10.3-cp39-none-win_amd64.whl", hash = "sha256:5102f50c5fc46d94f2033fe00d392588564378260d64377aec702f21a7a22912"},
|
||||
{file = "orjson-3.10.3.tar.gz", hash = "sha256:2b166507acae7ba2f7c315dcf185a9111ad5e992ac81f2d507aac39193c2c818"},
|
||||
{file = "orjson-3.10.5-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:545d493c1f560d5ccfc134803ceb8955a14c3fcb47bbb4b2fee0232646d0b932"},
|
||||
{file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4324929c2dd917598212bfd554757feca3e5e0fa60da08be11b4aa8b90013c1"},
|
||||
{file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c13ca5e2ddded0ce6a927ea5a9f27cae77eee4c75547b4297252cb20c4d30e6"},
|
||||
{file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b6c8e30adfa52c025f042a87f450a6b9ea29649d828e0fec4858ed5e6caecf63"},
|
||||
{file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:338fd4f071b242f26e9ca802f443edc588fa4ab60bfa81f38beaedf42eda226c"},
|
||||
{file = "orjson-3.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6970ed7a3126cfed873c5d21ece1cd5d6f83ca6c9afb71bbae21a0b034588d96"},
|
||||
{file = "orjson-3.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:235dadefb793ad12f7fa11e98a480db1f7c6469ff9e3da5e73c7809c700d746b"},
|
||||
{file = "orjson-3.10.5-cp310-none-win32.whl", hash = "sha256:be79e2393679eda6a590638abda16d167754393f5d0850dcbca2d0c3735cebe2"},
|
||||
{file = "orjson-3.10.5-cp310-none-win_amd64.whl", hash = "sha256:c4a65310ccb5c9910c47b078ba78e2787cb3878cdded1702ac3d0da71ddc5228"},
|
||||
{file = "orjson-3.10.5-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:cdf7365063e80899ae3a697def1277c17a7df7ccfc979990a403dfe77bb54d40"},
|
||||
{file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b68742c469745d0e6ca5724506858f75e2f1e5b59a4315861f9e2b1df77775a"},
|
||||
{file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7d10cc1b594951522e35a3463da19e899abe6ca95f3c84c69e9e901e0bd93d38"},
|
||||
{file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dcbe82b35d1ac43b0d84072408330fd3295c2896973112d495e7234f7e3da2e1"},
|
||||
{file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c0eb7e0c75e1e486c7563fe231b40fdd658a035ae125c6ba651ca3b07936f5"},
|
||||
{file = "orjson-3.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:53ed1c879b10de56f35daf06dbc4a0d9a5db98f6ee853c2dbd3ee9d13e6f302f"},
|
||||
{file = "orjson-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:099e81a5975237fda3100f918839af95f42f981447ba8f47adb7b6a3cdb078fa"},
|
||||
{file = "orjson-3.10.5-cp311-none-win32.whl", hash = "sha256:1146bf85ea37ac421594107195db8bc77104f74bc83e8ee21a2e58596bfb2f04"},
|
||||
{file = "orjson-3.10.5-cp311-none-win_amd64.whl", hash = "sha256:36a10f43c5f3a55c2f680efe07aa93ef4a342d2960dd2b1b7ea2dd764fe4a37c"},
|
||||
{file = "orjson-3.10.5-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:68f85ecae7af14a585a563ac741b0547a3f291de81cd1e20903e79f25170458f"},
|
||||
{file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28afa96f496474ce60d3340fe8d9a263aa93ea01201cd2bad844c45cd21f5268"},
|
||||
{file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cd684927af3e11b6e754df80b9ffafd9fb6adcaa9d3e8fdd5891be5a5cad51e"},
|
||||
{file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d21b9983da032505f7050795e98b5d9eee0df903258951566ecc358f6696969"},
|
||||
{file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ad1de7fef79736dde8c3554e75361ec351158a906d747bd901a52a5c9c8d24b"},
|
||||
{file = "orjson-3.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d97531cdfe9bdd76d492e69800afd97e5930cb0da6a825646667b2c6c6c0211"},
|
||||
{file = "orjson-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d69858c32f09c3e1ce44b617b3ebba1aba030e777000ebdf72b0d8e365d0b2b3"},
|
||||
{file = "orjson-3.10.5-cp312-none-win32.whl", hash = "sha256:64c9cc089f127e5875901ac05e5c25aa13cfa5dbbbd9602bda51e5c611d6e3e2"},
|
||||
{file = "orjson-3.10.5-cp312-none-win_amd64.whl", hash = "sha256:b2efbd67feff8c1f7728937c0d7f6ca8c25ec81373dc8db4ef394c1d93d13dc5"},
|
||||
{file = "orjson-3.10.5-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:03b565c3b93f5d6e001db48b747d31ea3819b89abf041ee10ac6988886d18e01"},
|
||||
{file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:584c902ec19ab7928fd5add1783c909094cc53f31ac7acfada817b0847975f26"},
|
||||
{file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a35455cc0b0b3a1eaf67224035f5388591ec72b9b6136d66b49a553ce9eb1e6"},
|
||||
{file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1670fe88b116c2745a3a30b0f099b699a02bb3482c2591514baf5433819e4f4d"},
|
||||
{file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185c394ef45b18b9a7d8e8f333606e2e8194a50c6e3c664215aae8cf42c5385e"},
|
||||
{file = "orjson-3.10.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ca0b3a94ac8d3886c9581b9f9de3ce858263865fdaa383fbc31c310b9eac07c9"},
|
||||
{file = "orjson-3.10.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dfc91d4720d48e2a709e9c368d5125b4b5899dced34b5400c3837dadc7d6271b"},
|
||||
{file = "orjson-3.10.5-cp38-none-win32.whl", hash = "sha256:c05f16701ab2a4ca146d0bca950af254cb7c02f3c01fca8efbbad82d23b3d9d4"},
|
||||
{file = "orjson-3.10.5-cp38-none-win_amd64.whl", hash = "sha256:8a11d459338f96a9aa7f232ba95679fc0c7cedbd1b990d736467894210205c09"},
|
||||
{file = "orjson-3.10.5-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:85c89131d7b3218db1b24c4abecea92fd6c7f9fab87441cfc342d3acc725d807"},
|
||||
{file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb66215277a230c456f9038d5e2d84778141643207f85336ef8d2a9da26bd7ca"},
|
||||
{file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:51bbcdea96cdefa4a9b4461e690c75ad4e33796530d182bdd5c38980202c134a"},
|
||||
{file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbead71dbe65f959b7bd8cf91e0e11d5338033eba34c114f69078d59827ee139"},
|
||||
{file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5df58d206e78c40da118a8c14fc189207fffdcb1f21b3b4c9c0c18e839b5a214"},
|
||||
{file = "orjson-3.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c4057c3b511bb8aef605616bd3f1f002a697c7e4da6adf095ca5b84c0fd43595"},
|
||||
{file = "orjson-3.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b39e006b00c57125ab974362e740c14a0c6a66ff695bff44615dcf4a70ce2b86"},
|
||||
{file = "orjson-3.10.5-cp39-none-win32.whl", hash = "sha256:eded5138cc565a9d618e111c6d5c2547bbdd951114eb822f7f6309e04db0fb47"},
|
||||
{file = "orjson-3.10.5-cp39-none-win_amd64.whl", hash = "sha256:cc28e90a7cae7fcba2493953cff61da5a52950e78dc2dacfe931a317ee3d8de7"},
|
||||
{file = "orjson-3.10.5.tar.gz", hash = "sha256:7a5baef8a4284405d96c90c7c62b755e9ef1ada84c2406c24a9ebec86b89f46d"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -804,47 +804,47 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "1.10.15"
|
||||
version = "1.10.16"
|
||||
description = "Data validation and settings management using python type hints"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pydantic-1.10.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:22ed12ee588b1df028a2aa5d66f07bf8f8b4c8579c2e96d5a9c1f96b77f3bb55"},
|
||||
{file = "pydantic-1.10.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:75279d3cac98186b6ebc2597b06bcbc7244744f6b0b44a23e4ef01e5683cc0d2"},
|
||||
{file = "pydantic-1.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50f1666a9940d3d68683c9d96e39640f709d7a72ff8702987dab1761036206bb"},
|
||||
{file = "pydantic-1.10.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82790d4753ee5d00739d6cb5cf56bceb186d9d6ce134aca3ba7befb1eedbc2c8"},
|
||||
{file = "pydantic-1.10.15-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d207d5b87f6cbefbdb1198154292faee8017d7495a54ae58db06762004500d00"},
|
||||
{file = "pydantic-1.10.15-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e49db944fad339b2ccb80128ffd3f8af076f9f287197a480bf1e4ca053a866f0"},
|
||||
{file = "pydantic-1.10.15-cp310-cp310-win_amd64.whl", hash = "sha256:d3b5c4cbd0c9cb61bbbb19ce335e1f8ab87a811f6d589ed52b0254cf585d709c"},
|
||||
{file = "pydantic-1.10.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c3d5731a120752248844676bf92f25a12f6e45425e63ce22e0849297a093b5b0"},
|
||||
{file = "pydantic-1.10.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c365ad9c394f9eeffcb30a82f4246c0006417f03a7c0f8315d6211f25f7cb654"},
|
||||
{file = "pydantic-1.10.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3287e1614393119c67bd4404f46e33ae3be3ed4cd10360b48d0a4459f420c6a3"},
|
||||
{file = "pydantic-1.10.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be51dd2c8596b25fe43c0a4a59c2bee4f18d88efb8031188f9e7ddc6b469cf44"},
|
||||
{file = "pydantic-1.10.15-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6a51a1dd4aa7b3f1317f65493a182d3cff708385327c1c82c81e4a9d6d65b2e4"},
|
||||
{file = "pydantic-1.10.15-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4e316e54b5775d1eb59187f9290aeb38acf620e10f7fd2f776d97bb788199e53"},
|
||||
{file = "pydantic-1.10.15-cp311-cp311-win_amd64.whl", hash = "sha256:0d142fa1b8f2f0ae11ddd5e3e317dcac060b951d605fda26ca9b234b92214986"},
|
||||
{file = "pydantic-1.10.15-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7ea210336b891f5ea334f8fc9f8f862b87acd5d4a0cbc9e3e208e7aa1775dabf"},
|
||||
{file = "pydantic-1.10.15-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3453685ccd7140715e05f2193d64030101eaad26076fad4e246c1cc97e1bb30d"},
|
||||
{file = "pydantic-1.10.15-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bea1f03b8d4e8e86702c918ccfd5d947ac268f0f0cc6ed71782e4b09353b26f"},
|
||||
{file = "pydantic-1.10.15-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:005655cabc29081de8243126e036f2065bd7ea5b9dff95fde6d2c642d39755de"},
|
||||
{file = "pydantic-1.10.15-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:af9850d98fc21e5bc24ea9e35dd80a29faf6462c608728a110c0a30b595e58b7"},
|
||||
{file = "pydantic-1.10.15-cp37-cp37m-win_amd64.whl", hash = "sha256:d31ee5b14a82c9afe2bd26aaa405293d4237d0591527d9129ce36e58f19f95c1"},
|
||||
{file = "pydantic-1.10.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5e09c19df304b8123938dc3c53d3d3be6ec74b9d7d0d80f4f4b5432ae16c2022"},
|
||||
{file = "pydantic-1.10.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7ac9237cd62947db00a0d16acf2f3e00d1ae9d3bd602b9c415f93e7a9fc10528"},
|
||||
{file = "pydantic-1.10.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:584f2d4c98ffec420e02305cf675857bae03c9d617fcfdc34946b1160213a948"},
|
||||
{file = "pydantic-1.10.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbc6989fad0c030bd70a0b6f626f98a862224bc2b1e36bfc531ea2facc0a340c"},
|
||||
{file = "pydantic-1.10.15-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d573082c6ef99336f2cb5b667b781d2f776d4af311574fb53d908517ba523c22"},
|
||||
{file = "pydantic-1.10.15-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6bd7030c9abc80134087d8b6e7aa957e43d35714daa116aced57269a445b8f7b"},
|
||||
{file = "pydantic-1.10.15-cp38-cp38-win_amd64.whl", hash = "sha256:3350f527bb04138f8aff932dc828f154847fbdc7a1a44c240fbfff1b57f49a12"},
|
||||
{file = "pydantic-1.10.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:51d405b42f1b86703555797270e4970a9f9bd7953f3990142e69d1037f9d9e51"},
|
||||
{file = "pydantic-1.10.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a980a77c52723b0dc56640ced396b73a024d4b74f02bcb2d21dbbac1debbe9d0"},
|
||||
{file = "pydantic-1.10.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67f1a1fb467d3f49e1708a3f632b11c69fccb4e748a325d5a491ddc7b5d22383"},
|
||||
{file = "pydantic-1.10.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:676ed48f2c5bbad835f1a8ed8a6d44c1cd5a21121116d2ac40bd1cd3619746ed"},
|
||||
{file = "pydantic-1.10.15-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:92229f73400b80c13afcd050687f4d7e88de9234d74b27e6728aa689abcf58cc"},
|
||||
{file = "pydantic-1.10.15-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2746189100c646682eff0bce95efa7d2e203420d8e1c613dc0c6b4c1d9c1fde4"},
|
||||
{file = "pydantic-1.10.15-cp39-cp39-win_amd64.whl", hash = "sha256:394f08750bd8eaad714718812e7fab615f873b3cdd0b9d84e76e51ef3b50b6b7"},
|
||||
{file = "pydantic-1.10.15-py3-none-any.whl", hash = "sha256:28e552a060ba2740d0d2aabe35162652c1459a0b9069fe0db7f4ee0e18e74d58"},
|
||||
{file = "pydantic-1.10.15.tar.gz", hash = "sha256:ca832e124eda231a60a041da4f013e3ff24949d94a01154b137fc2f2a43c3ffb"},
|
||||
{file = "pydantic-1.10.16-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1a539ac40551b01a85e899829aa43ca8036707474af8d74b48be288d4d2d2846"},
|
||||
{file = "pydantic-1.10.16-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a4fcc7b0b8038dbda2dda642cff024032dfae24a7960cc58e57a39eb1949b9b"},
|
||||
{file = "pydantic-1.10.16-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4660dd697de1ae2d4305a85161312611f64d5360663a9ba026cd6ad9e3fe14c3"},
|
||||
{file = "pydantic-1.10.16-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:900a787c574f903a97d0bf52a43ff3b6cf4fa0119674bcfc0e5fd1056d388ad9"},
|
||||
{file = "pydantic-1.10.16-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d30192a63e6d3334c3f0c0506dd6ae9f1dce7b2f8845518915291393a5707a22"},
|
||||
{file = "pydantic-1.10.16-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:16cf23ed599ca5ca937e37ba50ab114e6b5c387eb43a6cc533701605ad1be611"},
|
||||
{file = "pydantic-1.10.16-cp310-cp310-win_amd64.whl", hash = "sha256:8d23111f41d1e19334edd51438fd57933f3eee7d9d2fa8cc3f5eda515a272055"},
|
||||
{file = "pydantic-1.10.16-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef287b8d7fc0e86a8bd1f902c61aff6ba9479c50563242fe88ba39692e98e1e0"},
|
||||
{file = "pydantic-1.10.16-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b9ded699bfd3b3912d796ff388b0c607e6d35d41053d37aaf8fd6082c660de9a"},
|
||||
{file = "pydantic-1.10.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:daeb199814333e4426c5e86d7fb610f4e230289f28cab90eb4de27330bef93cf"},
|
||||
{file = "pydantic-1.10.16-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5973843f1fa99ec6c3ac8d1a8698ac9340b35e45cca6c3e5beb5c3bd1ef15de6"},
|
||||
{file = "pydantic-1.10.16-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6b8a7788a8528a558828fe4a48783cafdcf2612d13c491594a8161dc721629c"},
|
||||
{file = "pydantic-1.10.16-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8abaecf54dacc9d991dda93c3b880d41092a8924cde94eeb811d7d9ab55df7d8"},
|
||||
{file = "pydantic-1.10.16-cp311-cp311-win_amd64.whl", hash = "sha256:ddc7b682fbd23f051edc419dc6977e11dd2dbdd0cef9d05f0e15d1387862d230"},
|
||||
{file = "pydantic-1.10.16-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:067c2b5539f7839653ad8c3d1fc2f1343338da8677b7b2172abf3cd3fdc8f719"},
|
||||
{file = "pydantic-1.10.16-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d1fc943583c046ecad0ff5d6281ee571b64e11b5503d9595febdce54f38b290"},
|
||||
{file = "pydantic-1.10.16-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18548b30ccebe71d380b0886cc44ea5d80afbcc155e3518792f13677ad06097d"},
|
||||
{file = "pydantic-1.10.16-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4e92292f9580fc5ea517618580fac24e9f6dc5657196e977c194a8e50e14f5a9"},
|
||||
{file = "pydantic-1.10.16-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5da8bc4bb4f85b8c97cc7f11141fddbbd29eb25e843672e5807e19cc3d7c1b7f"},
|
||||
{file = "pydantic-1.10.16-cp37-cp37m-win_amd64.whl", hash = "sha256:a04ee1ea34172b87707a6ecfcdb120d7656892206b7c4dbdb771a73e90179fcb"},
|
||||
{file = "pydantic-1.10.16-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4fa86469fd46e732242c7acb83282d33f83591a7e06f840481327d5bf6d96112"},
|
||||
{file = "pydantic-1.10.16-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:89c2783dc261726fe7a5ce1121bce29a2f7eb9b1e704c68df2b117604e3b346f"},
|
||||
{file = "pydantic-1.10.16-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78e59fa919fa7a192f423d190d8660c35dd444efa9216662273f36826765424b"},
|
||||
{file = "pydantic-1.10.16-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7e82a80068c77f4b074032e031e642530b6d45cb8121fc7c99faa31fb6c6b72"},
|
||||
{file = "pydantic-1.10.16-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d82d5956cee27a30e26a5b88d00a6a2a15a4855e13c9baf50175976de0dc282c"},
|
||||
{file = "pydantic-1.10.16-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b7b99424cc0970ff08deccb549b5a6ec1040c0b449eab91723e64df2bd8fdca"},
|
||||
{file = "pydantic-1.10.16-cp38-cp38-win_amd64.whl", hash = "sha256:d97a35e1ba59442775201657171f601a2879e63517a55862a51f8d67cdfc0017"},
|
||||
{file = "pydantic-1.10.16-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9d91f6866fd3e303c632207813ef6bc4d86055e21c5e5a0a311983a9ac5f0192"},
|
||||
{file = "pydantic-1.10.16-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d8d3c71d14c8bd26d2350c081908dbf59d5a6a8f9596d9ef2b09cc1e61c8662b"},
|
||||
{file = "pydantic-1.10.16-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b73e6386b439b4881d79244e9fc1e32d1e31e8d784673f5d58a000550c94a6c0"},
|
||||
{file = "pydantic-1.10.16-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f039881fb2ef86f6de6eacce6e71701b47500355738367413ccc1550b2a69cf"},
|
||||
{file = "pydantic-1.10.16-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3895ddb26f22bdddee7e49741486aa7b389258c6f6771943e87fc00eabd79134"},
|
||||
{file = "pydantic-1.10.16-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:55b945da2756b5cef93d792521ad0d457fdf2f69fd5a2d10a27513f5281717dd"},
|
||||
{file = "pydantic-1.10.16-cp39-cp39-win_amd64.whl", hash = "sha256:22dd265c77c3976a34be78409b128cb84629284dfd1b69d2fa1507a36f84dc8b"},
|
||||
{file = "pydantic-1.10.16-py3-none-any.whl", hash = "sha256:aa2774ba5412fd1c5cb890d08e8b0a3bb5765898913ba1f61a65a4810f03cf29"},
|
||||
{file = "pydantic-1.10.16.tar.gz", hash = "sha256:8bb388f6244809af69ee384900b10b677a69f1980fdc655ea419710cffcb5610"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1066,13 +1066,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.32.2"
|
||||
version = "2.32.3"
|
||||
description = "Python HTTP for Humans."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "requests-2.32.2-py3-none-any.whl", hash = "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"},
|
||||
{file = "requests-2.32.2.tar.gz", hash = "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289"},
|
||||
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
|
||||
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1087,13 +1087,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
||||
|
||||
[[package]]
|
||||
name = "requests-cache"
|
||||
version = "1.2.0"
|
||||
version = "1.2.1"
|
||||
description = "A persistent cache for python requests"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "requests_cache-1.2.0-py3-none-any.whl", hash = "sha256:490324301bf0cb924ff4e6324bd2613453e7e1f847353928b08adb0fdfb7f722"},
|
||||
{file = "requests_cache-1.2.0.tar.gz", hash = "sha256:db1c709ca343cc1cd5b6c8b1a5387298eceed02306a6040760db538c885e3838"},
|
||||
{file = "requests_cache-1.2.1-py3-none-any.whl", hash = "sha256:1285151cddf5331067baa82598afe2d47c7495a1334bfe7a7d329b43e9fd3603"},
|
||||
{file = "requests_cache-1.2.1.tar.gz", hash = "sha256:68abc986fdc5b8d0911318fbb5f7c80eebcd4d01bfacc6685ecf8876052511d1"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1134,18 +1134,18 @@ fixture = ["fixtures"]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "70.0.0"
|
||||
version = "70.1.0"
|
||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "setuptools-70.0.0-py3-none-any.whl", hash = "sha256:54faa7f2e8d2d11bcd2c07bed282eef1046b5c080d1c32add737d7b5817b1ad4"},
|
||||
{file = "setuptools-70.0.0.tar.gz", hash = "sha256:f211a66637b8fa059bb28183da127d4e86396c991a942b028c6650d4319c3fd0"},
|
||||
{file = "setuptools-70.1.0-py3-none-any.whl", hash = "sha256:d9b8b771455a97c8a9f3ab3448ebe0b29b5e105f1228bba41028be116985a267"},
|
||||
{file = "setuptools-70.1.0.tar.gz", hash = "sha256:01a1e793faa5bd89abc851fa15d0a0db26f160890c7102cd8dce643e886b47f5"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
||||
testing = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
||||
testing = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
@@ -1160,13 +1160,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "tenacity"
|
||||
version = "8.3.0"
|
||||
version = "8.4.1"
|
||||
description = "Retry code until it succeeds"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "tenacity-8.3.0-py3-none-any.whl", hash = "sha256:3649f6443dbc0d9b01b9d8020a9c4ec7a1ff5f6f3c6c8a036ef371f573fe9185"},
|
||||
{file = "tenacity-8.3.0.tar.gz", hash = "sha256:953d4e6ad24357bceffbc9707bc74349aca9d245f68eb65419cf0c249a1949a2"},
|
||||
{file = "tenacity-8.4.1-py3-none-any.whl", hash = "sha256:28522e692eda3e1b8f5e99c51464efcc0b9fc86933da92415168bc1c4e2308fa"},
|
||||
{file = "tenacity-8.4.1.tar.gz", hash = "sha256:54b1412b878ddf7e1f1577cd49527bad8cdef32421bd599beac0c6c3f10582fd"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -1186,13 +1186,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.11.0"
|
||||
version = "4.12.2"
|
||||
description = "Backported and Experimental Type Hints for Python 3.8+"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"},
|
||||
{file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"},
|
||||
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
|
||||
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1211,13 +1211,13 @@ six = "*"
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.2.1"
|
||||
version = "2.2.2"
|
||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
|
||||
{file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
|
||||
{file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
|
||||
{file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -1322,4 +1322,4 @@ files = [
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.9,<3.12"
|
||||
content-hash = "64a5d2e5e85ad74cbb53a4395ac422f44e923cbd418171327c4dc49f47167f74"
|
||||
content-hash = "912963301c039ac2f732e49803dddb895253a3f531d279fb210b45c6ea2e435a"
|
||||
|
||||
@@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.poetry]
|
||||
version = "0.6.2"
|
||||
version = "1.0.0"
|
||||
name = "source-snapchat-marketing"
|
||||
description = "Source implementation for Snapchat Marketing."
|
||||
authors = [ "Airbyte <contact@airbyte.io>",]
|
||||
@@ -17,7 +17,7 @@ include = "source_snapchat_marketing"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.9,<3.12"
|
||||
airbyte-cdk = "0.90.0"
|
||||
airbyte-cdk = "^1"
|
||||
|
||||
[tool.poetry.scripts]
|
||||
source-snapchat-marketing = "source_snapchat_marketing.run:run"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,79 +0,0 @@
|
||||
{
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "The unique identifier for the ad account.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"updated_at": {
|
||||
"description": "The timestamp when the ad account details were last updated.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"created_at": {
|
||||
"description": "The timestamp when the ad account was created.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"name": {
|
||||
"description": "The name or title of the ad account.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"type": {
|
||||
"description": "The type or category of the ad account.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"status": {
|
||||
"description": "The current status or state of the ad account.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"organization_id": {
|
||||
"description": "The ID of the organization that owns the ad account.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"funding_source_ids": {
|
||||
"description": "IDs of the funding sources linked to the ad account.",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"description": "Individual funding source ID.",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
},
|
||||
"currency": {
|
||||
"description": "The currency used for financial transactions within the ad account.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"timezone": {
|
||||
"description": "The timezone setting for the ad account operations.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"advertiser_organization_id": {
|
||||
"description": "The ID of the organization that is advertising on the platform.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"billing_center_id": {
|
||||
"description": "The ID of the billing center associated with the ad account.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"billing_type": {
|
||||
"description": "The type of billing arrangement for the ad account.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"agency_representing_client": {
|
||||
"description": "The agency representing the client for ad account management.",
|
||||
"type": ["null", "boolean"]
|
||||
},
|
||||
"client_paying_invoices": {
|
||||
"description": "Indicates if the client is responsible for paying the invoices.",
|
||||
"type": ["null", "boolean"]
|
||||
},
|
||||
"regulations": {
|
||||
"description": "Regulatory information associated with the ad account.",
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"restricted_delivery_signals": {
|
||||
"description": "Signals or content types subject to delivery restrictions.",
|
||||
"type": ["null", "boolean"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
{
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "The unique identifier of the ad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"updated_at": {
|
||||
"description": "The date and time when the ad was last updated.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"created_at": {
|
||||
"description": "The date and time when the ad was created.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"name": {
|
||||
"description": "The name or title of the ad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"ad_squad_id": {
|
||||
"description": "The unique identifier of the ad squad this ad belongs to.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"creative_id": {
|
||||
"description": "The unique identifier of the creative content used in the ad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"status": {
|
||||
"description": "The current status of the ad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"type": {
|
||||
"description": "The type or category of the ad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"render_type": {
|
||||
"description": "The type of rendering used for the ad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"review_status": {
|
||||
"description": "The review status of the ad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"review_status_reasons": {
|
||||
"description": "Reasons for the review status of the ad.",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
},
|
||||
"delivery_status": {
|
||||
"description": "The delivery status of the ad.",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,263 +0,0 @@
|
||||
{
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "Unique identifier for the ad squad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"updated_at": {
|
||||
"description": "Timestamp indicating when the ad squad was last updated.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"created_at": {
|
||||
"description": "Timestamp indicating when the ad squad was created.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"name": {
|
||||
"description": "Name of the ad squad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"status": {
|
||||
"description": "Current status of the ad squad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"campaign_id": {
|
||||
"description": "ID of the campaign associated with the ad squad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"type": {
|
||||
"description": "Type of the ad squad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"targeting": {
|
||||
"description": "Targeting settings for the ad squad.",
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"regulated_content": {
|
||||
"description": "Indicates whether regulated content targeting is enabled.",
|
||||
"type": ["null", "boolean"]
|
||||
},
|
||||
"geos": {
|
||||
"description": "Geographic targeting criteria.",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"description": "Individual geographic item.",
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"country_code": {
|
||||
"description": "Country code for geographic targeting.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"operation": {
|
||||
"description": "Operation applied for geographic targeting.",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"locations": {
|
||||
"description": "Location targeting criteria.",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"description": "Individual location item.",
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"circles": {
|
||||
"description": "Circular location details.",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"description": "Individual circle item.",
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"latitude": {
|
||||
"description": "Latitude coordinate of the circle center.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"longitude": {
|
||||
"description": "Longitude coordinate of the circle center.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"name": {
|
||||
"description": "Name of the circle location.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"radius": {
|
||||
"description": "Radius of the circle in specified unit.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"unit": {
|
||||
"description": "Unit used to measure the radius of the circle.",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"operation": {
|
||||
"description": "Operation applied for location targeting.",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"auto_expansion_options": {
|
||||
"description": "Options for automatic expansion in targeting.",
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"interest_expansion_option": {
|
||||
"description": "Settings for interest expansion option.",
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Indicates whether interest expansion is enabled.",
|
||||
"type": ["null", "boolean"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"enable_targeting_expansion": {
|
||||
"description": "Option to enable targeting expansion.",
|
||||
"type": ["null", "boolean"]
|
||||
},
|
||||
"interests": {
|
||||
"description": "Interest targeting criteria.",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"description": "Individual interest item.",
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"category_id": {
|
||||
"description": "Category ID for interest targeting.",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"description": "Individual category ID item.",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
},
|
||||
"operation": {
|
||||
"description": "Operation applied for interest targeting.",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"demographics": {
|
||||
"description": "Demographic targeting criteria.",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"description": "Individual demographic item.",
|
||||
"type": ["null", "object"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"targeting_reach_status": {
|
||||
"description": "Status of targeting reach for the ad squad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"placement": {
|
||||
"description": "Ad placement settings for the ad squad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"billing_event": {
|
||||
"description": "Defines the billing event for the ad squad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"auto_bid": {
|
||||
"description": "Indicates whether the ad squad is using auto-bidding for its bids.",
|
||||
"type": ["null", "boolean"]
|
||||
},
|
||||
"target_bid": {
|
||||
"description": "Target bid value for the ad squad.",
|
||||
"type": ["null", "boolean"]
|
||||
},
|
||||
"bid_strategy": {
|
||||
"description": "Specifies the bidding strategy used by the ad squad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"daily_budget_micro": {
|
||||
"description": "Daily budget in micro currency units for the ad squad.",
|
||||
"type": ["null", "integer"]
|
||||
},
|
||||
"start_time": {
|
||||
"description": "Start time for the ad squad's run.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"optimization_goal": {
|
||||
"description": "Goal used for optimizing ad delivery.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"delivery_constraint": {
|
||||
"description": "Constraints applied to the delivery of the ad squad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"delivery_properties_version": {
|
||||
"description": "Version of delivery properties for the ad squad.",
|
||||
"type": ["null", "integer"]
|
||||
},
|
||||
"pacing_type": {
|
||||
"description": "Type of pacing applied to the ad squad's delivery.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"child_ad_type": {
|
||||
"description": "Type of child ads under the ad squad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"forced_view_setting": {
|
||||
"description": "Setting to force views for the ad squad.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"creation_state": {
|
||||
"description": "Current state of the ad squad creation process.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"delivery_status": {
|
||||
"description": "Status of ad delivery for the ad squad.",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"description": "Individual delivery status item.",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
},
|
||||
"event_sources": {
|
||||
"description": "Sources of events associated with the ad squad.",
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"PLACE": {
|
||||
"description": "Event source related to a specific place.",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"description": "Individual event source item.",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"skadnetwork_properties": {
|
||||
"description": "Properties related to SKAdNetwork integration for the ad squad.",
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"ecid_enrollment_status": {
|
||||
"description": "Status of ECID enrollment.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"enable_skoverlay": {
|
||||
"description": "Option to enable SKOverlay.",
|
||||
"type": ["null", "boolean"]
|
||||
},
|
||||
"status": {
|
||||
"description": "Current status of SKAdNetwork.",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"lifetime_budget_micro": {
|
||||
"description": "Total budget in micro currency units for the lifetime of the ad squad.",
|
||||
"type": ["null", "integer"]
|
||||
},
|
||||
"end_time": {
|
||||
"description": "End time for the ad squad's run.",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,307 +0,0 @@
|
||||
{
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "Identifier for the data entry.",
|
||||
"type": ["string"]
|
||||
},
|
||||
"type": {
|
||||
"description": "Type of data entry.",
|
||||
"type": ["string"]
|
||||
},
|
||||
"granularity": {
|
||||
"description": "Granularity of the data.",
|
||||
"type": ["string"]
|
||||
},
|
||||
"start_time": {
|
||||
"description": "Start time of the data snapshot.",
|
||||
"type": ["null", "string"],
|
||||
"format": "date-time"
|
||||
},
|
||||
"end_time": {
|
||||
"description": "End time of the data snapshot.",
|
||||
"type": ["null", "string"],
|
||||
"format": "date-time"
|
||||
},
|
||||
"android_installs": {
|
||||
"description": "Total number of installs on Android devices.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"attachment_avg_view_time_millis": {
|
||||
"description": "Average time in milliseconds a viewer spends viewing an attachment.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"attachment_impressions": {
|
||||
"description": "Total number of times an attachment is displayed to users.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"attachment_quartile_1": {
|
||||
"description": "First quartile of attachment viewing time.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"attachment_quartile_2": {
|
||||
"description": "Second quartile of attachment viewing time.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"attachment_quartile_3": {
|
||||
"description": "Third quartile of attachment viewing time.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"attachment_total_view_time_millis": {
|
||||
"description": "Total time in milliseconds viewers spend on attachment views.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"attachment_view_completion": {
|
||||
"description": "Percentage of attachment views that are completed.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"avg_screen_time_millis": {
|
||||
"description": "Average time in milliseconds users spent on the screen.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"avg_view_time_millis": {
|
||||
"description": "Average time in milliseconds viewers spend on viewing content.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"impressions": {
|
||||
"description": "Total number of impressions recorded.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"ios_installs": {
|
||||
"description": "Total number of installs on iOS devices.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"quartile_1": {
|
||||
"description": "First quartile of viewing time.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"quartile_2": {
|
||||
"description": "Second quartile of viewing time.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"quartile_3": {
|
||||
"description": "Third quartile of viewing time.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"screen_time_millis": {
|
||||
"description": "Total time in milliseconds users spend on the screen.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"spend": {
|
||||
"description": "Total spend for marketing activities.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"swipe_up_percent": {
|
||||
"description": "Percentage of users who swiped up.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"swipes": {
|
||||
"description": "Total number of swipe gestures.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"total_installs": {
|
||||
"description": "Total number of installations.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"video_views": {
|
||||
"description": "Total number of video views.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"video_views_time_based": {
|
||||
"description": "Video views based on time duration.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"video_views_15s": {
|
||||
"description": "Total number of video views that last at least 15 seconds.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"view_completion": {
|
||||
"description": "Percentage of views that are completed.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"view_time_millis": {
|
||||
"description": "Total time viewers spend on viewing content in milliseconds.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"paid_impressions": {
|
||||
"description": "Total number of impressions from paid sources.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"earned_impressions": {
|
||||
"description": "Imprressions earned through engagements.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"total_impressions": {
|
||||
"description": "Total number of impressions including earned and paid.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"play_time_millis": {
|
||||
"description": "Total time in milliseconds users spend playing content.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"shares": {
|
||||
"description": "Total number of content shares.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"saves": {
|
||||
"description": "Number of saves performed.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"native_leads": {
|
||||
"description": "Number of leads generated natively.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_purchases": {
|
||||
"description": "Number of total purchases made.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_purchases_value": {
|
||||
"description": "Total value of purchases made.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_save": {
|
||||
"description": "Number of saves performed.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_start_checkout": {
|
||||
"description": "Number of times checkout process is initiated.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_add_cart": {
|
||||
"description": "Conversion events where items are added to cart.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_view_content": {
|
||||
"description": "Number of content views.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_add_billing": {
|
||||
"description": "Conversion events where billing information is added.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_searches": {
|
||||
"description": "Number of search queries made.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_level_completes": {
|
||||
"description": "Number of game levels completed.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_app_opens": {
|
||||
"description": "Number of times the app is opened.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_page_views": {
|
||||
"description": "Total number of page views.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_subscribe": {
|
||||
"description": "Number of subscriptions made.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_ad_click": {
|
||||
"description": "Number of ad clicks recorded.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_ad_view": {
|
||||
"description": "Number of ad views.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_complete_tutorial": {
|
||||
"description": "Number of completed tutorials.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_invite": {
|
||||
"description": "Number of invitations sent by users.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_login": {
|
||||
"description": "Number of logins recorded.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_share": {
|
||||
"description": "Number of shares made.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_reserve": {
|
||||
"description": "Reserve conversion events.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_achievement_unlocked": {
|
||||
"description": "Number of times achievements are unlocked.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_add_to_wishlist": {
|
||||
"description": "Conversion events where items are added to the wishlist.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_spend_credits": {
|
||||
"description": "Total credits spent during conversion events.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_rate": {
|
||||
"description": "Rate of conversion events.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_start_trial": {
|
||||
"description": "Number of trials started.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"conversion_list_view": {
|
||||
"description": "Number of views on the list content.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"custom_event_1": {
|
||||
"description": "Custom event tracking 1.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"custom_event_2": {
|
||||
"description": "Custom event tracking 2.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"custom_event_3": {
|
||||
"description": "Custom event tracking 3.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"custom_event_4": {
|
||||
"description": "Custom event tracking 4.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"custom_event_5": {
|
||||
"description": "Custom event tracking 5.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"attachment_frequency": {
|
||||
"description": "Frequency of attachment views.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"attachment_uniques": {
|
||||
"description": "Unique viewers of attachments.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"frequency": {
|
||||
"description": "Frequency of events tracked.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"uniques": {
|
||||
"description": "Total unique events or users.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"total_reach": {
|
||||
"description": "Total reach including earned and paid.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"earned_reach": {
|
||||
"description": "Total reach earned through engagements.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"story_opens": {
|
||||
"description": "Total number of story opens.",
|
||||
"type": ["null", "number"]
|
||||
},
|
||||
"story_completes": {
|
||||
"description": "Total number of completed stories.",
|
||||
"type": ["null", "number"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
{
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "The unique identifier of the campaign.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"updated_at": {
|
||||
"description": "The timestamp indicating when the campaign was last updated.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"created_at": {
|
||||
"description": "The timestamp indicating when the campaign was created.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"name": {
|
||||
"description": "The name assigned to the campaign for easy identification.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"ad_account_id": {
|
||||
"description": "The unique identifier of the advertising account associated with the campaign.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"status": {
|
||||
"description": "The current status of the campaign (e.g., paused, active).",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"objective": {
|
||||
"description": "The primary goal or objective of the campaign.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"start_time": {
|
||||
"description": "The starting date and time for the campaign to begin running.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"buy_model": {
|
||||
"description": "The purchasing model used for the campaign (e.g., auction, reach and frequency).",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"delivery_status": {
|
||||
"description": "The status of campaign delivery.",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
},
|
||||
"creation_state": {
|
||||
"description": "The current state of the campaign creation process.",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
{
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "The unique identifier of the creative",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"updated_at": {
|
||||
"description": "The timestamp indicating when the creative was last updated",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"created_at": {
|
||||
"description": "The timestamp indicating when the creative was created",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"name": {
|
||||
"description": "The name or title given to the creative",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"ad_account_id": {
|
||||
"description": "The ID of the advertising account linked to the creative",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"type": {
|
||||
"description": "The type or category of the creative",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"packaging_status": {
|
||||
"description": "The status of the packaging for the creative",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"review_status": {
|
||||
"description": "The overall review status of the creative",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"review_status_details": {
|
||||
"description": "Additional details related to the review status",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"shareable": {
|
||||
"description": "Indicates if the creative is shareable",
|
||||
"type": ["null", "boolean"]
|
||||
},
|
||||
"forced_view_eligibility": {
|
||||
"description": "Whether the creative is eligible for forced views",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"headline": {
|
||||
"description": "The headline or title of the creative",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"brand_name": {
|
||||
"description": "The name of the brand associated with the creative",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"call_to_action": {
|
||||
"description": "The call to action prompt for the creative",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"render_type": {
|
||||
"description": "The type of rendering used for the creative",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"top_snap_media_id": {
|
||||
"description": "The ID of the media file for the top snap",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"top_snap_crop_position": {
|
||||
"description": "The crop position for the top snap of the creative",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"web_view_properties": {
|
||||
"description": "Properties related to the web view functionality when a user interacts with the ad.",
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"url": {
|
||||
"description": "The URL to be loaded in the web view",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"allow_snap_javascript_sdk": {
|
||||
"description": "Whether to allow the use of Snap JavaScript SDK in the web view",
|
||||
"type": ["null", "boolean"]
|
||||
},
|
||||
"use_immersive_mode": {
|
||||
"description": "Whether to use immersive mode in the web view",
|
||||
"type": ["null", "boolean"]
|
||||
},
|
||||
"deep_link_urls": {
|
||||
"description": "List of deep link URLs associated with the web view",
|
||||
"type": ["null", "array"]
|
||||
},
|
||||
"block_preload": {
|
||||
"description": "Indicates if preloading is blocked for the web view",
|
||||
"type": ["null", "boolean"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"ad_product": {
|
||||
"description": "The type of Snapchat advertising product used for the creative",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"ad_to_place_properties": {
|
||||
"description": "Properties related to the ad to be displayed within the Snapchat interface.",
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"place_id": {
|
||||
"description": "The ID of the place where the ad is to be displayed",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
{
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "The unique identifier of the media.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"updated_at": {
|
||||
"description": "The timestamp when the media was last updated.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"created_at": {
|
||||
"description": "The timestamp when the media was created.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"ad_account_id": {
|
||||
"description": "The unique identifier of the ad account associated with the media.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"type": {
|
||||
"description": "The type of media (e.g., image, video).",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"media_status": {
|
||||
"description": "The status of the media (e.g., active, inactive).",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"media_usages": {
|
||||
"description": "Items associated with the media usage.",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"description": "Details of the media usage.",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
},
|
||||
"file_name": {
|
||||
"description": "The name of the media file.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"download_link": {
|
||||
"description": "The link to download the media file.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"duration_in_seconds": {
|
||||
"description": "The duration of the media in seconds.",
|
||||
"type": ["null", "number"],
|
||||
"multipleOf": 1e-10
|
||||
},
|
||||
"image_metadata": {
|
||||
"description": "Additional metadata related to the image media.",
|
||||
"type": ["null", "object"]
|
||||
},
|
||||
"video_metadata": {
|
||||
"description": "Additional metadata related to the video media.",
|
||||
"type": ["null", "object"]
|
||||
},
|
||||
"file_size_in_bytes": {
|
||||
"description": "The file size of the media in bytes.",
|
||||
"type": ["null", "integer"]
|
||||
},
|
||||
"is_demo_media": {
|
||||
"description": "Indicates if the media is a demo or not.",
|
||||
"type": ["null", "boolean"]
|
||||
},
|
||||
"hash": {
|
||||
"description": "The hash value of the media file for identification purposes.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"visibility": {
|
||||
"description": "The visibility settings of the media (e.g., public, private).",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"name": {
|
||||
"description": "The name or title of the media.",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
{
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "Unique identifier for the organization record.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"updated_at": {
|
||||
"description": "Timestamp indicating the last update date of the organization record.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"created_at": {
|
||||
"description": "Timestamp indicating the creation date of the organization record.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"name": {
|
||||
"description": "The name of the organization.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"country": {
|
||||
"description": "The country where the organization is located.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"postal_code": {
|
||||
"description": "The postal code of the organization's location.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"locality": {
|
||||
"description": "The locality or city where the organization is situated.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"contact_name": {
|
||||
"description": "The name of the contact person within the organization.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"contact_email": {
|
||||
"description": "The email address used for contact purposes.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"contact_phone": {
|
||||
"description": "The phone number of the contact person within the organization.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"address_line_1": {
|
||||
"description": "The first line of the organization's address.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"administrative_district_level_1": {
|
||||
"description": "The first-level administrative district of the organization's location.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"accepted_term_version": {
|
||||
"description": "The version of the terms and conditions accepted by the organization.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"contact_phone_optin": {
|
||||
"description": "Flag indicating if contact person has opted in for phone contact.",
|
||||
"type": ["null", "boolean"]
|
||||
},
|
||||
"configuration_settings": {
|
||||
"description": "Settings related to organization configurations",
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"notifications_enabled": {
|
||||
"description": "Flag indicating if notifications are enabled for the organization.",
|
||||
"type": ["null", "boolean"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"description": "The type or category of the organization.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"state": {
|
||||
"description": "The state or region where the organization is located.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"roles": {
|
||||
"description": "List of roles assigned to the organization.",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"description": "A specific role assigned to the organization.",
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
},
|
||||
"my_display_name": {
|
||||
"description": "The public display name of the organization.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"my_invited_email": {
|
||||
"description": "Email address of the member invited to the organization.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"my_member_id": {
|
||||
"description": "Unique identifier of the member within the organization.",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"createdByCaller": {
|
||||
"description": "Record of the creator of the organization within the system.",
|
||||
"type": ["null", "boolean"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
{
|
||||
"type": ["null", "object"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "Unique identifier for the segment",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"updated_at": {
|
||||
"description": "The date and time when the segment was last updated",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"created_at": {
|
||||
"description": "The date and time when the segment was created",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"name": {
|
||||
"description": "Name or title of the segment",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"ad_account_id": {
|
||||
"description": "The unique identifier for the ad account associated with the segment",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"organization_id": {
|
||||
"description": "Unique identifier for the organization to which the segment belongs",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"description": {
|
||||
"description": "Brief description of the segment",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"status": {
|
||||
"description": "Current status of the segment (e.g., active, inactive)",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"targetable_status": {
|
||||
"description": "Status indicating whether the segment can be targeted in marketing campaigns",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"upload_status": {
|
||||
"description": "Status of the segment upload process (e.g., pending, completed)",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"source_type": {
|
||||
"description": "Type of the source data used to create the segment",
|
||||
"type": ["null", "string"]
|
||||
},
|
||||
"retention_in_days": {
|
||||
"description": "Number of days for which the segment data is retained",
|
||||
"type": ["null", "integer"]
|
||||
},
|
||||
"approximate_number_users": {
|
||||
"description": "Approximate number of users within the segment",
|
||||
"type": ["null", "integer"]
|
||||
},
|
||||
"visible_to": {
|
||||
"description": "Visibility setting for the segment, determining who can access it",
|
||||
"type": ["null", "array"],
|
||||
"items": {
|
||||
"type": ["null", "string"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,826 +2,17 @@
|
||||
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
|
||||
#
|
||||
|
||||
import logging
|
||||
from abc import ABC, abstractmethod
|
||||
from enum import Enum
|
||||
from typing import Any, Iterable, List, Mapping, MutableMapping, Optional, Tuple
|
||||
from urllib.parse import parse_qsl, urlparse
|
||||
from airbyte_cdk.sources.declarative.yaml_declarative_source import YamlDeclarativeSource
|
||||
|
||||
import backoff
|
||||
import pendulum
|
||||
import requests
|
||||
from airbyte_cdk.models import SyncMode
|
||||
from airbyte_cdk.sources import AbstractSource
|
||||
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.requests_native_auth import Oauth2Authenticator
|
||||
from airbyte_cdk.sources.utils.schema_helpers import ResourceSchemaLoader
|
||||
"""
|
||||
This file provides the necessary constructs to interpret a provided declarative YAML configuration file into
|
||||
source connector.
|
||||
|
||||
# https://marketingapi.snapchat.com/docs/#core-metrics
|
||||
# https://marketingapi.snapchat.com/docs/#metrics-and-supported-granularities
|
||||
METRICS = [
|
||||
"android_installs",
|
||||
"attachment_avg_view_time_millis",
|
||||
"attachment_impressions",
|
||||
"attachment_quartile_1",
|
||||
"attachment_quartile_2",
|
||||
"attachment_quartile_3",
|
||||
"attachment_total_view_time_millis",
|
||||
"attachment_view_completion",
|
||||
"avg_screen_time_millis",
|
||||
"avg_view_time_millis",
|
||||
"impressions",
|
||||
"ios_installs",
|
||||
"quartile_1",
|
||||
"quartile_2",
|
||||
"quartile_3",
|
||||
"screen_time_millis",
|
||||
"spend",
|
||||
"swipe_up_percent",
|
||||
"swipes",
|
||||
"total_installs",
|
||||
"video_views",
|
||||
"video_views_time_based",
|
||||
"video_views_15s",
|
||||
"view_completion",
|
||||
"view_time_millis",
|
||||
"paid_impressions",
|
||||
"earned_impressions",
|
||||
"total_impressions",
|
||||
"play_time_millis",
|
||||
"shares",
|
||||
"saves",
|
||||
"native_leads",
|
||||
"conversion_purchases",
|
||||
"conversion_purchases_value",
|
||||
"conversion_save",
|
||||
"conversion_start_checkout",
|
||||
"conversion_add_cart",
|
||||
"conversion_view_content",
|
||||
"conversion_add_billing",
|
||||
# 'conversion_signups', # Invalid query parameters in request URL
|
||||
"conversion_searches",
|
||||
"conversion_level_completes",
|
||||
"conversion_app_opens",
|
||||
"conversion_page_views",
|
||||
"conversion_subscribe",
|
||||
"conversion_ad_click",
|
||||
"conversion_ad_view",
|
||||
"conversion_complete_tutorial",
|
||||
"conversion_invite",
|
||||
"conversion_login",
|
||||
"conversion_share",
|
||||
"conversion_reserve",
|
||||
"conversion_achievement_unlocked",
|
||||
"conversion_add_to_wishlist",
|
||||
"conversion_spend_credits",
|
||||
"conversion_rate",
|
||||
"conversion_start_trial",
|
||||
"conversion_list_view",
|
||||
"custom_event_1",
|
||||
"custom_event_2",
|
||||
"custom_event_3",
|
||||
"custom_event_4",
|
||||
"custom_event_5",
|
||||
"story_opens",
|
||||
"story_completes",
|
||||
]
|
||||
WARNING: Do not modify this file.
|
||||
"""
|
||||
|
||||
METRICS_NOT_HOURLY = [
|
||||
"attachment_frequency",
|
||||
"attachment_uniques",
|
||||
"frequency",
|
||||
"uniques",
|
||||
"total_reach",
|
||||
"earned_reach",
|
||||
]
|
||||
|
||||
logger = logging.getLogger("airbyte")
|
||||
|
||||
|
||||
class GranularityType(Enum):
|
||||
HOUR = "HOUR"
|
||||
DAY = "DAY"
|
||||
LIFETIME = "LIFETIME"
|
||||
|
||||
|
||||
# See the get_parent_ids function explanation
|
||||
# Long story short - used as cache for ids of higher level streams, that is used
|
||||
# as path variables in other streams. And to avoid requesting those ids for every stream
|
||||
# we put them to a dict and check if they exist on stream calling
|
||||
# The structure be like:
|
||||
# {
|
||||
# 'Organizations': [
|
||||
# {'organization_id': '7f064d90-52a1-some-uuid'}
|
||||
# ],
|
||||
# 'Adaccounts': [
|
||||
# {'ad_account_id': '04214c00-3aa5-some-uuid'},
|
||||
# {'ad_account_id': 'e4cd371b-8de8-some-uuid'}
|
||||
# ]
|
||||
# }
|
||||
#
|
||||
auxiliary_id_map = {}
|
||||
|
||||
|
||||
class SnapchatMarketingException(Exception):
|
||||
"""Just for formatting the exception as SnapchatMarketing"""
|
||||
|
||||
|
||||
def get_parent_ids(parent) -> List:
|
||||
"""Return record ids from <parent> stream full_refresh sync, example:
|
||||
[{'id': record_1['id']}, {'id': record_2['id']}, ... {'id': record_N['id']}]
|
||||
|
||||
Function uses global cache 'auxiliary_id_map' to save results of parent syncs.
|
||||
It prevents multiple actual syncs of the same basic streams like organizations, adacounts etc
|
||||
|
||||
:param parent: instance of stream class from what we need to retrieve ids
|
||||
:returns: empty list in case no ids of the stream was found or list with {'id': id}
|
||||
"""
|
||||
|
||||
# return cached data if it has been already extracted
|
||||
if parent.name in auxiliary_id_map:
|
||||
return auxiliary_id_map[parent.name]
|
||||
|
||||
parent_ids = []
|
||||
|
||||
# Run actual sync for parent stream
|
||||
parent_stream_slices = parent.stream_slices(sync_mode=SyncMode.full_refresh)
|
||||
for parent_stream_slice in parent_stream_slices:
|
||||
records = parent.read_records(sync_mode=SyncMode.full_refresh, stream_slice=parent_stream_slice)
|
||||
for record in records:
|
||||
parent_ids.append({"id": record["id"]})
|
||||
|
||||
# add data to cache to prevent further actual syncs of the same streams. (they always return the same data)
|
||||
auxiliary_id_map[parent.name] = parent_ids
|
||||
|
||||
return parent_ids
|
||||
|
||||
|
||||
class SnapchatMarketingStream(HttpStream, ABC):
|
||||
url_base = "https://adsapi.snapchat.com/v1/"
|
||||
primary_key = "id"
|
||||
raise_on_http_errors = True
|
||||
|
||||
def __init__(self, start_date, end_date, action_report_time, swipe_up_attribution_window, view_attribution_window, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.start_date = start_date
|
||||
self.end_date = end_date
|
||||
self.action_report_time = action_report_time
|
||||
self.swipe_up_attribution_window = swipe_up_attribution_window
|
||||
self.view_attribution_window = view_attribution_window
|
||||
|
||||
def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]:
|
||||
next_page_cursor = response.json().get("paging", False)
|
||||
if next_page_cursor:
|
||||
return {"cursor": dict(parse_qsl(urlparse(next_page_cursor["next_link"]).query))["cursor"]}
|
||||
|
||||
def request_params(
|
||||
self, stream_state: Mapping[str, Any], stream_slice: Mapping[str, any] = None, next_page_token: Mapping[str, Any] = None
|
||||
) -> MutableMapping[str, Any]:
|
||||
return next_page_token or {}
|
||||
|
||||
@property
|
||||
def response_root_name(self):
|
||||
"""Using the class name in lower to set the root node for response parsing"""
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def response_item_name(self):
|
||||
"""Remove last 's' from response_root_name, see example in parse_response function"""
|
||||
return self.response_root_name[:-1]
|
||||
|
||||
def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]:
|
||||
"""Response json came like
|
||||
{
|
||||
"organizations": [ <-- response_root_name
|
||||
{
|
||||
"organization": { <-- response_item_name
|
||||
"id": "some uuid",
|
||||
"updated_at": "2020-12-15T22:35:17.819Z",
|
||||
"created_at": "2020-12-15T11:13:03.910Z",
|
||||
... some_other_json_fields ...
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
So the response_root_name will be "organizations", and the response_item_name will be "organization"
|
||||
Also, the client side filtering for incremental sync is used
|
||||
"""
|
||||
|
||||
json_response = response.json().get(self.response_root_name, [])
|
||||
for resp in json_response:
|
||||
if self.response_item_name not in resp:
|
||||
error_text = f"stream {self.name}: field named '{self.response_item_name}' is absent in the response: {resp}"
|
||||
self.logger.error(error_text)
|
||||
raise SnapchatMarketingException(error_text)
|
||||
yield resp.get(self.response_item_name)
|
||||
|
||||
def should_retry(self, response: requests.Response) -> bool:
|
||||
if response.status_code == 403:
|
||||
setattr(self, "raise_on_http_errors", False)
|
||||
self.logger.warning(f"Got permission error when accessing URL {response.request.url}. " f"Skipping {self.name} stream.")
|
||||
return False
|
||||
return super().should_retry(response)
|
||||
|
||||
|
||||
class IncrementalSnapchatMarketingStream(SnapchatMarketingStream, ABC):
|
||||
cursor_field = "updated_at"
|
||||
|
||||
last_slice = None
|
||||
current_slice = None
|
||||
initial_state = None
|
||||
max_state = None
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def parent(self) -> SnapchatMarketingStream:
|
||||
"""Stream Class to extract entity ids from"""
|
||||
|
||||
def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str:
|
||||
return f"adaccounts/{stream_slice['id']}/{self.response_root_name}"
|
||||
|
||||
def stream_slices(self, **kwargs) -> Iterable[Optional[Mapping[str, Any]]]:
|
||||
|
||||
stream_state = kwargs.get("stream_state")
|
||||
self.initial_state = stream_state.get(self.cursor_field) if stream_state else self.start_date
|
||||
self.max_state = self.initial_state
|
||||
|
||||
parent_stream = self.parent(
|
||||
authenticator=self._session.auth,
|
||||
start_date=self.start_date,
|
||||
end_date=self.end_date,
|
||||
action_report_time=self.action_report_time,
|
||||
swipe_up_attribution_window=self.swipe_up_attribution_window,
|
||||
view_attribution_window=self.view_attribution_window,
|
||||
)
|
||||
stream_slices = get_parent_ids(parent_stream)
|
||||
|
||||
if stream_slices:
|
||||
self.last_slice = stream_slices[-1]
|
||||
|
||||
self.logger.info(f"{self.name} stream slices: {stream_slices}")
|
||||
|
||||
return stream_slices
|
||||
|
||||
def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]:
|
||||
"""
|
||||
Handle state value for streams with random order of cursor_field values.
|
||||
State with max value should be release only in last slice otherwise records
|
||||
from intermediate slices can be filtered out in 'read_records'
|
||||
"""
|
||||
|
||||
# store max state value across all records of all slices (parent ids) because
|
||||
# cursor_field values are random (not sorted) even within one slice (parent id)
|
||||
self.max_state = max(self.max_state, latest_record[self.cursor_field])
|
||||
|
||||
if self.current_slice == self.last_slice:
|
||||
# return max found state for last slice only
|
||||
return {self.cursor_field: self.max_state}
|
||||
else:
|
||||
# return release initial state until last slice is processed
|
||||
return {self.cursor_field: self.initial_state}
|
||||
|
||||
def read_records(
|
||||
self, stream_state: Mapping[str, Any] = None, stream_slice: Mapping[str, Any] = None, **kwargs
|
||||
) -> Iterable[Mapping[str, Any]]:
|
||||
"""
|
||||
This structure is used to set the class variable current_slice to the current stream slice for the
|
||||
purposes described above.
|
||||
Then all the retrieved records if the stream_state is present are filtered by the cursor_field value compared to the stream state
|
||||
This makes the incremental magic works
|
||||
"""
|
||||
self.current_slice = stream_slice
|
||||
records = super().read_records(stream_slice=stream_slice, stream_state=stream_state, **kwargs)
|
||||
if stream_state:
|
||||
for record in records:
|
||||
if record[self.cursor_field] > stream_state.get(self.cursor_field):
|
||||
yield record
|
||||
else:
|
||||
yield from records
|
||||
|
||||
|
||||
class Organizations(SnapchatMarketingStream):
|
||||
"""Docs: https://marketingapi.snapchat.com/docs/#organizations"""
|
||||
|
||||
def path(self, **kwargs) -> str:
|
||||
return "me/organizations"
|
||||
|
||||
|
||||
class Adaccounts(IncrementalSnapchatMarketingStream):
|
||||
"""Docs: https://marketingapi.snapchat.com/docs/#get-all-ad-accounts"""
|
||||
|
||||
parent = Organizations
|
||||
|
||||
def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str:
|
||||
return f"organizations/{stream_slice['id']}/adaccounts"
|
||||
|
||||
|
||||
class Creatives(IncrementalSnapchatMarketingStream):
|
||||
"""Docs: https://marketingapi.snapchat.com/docs/#get-all-creatives"""
|
||||
|
||||
parent = Adaccounts
|
||||
|
||||
|
||||
class Media(IncrementalSnapchatMarketingStream):
|
||||
"""Docs: https://marketingapi.snapchat.com/docs/#get-all-media"""
|
||||
|
||||
parent = Adaccounts
|
||||
|
||||
@property
|
||||
def response_item_name(self):
|
||||
return self.response_root_name
|
||||
|
||||
|
||||
class Campaigns(IncrementalSnapchatMarketingStream):
|
||||
"""Docs: https://marketingapi.snapchat.com/docs/#get-all-campaigns"""
|
||||
|
||||
parent = Adaccounts
|
||||
|
||||
|
||||
class Ads(IncrementalSnapchatMarketingStream):
|
||||
"""Docs: https://marketingapi.snapchat.com/docs/#get-all-ads-under-an-ad-account"""
|
||||
|
||||
parent = Adaccounts
|
||||
|
||||
|
||||
class Adsquads(IncrementalSnapchatMarketingStream):
|
||||
"""Docs: https://marketingapi.snapchat.com/docs/#get-all-ad-squads-under-an-ad-account"""
|
||||
|
||||
parent = Adaccounts
|
||||
|
||||
|
||||
class Segments(IncrementalSnapchatMarketingStream):
|
||||
"""Docs: https://marketingapi.snapchat.com/docs/#get-all-audience-segments"""
|
||||
|
||||
parent = Adaccounts
|
||||
|
||||
|
||||
class Stats(SnapchatMarketingStream, ABC):
|
||||
"""Stats streams for LIFETIME granularity.
|
||||
Docs: https://marketingapi.snapchat.com/docs/#measurement
|
||||
"""
|
||||
|
||||
primary_key = ["id", "granularity"]
|
||||
schema_name = "basic_stats"
|
||||
parent_name: str = "" # name of parent class
|
||||
response_root_name = "lifetime_stats"
|
||||
granularity = GranularityType.LIFETIME
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def parent(self) -> SnapchatMarketingStream:
|
||||
"""Stream Class to extract entity ids from"""
|
||||
|
||||
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._session.auth,
|
||||
start_date=self.start_date,
|
||||
end_date=self.end_date,
|
||||
action_report_time=self.action_report_time,
|
||||
swipe_up_attribution_window=self.swipe_up_attribution_window,
|
||||
view_attribution_window=self.view_attribution_window,
|
||||
)
|
||||
self.parent_name = parent_stream.name
|
||||
stream_slices = get_parent_ids(parent_stream)
|
||||
|
||||
if not stream_slices:
|
||||
self.logger.error(f"No {'id'}s found. {self.name} cannot be extracted without {'id'}.")
|
||||
|
||||
self.logger.info(f"Stats: stream_slices:{stream_slices}")
|
||||
|
||||
return stream_slices
|
||||
|
||||
def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str:
|
||||
return f"{self.parent_name}/{stream_slice['id']}/stats"
|
||||
|
||||
def request_params(
|
||||
self, stream_state: Mapping[str, Any], stream_slice: Mapping[str, any] = None, next_page_token: Mapping[str, Any] = None
|
||||
) -> MutableMapping[str, Any]:
|
||||
|
||||
params = super().request_params(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token)
|
||||
params["granularity"] = self.granularity.value
|
||||
params["action_report_time"] = self.action_report_time
|
||||
params["swipe_up_attribution_window"] = self.swipe_up_attribution_window
|
||||
params["view_attribution_window"] = self.view_attribution_window
|
||||
if self.metrics:
|
||||
params["fields"] = ",".join(self.metrics)
|
||||
|
||||
return params
|
||||
|
||||
def parse_response(
|
||||
self,
|
||||
response: requests.Response,
|
||||
*,
|
||||
stream_state: Mapping[str, Any],
|
||||
stream_slice: Mapping[str, Any] = None,
|
||||
next_page_token: Mapping[str, Any] = None,
|
||||
) -> Iterable[Mapping]:
|
||||
"""Customized by adding stream state setting"""
|
||||
|
||||
for record in super().parse_response(
|
||||
response=response, stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token
|
||||
):
|
||||
# move all 'stats' metrics to root level
|
||||
record.update(record.pop("stats", {}))
|
||||
|
||||
yield record
|
||||
|
||||
def get_json_schema(self) -> Mapping[str, Any]:
|
||||
"""All stats streams have same schema"""
|
||||
return ResourceSchemaLoader(package_name_from_class(self.__class__)).get_schema(self.schema_name)
|
||||
|
||||
|
||||
class StatsIncremental(Stats, IncrementalMixin):
|
||||
"""Incremental Stats class for Daily and Hourly streams which requires start/end date param"""
|
||||
|
||||
primary_key = ["id", "granularity", "start_time"]
|
||||
cursor_field: str = "start_time"
|
||||
slice_period: int = 7 # days https://marketingapi.snapchat.com/docs/#metrics-and-supported-granularities
|
||||
number_of_parent_ids: int = 0
|
||||
number_of_last_records: int = 0
|
||||
response_root_name = "timeseries_stats"
|
||||
response_subitem_name = "timeseries"
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self._state = {}
|
||||
|
||||
def date_slices(self, stream_state=None) -> Iterable[Optional[Mapping[str, Any]]]:
|
||||
date_slices = []
|
||||
# use start_date from state or from config
|
||||
start_date_str = stream_state.get(self.cursor_field) if stream_state else self.start_date
|
||||
slice_start_date = pendulum.parse(start_date_str)
|
||||
end_date = pendulum.parse(self.end_date)
|
||||
|
||||
while slice_start_date < end_date:
|
||||
slice_end_date_next = slice_start_date + pendulum.duration(days=self.slice_period)
|
||||
slice_end_date = min(slice_end_date_next, end_date)
|
||||
date_slices.append({"start_time": slice_start_date.to_date_string(), "end_time": slice_end_date.to_date_string()})
|
||||
slice_start_date = slice_end_date
|
||||
|
||||
self.logger.info(f"{self.name} stream date slices: {date_slices}.")
|
||||
|
||||
return date_slices
|
||||
|
||||
def stream_slices(self, stream_state: Mapping[str, Any] = None, **kwargs) -> Iterable[Optional[Mapping[str, Any]]]:
|
||||
"""Incremental stream slices is a combinations of date and parent id slices"""
|
||||
|
||||
stream_slices = []
|
||||
|
||||
parent_ids = super().stream_slices()
|
||||
|
||||
# save a number of parent ids we need to get stats for
|
||||
self.number_of_parent_ids = len(parent_ids)
|
||||
|
||||
# within each date period extract data for all parent_ids
|
||||
# it allows incremental sync implementation with slice period granularity
|
||||
for date_slice in self.date_slices(stream_state=stream_state):
|
||||
for parent_id in parent_ids:
|
||||
stream_slices.append({**date_slice, **parent_id})
|
||||
|
||||
self.logger.info(f"{self.name} stream slices: {stream_slices}")
|
||||
|
||||
return stream_slices
|
||||
|
||||
def request_params(
|
||||
self, stream_state: Mapping[str, Any], stream_slice: Mapping[str, any] = None, next_page_token: Mapping[str, Any] = None
|
||||
) -> MutableMapping[str, Any]:
|
||||
"""start/end date param should be set for Daily and Hourly streams"""
|
||||
|
||||
params = super().request_params(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token)
|
||||
params["start_time"] = stream_slice["start_time"]
|
||||
params["end_time"] = stream_slice["end_time"]
|
||||
return params
|
||||
|
||||
def update_state_after_last_record(self, record):
|
||||
"""Update state if last record has been read"""
|
||||
record_end_date = record.get("end_time", "").split("T")[0] # "2022-07-06T00:00:00.000-07:00" --> "2022-07-06"
|
||||
if record_end_date == self.end_date:
|
||||
self.number_of_last_records += 1
|
||||
# Update state if 'last' records for all dependant entities have been read
|
||||
if self.number_of_parent_ids == self.number_of_last_records:
|
||||
self.state = {self.cursor_field: record_end_date}
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self._state
|
||||
|
||||
@state.setter
|
||||
def state(self, value):
|
||||
self._state = value
|
||||
|
||||
def parse_response(
|
||||
self,
|
||||
response: requests.Response,
|
||||
*,
|
||||
stream_state: Mapping[str, Any],
|
||||
stream_slice: Mapping[str, Any] = None,
|
||||
next_page_token: Mapping[str, Any] = None,
|
||||
) -> Iterable[Mapping]:
|
||||
"""Customized by adding stream state setting"""
|
||||
|
||||
# Update state for each date slice (start_date), it ensures that previous date slices have been read
|
||||
# and can be skipped in next incremental sync
|
||||
self.state = {self.cursor_field: stream_slice[self.cursor_field]}
|
||||
|
||||
for record in super().parse_response(
|
||||
response=response, stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token
|
||||
):
|
||||
|
||||
record_identifiers = {
|
||||
"id": record["id"],
|
||||
"type": record["type"],
|
||||
"granularity": record["granularity"],
|
||||
}
|
||||
|
||||
# Hourly/Daily stats contains nested structure (under self.response_subitem_name) with actual stats items
|
||||
for stat_item in record.get(self.response_subitem_name, []):
|
||||
# add common record identifiers
|
||||
stat_item.update(record_identifiers)
|
||||
# move all 'stats' metrics to root level
|
||||
stat_item.update(stat_item.pop("stats", {}))
|
||||
|
||||
# Update state for last record in the stream
|
||||
self.update_state_after_last_record(stat_item)
|
||||
|
||||
yield stat_item
|
||||
|
||||
|
||||
class Granularity:
|
||||
granularity: GranularityType
|
||||
metrics = METRICS + METRICS_NOT_HOURLY
|
||||
|
||||
|
||||
class Lifetime(Granularity):
|
||||
"""Example of raw response:
|
||||
{
|
||||
"request_status": "SUCCESS",
|
||||
"request_id": "d0cb395f-c39d-480d-b62c-24878c7d0b76",
|
||||
"lifetime_stats": [{ <-- response_root_name
|
||||
"sub_request_status": "SUCCESS",
|
||||
"lifetime_stat": { <-- response_item_name
|
||||
"id": "96e5549f-4065-490e-93dd-ffb9f7973b77",
|
||||
"type": "AD",
|
||||
"granularity": "LIFETIME",
|
||||
"stats": {
|
||||
"impressions": 0,
|
||||
"swipes": 0,
|
||||
"quartile_1": 0,
|
||||
"quartile_2": 0,
|
||||
},
|
||||
"start_time": "2016-09-26T00:00:00.000-07:00",
|
||||
"end_time": "2022-07-01T07:00:00.000-07:00",
|
||||
"finalized_data_end_time": "2022-07-01T07:00:00.000-07:00",
|
||||
"conversion_data_processed_end_time": "2022-07-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
granularity = GranularityType.LIFETIME
|
||||
|
||||
|
||||
class Hourly(Granularity):
|
||||
"""Example of raw response:
|
||||
{
|
||||
"request_status": "SUCCESS",
|
||||
"request_id": "c106d757-7c07-4415-b62f-78108d9dc668",
|
||||
"timeseries_stats": [{ <-- response_root_name
|
||||
"sub_request_status": "SUCCESS",
|
||||
"timeseries_stat": { <-- response_item_name
|
||||
"id": "417d0269-80fb-496a-b5f3-ec0bac665144",
|
||||
"type": "AD",
|
||||
"granularity": "HOUR",
|
||||
"start_time": "2022-06-24T17:00:00.000-07:00",
|
||||
"end_time": "2022-06-28T17:00:00.000-07:00",
|
||||
"finalized_data_end_time": "2022-06-30T11:00:00.000-07:00",
|
||||
"conversion_data_processed_end_time": "2022-06-30T00:00:00.000Z",
|
||||
"timeseries": [{ <-- response_subitem_name
|
||||
"start_time": "2022-06-24T17:00:00.000-07:00",
|
||||
"end_time": "2022-06-24T18:00:00.000-07:00",
|
||||
"stats": {
|
||||
"impressions": 0,
|
||||
"swipes": 0,
|
||||
"quartile_1": 0,
|
||||
"quartile_2": 0,
|
||||
"quartile_3": 0,
|
||||
"view_completion": 0,
|
||||
}
|
||||
}, {
|
||||
"start_time": "2022-06-24T18:00:00.000-07:00",
|
||||
"end_time": "2022-06-24T19:00:00.000-07:00",
|
||||
"stats": {
|
||||
"impressions": 0,
|
||||
"swipes": 0,
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
granularity = GranularityType.HOUR
|
||||
metrics = METRICS
|
||||
slice_period = 7 # days https://marketingapi.snapchat.com/docs/#metrics-and-supported-granularities
|
||||
|
||||
|
||||
class Daily(Granularity):
|
||||
"""Example of raw response:
|
||||
{
|
||||
"request_status": "SUCCESS",
|
||||
"request_id": "f2cba857-e246-43bf-b644-1a0a540e1f92",
|
||||
"timeseries_stats": [{ <-- response_root_name
|
||||
"sub_request_status": "SUCCESS",
|
||||
"timeseries_stat": { <-- response_item_name
|
||||
"id": "417d0269-80fb-496a-b5f3-ec0bac665144",
|
||||
"type": "AD",
|
||||
"granularity": "DAY",
|
||||
"start_time": "2022-06-25T00:00:00.000-07:00",
|
||||
"end_time": "2022-06-29T00:00:00.000-07:00",
|
||||
"finalized_data_end_time": "2022-06-30T00:00:00.000-07:00",
|
||||
"conversion_data_processed_end_time": "2022-06-30T00:00:00.000Z",
|
||||
"timeseries": [{ <-- response_subitem_name
|
||||
"start_time": "2022-06-25T00:00:00.000-07:00",
|
||||
"end_time": "2022-06-26T00:00:00.000-07:00",
|
||||
"stats": {
|
||||
"impressions": 0,
|
||||
"swipes": 0,
|
||||
"quartile_1": 0,
|
||||
"quartile_2": 0,
|
||||
"quartile_3": 0,
|
||||
}
|
||||
}, {
|
||||
"start_time": "2022-06-26T00:00:00.000-07:00",
|
||||
"end_time": "2022-06-27T00:00:00.000-07:00",
|
||||
"stats": {
|
||||
"impressions": 0,
|
||||
"swipes": 0,
|
||||
"quartile_1": 0,
|
||||
"quartile_2": 0,
|
||||
"quartile_3": 0,
|
||||
},
|
||||
},
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
granularity = GranularityType.DAY
|
||||
slice_period = 31 # days https://marketingapi.snapchat.com/docs/#metrics-and-supported-granularities
|
||||
|
||||
|
||||
class AdaccountsStatsHourly(Hourly, StatsIncremental):
|
||||
"""Adaccounts stats with Hourly granularity: https://marketingapi.snapchat.com/docs/#get-ad-account-stats"""
|
||||
|
||||
parent = Adaccounts
|
||||
metrics = ["spend"]
|
||||
|
||||
|
||||
class AdaccountsStatsDaily(Daily, StatsIncremental):
|
||||
"""Adaccounts stats with Daily granularity: https://marketingapi.snapchat.com/docs/#get-ad-account-stats"""
|
||||
|
||||
parent = Adaccounts
|
||||
metrics = ["spend"]
|
||||
|
||||
|
||||
class AdaccountsStatsLifetime(Lifetime, Stats):
|
||||
"""Adaccounts stats with Lifetime granularity: https://marketingapi.snapchat.com/docs/#get-ad-account-stats"""
|
||||
|
||||
parent = Adaccounts
|
||||
metrics = ["spend"]
|
||||
|
||||
|
||||
class AdsStatsHourly(Hourly, StatsIncremental):
|
||||
"""Ads stats with Hourly granularity: https://marketingapi.snapchat.com/docs/#get-ad-stats"""
|
||||
|
||||
parent = Ads
|
||||
|
||||
|
||||
class AdsStatsDaily(Daily, StatsIncremental):
|
||||
"""Ads stats with Daily granularity: https://marketingapi.snapchat.com/docs/#get-ad-stats"""
|
||||
|
||||
parent = Ads
|
||||
|
||||
|
||||
class AdsStatsLifetime(Lifetime, Stats):
|
||||
"""Ads stats with Lifetime granularity: https://marketingapi.snapchat.com/docs/#get-ad-stats"""
|
||||
|
||||
parent = Ads
|
||||
|
||||
|
||||
class AdsquadsStatsHourly(Hourly, StatsIncremental):
|
||||
"""Adsquads stats with Hourly granularity: https://marketingapi.snapchat.com/docs/#get-ad-squad-stats"""
|
||||
|
||||
parent = Adsquads
|
||||
|
||||
|
||||
class AdsquadsStatsDaily(Daily, StatsIncremental):
|
||||
"""Adsquads stats with Daily granularity: https://marketingapi.snapchat.com/docs/#get-ad-squad-stats"""
|
||||
|
||||
parent = Adsquads
|
||||
|
||||
|
||||
class AdsquadsStatsLifetime(Lifetime, Stats):
|
||||
"""Adsquads stats with Lifetime granularity: https://marketingapi.snapchat.com/docs/#get-ad-squad-stats"""
|
||||
|
||||
parent = Adsquads
|
||||
|
||||
|
||||
class CampaignsStatsHourly(Hourly, StatsIncremental):
|
||||
"""Campaigns stats with Hourly granularity: https://marketingapi.snapchat.com/docs/#get-campaign-stats"""
|
||||
|
||||
parent = Campaigns
|
||||
|
||||
|
||||
class CampaignsStatsDaily(Daily, StatsIncremental):
|
||||
"""Campaigns stats with Daily granularity: https://marketingapi.snapchat.com/docs/#get-campaign-stats"""
|
||||
|
||||
parent = Campaigns
|
||||
|
||||
|
||||
class CampaignsStatsLifetime(Lifetime, Stats):
|
||||
"""Campaigns stats with Lifetime granularity: https://marketingapi.snapchat.com/docs/#get-campaign-stats"""
|
||||
|
||||
parent = Campaigns
|
||||
|
||||
|
||||
# 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 = Oauth2Authenticator(
|
||||
token_refresh_endpoint="https://accounts.snapchat.com/login/oauth2/access_token",
|
||||
client_id=config["client_id"],
|
||||
client_secret=config["client_secret"],
|
||||
refresh_token=config["refresh_token"],
|
||||
)
|
||||
token = auth.get_access_token()
|
||||
url = f"{SnapchatMarketingStream.url_base}me"
|
||||
|
||||
session = requests.get(url, headers={"Authorization": "Bearer {}".format(token)})
|
||||
session.raise_for_status()
|
||||
return True, None
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
return False, e
|
||||
|
||||
def streams(self, config: Mapping[str, Any]) -> List[Stream]:
|
||||
# https://marketingapi.snapchat.com/docs/#core-metrics
|
||||
# IMPORTANT: Metrics are finalized 48 hours after the end of the day in the Ad Account’s timezone.
|
||||
DELAYED_DAYS = 2
|
||||
|
||||
# Start/End dates should better be in YYYY-MM-DD format:
|
||||
# 1. minutes are not supported
|
||||
# 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": Oauth2Authenticator(
|
||||
token_refresh_endpoint="https://accounts.snapchat.com/login/oauth2/access_token",
|
||||
client_id=config["client_id"],
|
||||
client_secret=config["client_secret"],
|
||||
refresh_token=config["refresh_token"],
|
||||
),
|
||||
"start_date": config["start_date"],
|
||||
"end_date": config.get("end_date", default_end_date),
|
||||
"action_report_time": config.get("action_report_time", "conversion"),
|
||||
"swipe_up_attribution_window": config.get("swipe_up_attribution_window", "28_DAY"),
|
||||
"view_attribution_window": config.get("view_attribution_window", "1_DAY"),
|
||||
}
|
||||
|
||||
return [
|
||||
# Base streams:
|
||||
Adaccounts(**kwargs),
|
||||
Ads(**kwargs),
|
||||
Adsquads(**kwargs),
|
||||
Campaigns(**kwargs),
|
||||
Creatives(**kwargs),
|
||||
Media(**kwargs),
|
||||
Organizations(**kwargs),
|
||||
Segments(**kwargs),
|
||||
# Stats streams:
|
||||
AdaccountsStatsHourly(**kwargs),
|
||||
AdaccountsStatsDaily(**kwargs),
|
||||
AdaccountsStatsLifetime(**kwargs),
|
||||
AdsStatsHourly(**kwargs),
|
||||
AdsStatsDaily(**kwargs),
|
||||
AdsStatsLifetime(**kwargs),
|
||||
AdsquadsStatsHourly(**kwargs),
|
||||
AdsquadsStatsDaily(**kwargs),
|
||||
AdsquadsStatsLifetime(**kwargs),
|
||||
CampaignsStatsHourly(**kwargs),
|
||||
CampaignsStatsDaily(**kwargs),
|
||||
CampaignsStatsLifetime(**kwargs),
|
||||
]
|
||||
# Declarative Source
|
||||
class SourceSnapchatMarketing(YamlDeclarativeSource):
|
||||
def __init__(self):
|
||||
super().__init__(**{"path_to_yaml": "manifest.yaml"})
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
|
||||
#
|
||||
|
||||
from source_snapchat_marketing.source import SourceSnapchatMarketing
|
||||
|
||||
|
||||
def find_stream(stream_name, config):
|
||||
streams = SourceSnapchatMarketing().streams(config=config)
|
||||
|
||||
# cache should be disabled once this issue is fixed https://github.com/airbytehq/airbyte-internal-issues/issues/6513
|
||||
for stream in streams:
|
||||
stream.retriever.requester.use_cache = True
|
||||
|
||||
# find by name
|
||||
for stream in streams:
|
||||
if stream.name == stream_name:
|
||||
return stream
|
||||
raise ValueError(f"Stream {stream_name} not found")
|
||||
@@ -1,105 +1,63 @@
|
||||
#
|
||||
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
|
||||
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
|
||||
#
|
||||
|
||||
# from unittest.mock import MagicMock, PropertyMock, patch
|
||||
import json
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
import source_snapchat_marketing
|
||||
from airbyte_cdk.models import SyncMode
|
||||
from airbyte_cdk.sources.streams.http.auth import NoAuth
|
||||
from source_snapchat_marketing.source import (
|
||||
Adaccounts,
|
||||
AdaccountsStatsDaily,
|
||||
Ads,
|
||||
AdsStatsDaily,
|
||||
AdsStatsLifetime,
|
||||
Oauth2Authenticator,
|
||||
Organizations,
|
||||
SourceSnapchatMarketing,
|
||||
)
|
||||
from airbyte_cdk.sources.declarative.types import StreamSlice
|
||||
from airbyte_cdk.sources.streams.http.exceptions import DefaultBackoffException
|
||||
from conftest import find_stream
|
||||
from source_snapchat_marketing.source import SourceSnapchatMarketing
|
||||
|
||||
logger = logging.getLogger("airbyte_logger")
|
||||
|
||||
config_mock = {
|
||||
"authenticator": NoAuth(),
|
||||
"start_date": "2000-01-01",
|
||||
"end_date": "2000-02-10",
|
||||
"client_id": "client_id",
|
||||
"client_secret": "client_secret",
|
||||
"refresh_token": "refresh_token",
|
||||
"start_date": "2024-01-01",
|
||||
"end_date": "2024-02-10",
|
||||
"action_report_time": "impression",
|
||||
"swipe_up_attribution_window": "7_DAY",
|
||||
"view_attribution_window": "1_DAY",
|
||||
}
|
||||
stats_stream = AdaccountsStatsDaily(**config_mock)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"slice_period,expected_date_slices",
|
||||
[
|
||||
# for Hourly streams
|
||||
(
|
||||
7,
|
||||
[
|
||||
{"start_time": "2000-01-01", "end_time": "2000-01-08"},
|
||||
{"start_time": "2000-01-08", "end_time": "2000-01-15"},
|
||||
{"start_time": "2000-01-15", "end_time": "2000-01-22"},
|
||||
{"start_time": "2000-01-22", "end_time": "2000-01-29"},
|
||||
{"start_time": "2000-01-29", "end_time": "2000-02-05"},
|
||||
{"start_time": "2000-02-05", "end_time": "2000-02-10"},
|
||||
],
|
||||
),
|
||||
# for Daily streams
|
||||
(
|
||||
31,
|
||||
[
|
||||
{"start_time": "2000-01-01", "end_time": "2000-02-01"},
|
||||
{"start_time": "2000-02-01", "end_time": "2000-02-10"},
|
||||
],
|
||||
),
|
||||
# when start-end period == slice period
|
||||
(
|
||||
40,
|
||||
[
|
||||
{"start_time": "2000-01-01", "end_time": "2000-02-10"},
|
||||
],
|
||||
),
|
||||
# when start-end period > slice period
|
||||
(
|
||||
100,
|
||||
[
|
||||
{"start_time": "2000-01-01", "end_time": "2000-02-10"},
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_date_slices(slice_period, expected_date_slices):
|
||||
stats_stream.slice_period = slice_period
|
||||
date_slices = stats_stream.date_slices()
|
||||
assert date_slices == expected_date_slices
|
||||
|
||||
|
||||
response_organizations = {
|
||||
"organizations": [
|
||||
{
|
||||
"organization": {
|
||||
"id": "organization_id_1",
|
||||
"updated_at": "2020-12-15T22:35:17.819Z",
|
||||
"created_at": "2020-12-15T11:13:03.910Z",
|
||||
"updated_at": "2024-02-05T22:35:17.819Z",
|
||||
"created_at": "2024-02-05T11:13:03.910Z",
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def test_organizations(requests_mock):
|
||||
def test_should_retry_403_error(requests_mock):
|
||||
requests_mock.post("https://accounts.snapchat.com/login/oauth2/access_token", json={"access_token": "XXX", "expires_in": 3600})
|
||||
requests_mock.register_uri(
|
||||
"GET", "https://adsapi.snapchat.com/v1/me/organizations", [{"status_code": 403, "json": {"organizations": []}}]
|
||||
)
|
||||
stream = find_stream("organizations", config_mock)
|
||||
with pytest.raises(DefaultBackoffException):
|
||||
list(stream.read_records(sync_mode=SyncMode.full_refresh))
|
||||
|
||||
|
||||
def test_organizations(requests_mock):
|
||||
requests_mock.post("https://accounts.snapchat.com/login/oauth2/access_token", json={"access_token": "XXX", "expires_in": 3600})
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/me/organizations", json=response_organizations)
|
||||
stream = Organizations(**config_mock)
|
||||
records = stream.read_records(sync_mode=SyncMode.full_refresh)
|
||||
assert list(records) == [
|
||||
{
|
||||
"id": "organization_id_1",
|
||||
"updated_at": "2020-12-15T22:35:17.819Z",
|
||||
"created_at": "2020-12-15T11:13:03.910Z",
|
||||
}
|
||||
]
|
||||
stream = find_stream("organizations", config_mock)
|
||||
records = stream.read_records(sync_mode=SyncMode.full_refresh, stream_slice=StreamSlice(partition={},
|
||||
cursor_slice={"start_time": "2024-01-01",
|
||||
"end_time": "2024-01-01"}),
|
||||
stream_state=None)
|
||||
assert json.dumps(next(records).data, sort_keys=True) == json.dumps(
|
||||
{"id": "organization_id_1", "updated_at": "2024-02-05T22:35:17.819Z", "created_at": "2024-02-05T11:13:03.910Z"}, sort_keys=True)
|
||||
|
||||
|
||||
response_adaccounts = {
|
||||
@@ -107,15 +65,15 @@ response_adaccounts = {
|
||||
{
|
||||
"adaccount": {
|
||||
"id": "adaccount_id_1",
|
||||
"updated_at": "2020-12-15T22:35:17.819Z",
|
||||
"created_at": "2020-12-15T11:13:03.910Z",
|
||||
"updated_at": "2024-02-05T22:35:17.819Z",
|
||||
"created_at": "2024-02-05T11:13:03.910Z",
|
||||
}
|
||||
},
|
||||
{
|
||||
"adaccount": {
|
||||
"id": "adaccount_id_2",
|
||||
"updated_at": "2020-12-15T22:35:17.819Z",
|
||||
"created_at": "2020-12-15T11:13:03.910Z",
|
||||
"updated_at": "2024-02-05T22:35:17.819Z",
|
||||
"created_at": "2024-02-05T11:13:03.910Z",
|
||||
}
|
||||
},
|
||||
]
|
||||
@@ -129,22 +87,24 @@ def run_stream(stream):
|
||||
|
||||
|
||||
def test_accounts(requests_mock):
|
||||
requests_mock.post("https://accounts.snapchat.com/login/oauth2/access_token", json={"access_token": "XXX", "expires_in": 3600})
|
||||
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/me/organizations", json=response_organizations)
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/organizations/organization_id_1/adaccounts", json=response_adaccounts)
|
||||
|
||||
stream = Adaccounts(**config_mock)
|
||||
stream = find_stream("adaccounts", config_mock)
|
||||
records = run_stream(stream)
|
||||
assert list(records) == [
|
||||
list_records = [record.data for record in records]
|
||||
assert list_records == [
|
||||
{
|
||||
"id": "adaccount_id_1",
|
||||
"updated_at": "2020-12-15T22:35:17.819Z",
|
||||
"created_at": "2020-12-15T11:13:03.910Z",
|
||||
"updated_at": "2024-02-05T22:35:17.819Z",
|
||||
"created_at": "2024-02-05T11:13:03.910Z",
|
||||
},
|
||||
{
|
||||
"id": "adaccount_id_2",
|
||||
"updated_at": "2020-12-15T22:35:17.819Z",
|
||||
"created_at": "2020-12-15T11:13:03.910Z",
|
||||
"updated_at": "2024-02-05T22:35:17.819Z",
|
||||
"created_at": "2024-02-05T11:13:03.910Z",
|
||||
},
|
||||
]
|
||||
|
||||
@@ -154,15 +114,15 @@ response_ads = {
|
||||
{
|
||||
"ad": {
|
||||
"id": "ad_id_1",
|
||||
"updated_at": "2020-12-15T22:35:17.819Z",
|
||||
"created_at": "2020-12-15T11:13:03.910Z",
|
||||
"updated_at": "2024-02-05T22:35:17.819Z",
|
||||
"created_at": "2024-02-05T11:13:03.910Z",
|
||||
}
|
||||
},
|
||||
{
|
||||
"ad": {
|
||||
"id": "ad_id_2",
|
||||
"updated_at": "2020-12-15T22:35:17.819Z",
|
||||
"created_at": "2020-12-15T11:13:03.910Z",
|
||||
"updated_at": "2024-02-05T22:35:17.819Z",
|
||||
"created_at": "2024-02-05T11:13:03.910Z",
|
||||
}
|
||||
},
|
||||
]
|
||||
@@ -170,24 +130,26 @@ response_ads = {
|
||||
|
||||
|
||||
def test_ads(requests_mock):
|
||||
requests_mock.post("https://accounts.snapchat.com/login/oauth2/access_token", json={"access_token": "XXX", "expires_in": 3600})
|
||||
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/me/organizations", json=response_organizations)
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/organizations/organization_id_1/adaccounts", json=response_adaccounts)
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/adaccounts/adaccount_id_1/ads", json={"ads": []})
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/adaccounts/adaccount_id_2/ads", json=response_ads)
|
||||
|
||||
stream = Ads(**config_mock)
|
||||
stream = find_stream("ads", config_mock)
|
||||
records = run_stream(stream)
|
||||
assert list(records) == [
|
||||
list_records = [record.data for record in records]
|
||||
assert list_records == [
|
||||
{
|
||||
"id": "ad_id_1",
|
||||
"updated_at": "2020-12-15T22:35:17.819Z",
|
||||
"created_at": "2020-12-15T11:13:03.910Z",
|
||||
"updated_at": "2024-02-05T22:35:17.819Z",
|
||||
"created_at": "2024-02-05T11:13:03.910Z",
|
||||
},
|
||||
{
|
||||
"id": "ad_id_2",
|
||||
"updated_at": "2020-12-15T22:35:17.819Z",
|
||||
"created_at": "2020-12-15T11:13:03.910Z",
|
||||
"updated_at": "2024-02-05T22:35:17.819Z",
|
||||
"created_at": "2024-02-05T11:13:03.910Z",
|
||||
},
|
||||
]
|
||||
|
||||
@@ -215,7 +177,6 @@ response_ads_stats_lifetime_1 = {
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
response_ads_stats_lifetime_2 = {
|
||||
"request_status": "SUCCESS",
|
||||
"request_id": "d0cb395f-c39d-480d-b62c-24878c7d0b76",
|
||||
@@ -241,6 +202,7 @@ response_ads_stats_lifetime_2 = {
|
||||
|
||||
|
||||
def test_ads_stats_lifetime(requests_mock):
|
||||
requests_mock.post("https://accounts.snapchat.com/login/oauth2/access_token", json={"access_token": "XXX", "expires_in": 3600})
|
||||
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/me/organizations", json=response_organizations)
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/organizations/organization_id_1/adaccounts", json=response_adaccounts)
|
||||
@@ -249,31 +211,166 @@ def test_ads_stats_lifetime(requests_mock):
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/ads/ad_id_1/stats", json=response_ads_stats_lifetime_1)
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/ads/ad_id_2/stats", json=response_ads_stats_lifetime_2)
|
||||
|
||||
stream = AdsStatsLifetime(**config_mock)
|
||||
stream = find_stream("ads_stats_lifetime", config_mock)
|
||||
records = run_stream(stream)
|
||||
assert list(records) == [
|
||||
list_records = [record.data for record in records]
|
||||
assert list_records == [
|
||||
{
|
||||
"conversion_data_processed_end_time": "2022-07-01T00:00:00.000Z",
|
||||
"end_time": "2022-07-01T07:00:00.000-07:00",
|
||||
"finalized_data_end_time": "2022-07-01T07:00:00.000-07:00",
|
||||
"granularity": "LIFETIME",
|
||||
"id": "ad_id_1",
|
||||
"impressions": 0,
|
||||
"start_time": "2016-09-26T00:00:00.000-07:00",
|
||||
"swipes": 0,
|
||||
"type": "AD",
|
||||
},
|
||||
{
|
||||
"conversion_data_processed_end_time": "2022-07-01T00:00:00.000Z",
|
||||
"granularity": "LIFETIME",
|
||||
"start_time": "2016-09-26T00:00:00.000-07:00",
|
||||
"end_time": "2022-07-01T07:00:00.000-07:00",
|
||||
"finalized_data_end_time": "2022-07-01T07:00:00.000-07:00",
|
||||
"granularity": "LIFETIME",
|
||||
"id": "ad_id_2",
|
||||
"conversion_data_processed_end_time": "2022-07-01T00:00:00.000Z",
|
||||
"android_installs": None,
|
||||
"attachment_avg_view_time_millis": None,
|
||||
"attachment_impressions": None,
|
||||
"attachment_quartile_1": None,
|
||||
"attachment_quartile_2": None,
|
||||
"attachment_quartile_3": None,
|
||||
"attachment_total_view_time_millis": None,
|
||||
"attachment_view_completion": None,
|
||||
"avg_screen_time_millis": None,
|
||||
"avg_view_time_millis": None,
|
||||
"impressions": 0,
|
||||
"start_time": "2016-09-26T00:00:00.000-07:00",
|
||||
"ios_installs": None,
|
||||
"quartile_1": None,
|
||||
"quartile_2": None,
|
||||
"quartile_3": None,
|
||||
"screen_time_millis": None,
|
||||
"swipe_up_percent": None,
|
||||
"swipes": 0,
|
||||
"type": "AD",
|
||||
"total_installs": None,
|
||||
"video_views": None,
|
||||
"video_views_time_based": None,
|
||||
"video_views_15s": None,
|
||||
"view_completion": None,
|
||||
"view_time_millis": None,
|
||||
"paid_impressions": None,
|
||||
"earned_impressions": None,
|
||||
"total_impressions": None,
|
||||
"play_time_millis": None,
|
||||
"shares": None,
|
||||
"saves": None,
|
||||
"native_leads": None,
|
||||
"conversion_purchases": None,
|
||||
"conversion_purchases_value": None,
|
||||
"conversion_save": None,
|
||||
"conversion_start_checkout": None,
|
||||
"conversion_add_cart": None,
|
||||
"conversion_view_content": None,
|
||||
"conversion_add_billing": None,
|
||||
"conversion_searches": None,
|
||||
"conversion_level_completes": None,
|
||||
"conversion_app_opens": None,
|
||||
"conversion_page_views": None,
|
||||
"conversion_subscribe": None,
|
||||
"conversion_ad_click": None,
|
||||
"conversion_ad_view": None,
|
||||
"conversion_complete_tutorial": None,
|
||||
"conversion_invite": None,
|
||||
"conversion_login": None,
|
||||
"conversion_share": None,
|
||||
"conversion_reserve": None,
|
||||
"conversion_achievement_unlocked": None,
|
||||
"conversion_add_to_wishlist": None,
|
||||
"conversion_spend_credits": None,
|
||||
"conversion_rate": None,
|
||||
"conversion_start_trial": None,
|
||||
"conversion_list_view": None,
|
||||
"custom_event_1": None,
|
||||
"custom_event_2": None,
|
||||
"custom_event_3": None,
|
||||
"custom_event_4": None,
|
||||
"custom_event_5": None,
|
||||
"story_opens": None,
|
||||
"story_completes": None,
|
||||
"attachment_frequency": None,
|
||||
"attachment_uniques": None,
|
||||
"frequency": None,
|
||||
"uniques": None,
|
||||
"total_reach": None,
|
||||
"earned_reach": None
|
||||
},
|
||||
{
|
||||
"id": "ad_id_2",
|
||||
"type": "AD",
|
||||
"granularity": "LIFETIME",
|
||||
"start_time": "2016-09-26T00:00:00.000-07:00",
|
||||
"end_time": "2022-07-01T07:00:00.000-07:00",
|
||||
"finalized_data_end_time": "2022-07-01T07:00:00.000-07:00",
|
||||
"conversion_data_processed_end_time": "2022-07-01T00:00:00.000Z",
|
||||
"android_installs": None,
|
||||
"attachment_avg_view_time_millis": None,
|
||||
"attachment_impressions": None,
|
||||
"attachment_quartile_1": None,
|
||||
"attachment_quartile_2": None,
|
||||
"attachment_quartile_3": None,
|
||||
"attachment_total_view_time_millis": None,
|
||||
"attachment_view_completion": None,
|
||||
"avg_screen_time_millis": None,
|
||||
"avg_view_time_millis": None,
|
||||
"impressions": 0,
|
||||
"ios_installs": None,
|
||||
"quartile_1": None,
|
||||
"quartile_2": None,
|
||||
"quartile_3": None,
|
||||
"screen_time_millis": None,
|
||||
"swipe_up_percent": None,
|
||||
"swipes": 0,
|
||||
"total_installs": None,
|
||||
"video_views": None,
|
||||
"video_views_time_based": None,
|
||||
"video_views_15s": None,
|
||||
"view_completion": None,
|
||||
"view_time_millis": None,
|
||||
"paid_impressions": None,
|
||||
"earned_impressions": None,
|
||||
"total_impressions": None,
|
||||
"play_time_millis": None,
|
||||
"shares": None,
|
||||
"saves": None,
|
||||
"native_leads": None,
|
||||
"conversion_purchases": None,
|
||||
"conversion_purchases_value": None,
|
||||
"conversion_save": None,
|
||||
"conversion_start_checkout": None,
|
||||
"conversion_add_cart": None,
|
||||
"conversion_view_content": None,
|
||||
"conversion_add_billing": None,
|
||||
"conversion_searches": None,
|
||||
"conversion_level_completes": None,
|
||||
"conversion_app_opens": None,
|
||||
"conversion_page_views": None,
|
||||
"conversion_subscribe": None,
|
||||
"conversion_ad_click": None,
|
||||
"conversion_ad_view": None,
|
||||
"conversion_complete_tutorial": None,
|
||||
"conversion_invite": None,
|
||||
"conversion_login": None,
|
||||
"conversion_share": None,
|
||||
"conversion_reserve": None,
|
||||
"conversion_achievement_unlocked": None,
|
||||
"conversion_add_to_wishlist": None,
|
||||
"conversion_spend_credits": None,
|
||||
"conversion_rate": None,
|
||||
"conversion_start_trial": None,
|
||||
"conversion_list_view": None,
|
||||
"custom_event_1": None,
|
||||
"custom_event_2": None,
|
||||
"custom_event_3": None,
|
||||
"custom_event_4": None,
|
||||
"custom_event_5": None,
|
||||
"story_opens": None,
|
||||
"story_completes": None,
|
||||
"attachment_frequency": None,
|
||||
"attachment_uniques": None,
|
||||
"frequency": None,
|
||||
"uniques": None,
|
||||
"total_reach": None,
|
||||
"earned_reach": None
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -287,14 +384,14 @@ response_ads_stats_daily_1 = {
|
||||
"id": "417d0269-80fb-496a-b5f3-ec0bac665144",
|
||||
"type": "AD",
|
||||
"granularity": "DAY",
|
||||
"start_time": "2022-06-25T00:00:00.000-07:00",
|
||||
"end_time": "2022-06-29T00:00:00.000-07:00",
|
||||
"start_time": "2024-02-05T00:00:00.000-07:00",
|
||||
"end_time": "2024-02-08T00:00:00.000-07:00",
|
||||
"finalized_data_end_time": "2022-06-30T00:00:00.000-07:00",
|
||||
"conversion_data_processed_end_time": "2022-06-30T00:00:00.000Z",
|
||||
"timeseries": [
|
||||
{
|
||||
"start_time": "2022-06-25T00:00:00.000-07:00",
|
||||
"end_time": "2022-06-26T00:00:00.000-07:00",
|
||||
"start_time": "2024-02-05T00:00:00.000-07:00",
|
||||
"end_time": "2024-02-06T00:00:00.000-07:00",
|
||||
"stats": {
|
||||
"impressions": 0,
|
||||
"swipes": 0,
|
||||
@@ -304,8 +401,8 @@ response_ads_stats_daily_1 = {
|
||||
},
|
||||
},
|
||||
{
|
||||
"start_time": "2022-06-26T00:00:00.000-07:00",
|
||||
"end_time": "2022-06-27T00:00:00.000-07:00",
|
||||
"start_time": "2024-02-07T00:00:00.000-07:00",
|
||||
"end_time": "2024-02-08T00:00:00.000-07:00",
|
||||
"stats": {
|
||||
"impressions": 0,
|
||||
"swipes": 0,
|
||||
@@ -322,6 +419,7 @@ response_ads_stats_daily_1 = {
|
||||
|
||||
|
||||
def test_ads_stats_daily(requests_mock):
|
||||
requests_mock.post("https://accounts.snapchat.com/login/oauth2/access_token", json={"access_token": "XXX", "expires_in": 3600})
|
||||
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/me/organizations", json=response_organizations)
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/organizations/organization_id_1/adaccounts", json=response_adaccounts)
|
||||
@@ -330,36 +428,11 @@ def test_ads_stats_daily(requests_mock):
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/ads/ad_id_1/stats", json={"timeseries_stats": []})
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/ads/ad_id_2/stats", json=response_ads_stats_daily_1)
|
||||
|
||||
stream = AdsStatsDaily(**config_mock)
|
||||
stream = find_stream("ads_stats_daily", config_mock)
|
||||
records = run_stream(stream)
|
||||
assert len(list(records)) == 4 # 2 records for each of 2 slices
|
||||
|
||||
|
||||
def test_get_parent_ids(requests_mock):
|
||||
"""Test cache usage in get_parent_ids"""
|
||||
# nonlocal auxiliary_id_map
|
||||
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/me/organizations", json=response_organizations)
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/organizations/organization_id_1/adaccounts", json=response_adaccounts)
|
||||
|
||||
stream = Adaccounts(**config_mock)
|
||||
|
||||
# reset cache, it can be filled by calls in previous tests
|
||||
source_snapchat_marketing.source.auxiliary_id_map = {}
|
||||
|
||||
# 1st call
|
||||
list(run_stream(stream))
|
||||
# 1st request to organizations
|
||||
# 2nd request to adaccounts
|
||||
assert len(requests_mock.request_history) == 2
|
||||
|
||||
# 2nd call
|
||||
list(run_stream(stream))
|
||||
# request to organizations is skipped due to cache
|
||||
# 3rd request to adaccounts
|
||||
assert len(requests_mock.request_history) == 3
|
||||
|
||||
|
||||
def test_source_streams():
|
||||
source_config = {"client_id": "XXX", "client_secret": "XXX", "refresh_token": "XXX", "start_date": "2022-05-25"}
|
||||
streams = SourceSnapchatMarketing().streams(config=source_config)
|
||||
@@ -369,34 +442,7 @@ def test_source_streams():
|
||||
def test_source_check_connection(requests_mock):
|
||||
source_config = {"client_id": "XXX", "client_secret": "XXX", "refresh_token": "XXX", "start_date": "2022-05-25"}
|
||||
requests_mock.post("https://accounts.snapchat.com/login/oauth2/access_token", json={"access_token": "XXX", "expires_in": 3600})
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/me", json={})
|
||||
requests_mock.get("https://adsapi.snapchat.com/v1/me/organizations", json={})
|
||||
|
||||
results = SourceSnapchatMarketing().check_connection(logger=None, config=source_config)
|
||||
results = SourceSnapchatMarketing().check_connection(logger=logger, config=source_config)
|
||||
assert results == (True, None)
|
||||
|
||||
|
||||
def test_retry_get_access_token(requests_mock):
|
||||
requests_mock.register_uri(
|
||||
"POST",
|
||||
"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 = Oauth2Authenticator(
|
||||
token_refresh_endpoint="https://accounts.snapchat.com/login/oauth2/access_token",
|
||||
client_id="client_id",
|
||||
client_secret="client_secret",
|
||||
refresh_token="refresh_token",
|
||||
)
|
||||
token = auth.get_access_token()
|
||||
assert len(requests_mock.request_history) == 3
|
||||
assert token == "token"
|
||||
|
||||
|
||||
def test_should_retry_403_error(requests_mock):
|
||||
requests_mock.register_uri(
|
||||
"GET", "https://adsapi.snapchat.com/v1/me/organizations", [{"status_code": 403, "json": {"organizations": []}}]
|
||||
)
|
||||
stream = Organizations(**config_mock)
|
||||
records = list(stream.read_records(sync_mode=SyncMode.full_refresh))
|
||||
|
||||
assert not records
|
||||
|
||||
27
docs/integrations/sources/snapchat-marketing-migrations.md
Normal file
27
docs/integrations/sources/snapchat-marketing-migrations.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Snapchat Marketing Migration Guide
|
||||
|
||||
## Upgrading to 1.0.0
|
||||
|
||||
We're continuously striving to enhance the quality and reliability of our connectors at Airbyte.
|
||||
As part of our commitment to delivering exceptional service, we are transitioning Snapchat Marketing source from
|
||||
the Python Connector Development Kit (CDK) to our innovative low-code framework. This is part of a strategic move
|
||||
to streamline many processes across connectors, bolstering maintainability and freeing us to focus more of our efforts
|
||||
on improving the performance and features of our evolving platform and growing catalog. However, due to differences
|
||||
between the Python and low-code CDKs, this migration constitutes a breaking change.
|
||||
|
||||
To gracefully handle these changes for your existing connections, we highly recommend resetting your data before resuming your data syncs with the new version.
|
||||
|
||||
### Migration Steps
|
||||
|
||||
1. Select **Connections** in the main navbar.
|
||||
1. Select the connection(s) affected by the update.
|
||||
2. Select the **Schema** tab.
|
||||
3. Uncheck all streams except the affected ones.
|
||||
4. Select **Save changes** at the bottom of the page.
|
||||
5. Select the **Settings** tab.
|
||||
6. Press the **Clear your data** button.
|
||||
7. Return to the **Schema** tab.
|
||||
8. Check all your streams.
|
||||
9. Select **Sync now** to sync your data
|
||||
|
||||
For more information on resetting your data in Airbyte, see [this page](/operator-guides/clear).
|
||||
@@ -89,14 +89,14 @@ This page guides you through the process of setting up the Snapchat Marketing so
|
||||
## Supported streams and sync modes
|
||||
|
||||
| Stream | Incremental | Key |
|
||||
| :---------------------- | :---------- | ----------------------------------- |
|
||||
|:------------------------|:------------|-------------------------------------|
|
||||
| Adaccounts | Yes | "id" |
|
||||
| Ads | Yes | "id" |
|
||||
| Adsquads | Yes | "id" |
|
||||
| Campaigns | Yes | "id" |
|
||||
| Creatives | Yes | "id" |
|
||||
| Media | Yes | "id" |
|
||||
| Organizations | No | "id" |
|
||||
| Organizations | Yes | "id" |
|
||||
| Segments | Yes | "id" |
|
||||
| AdaccountsStatsHourly | Yes | ["id", "granularity", "start_time"] |
|
||||
| AdaccountsStatsDaily | Yes | ["id", "granularity", "start_time"] |
|
||||
@@ -123,8 +123,9 @@ Snapchat Marketing API has limitations to 1000 items per page.
|
||||
<summary>Expand to review</summary>
|
||||
|
||||
| Version | Date | Pull Request | Subject |
|
||||
| :------ | :--------- | :------------------------------------------------------- | :----------------------------------------------------------------------------- |
|
||||
| 0.6.2 | 2024-15-22 | [38574](https://github.com/airbytehq/airbyte/pull/38574) | Update authenticator package |
|
||||
|:--------|:-----------|:---------------------------------------------------------|:-------------------------------------------------------------------------------|
|
||||
| 1.0.0 | 2024-06-20 | [39507](https://github.com/airbytehq/airbyte/pull/39507) | Migrate to low-code CDK and add incremental functionality to `organizations` |
|
||||
| 0.6.2 | 2024-05-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` |
|
||||
|
||||
Reference in New Issue
Block a user