logos-sdk 0.0.25.dev10__tar.gz → 0.0.25.dev11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/PKG-INFO +10 -2
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/services/CampaignManager.py +58 -33
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/services/DV360.py +46 -23
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/services/Facebook.py +22 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/services/GoogleAds.py +42 -19
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/services/MerchantCenter.py +25 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/services/MicrosoftAdvertising.py +23 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/services/Sklik.py +15 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk.egg-info/PKG-INFO +10 -2
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/LICENSE +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/README.md +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/__init__.py +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/big_query/BigQuery.py +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/big_query/__init__.py +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/logging/LogosLogger.py +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/logging/__init__.py +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/services/Collabim.py +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/services/GoogleSheets.py +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/services/MarketMiner.py +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/services/__init__.py +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk.egg-info/SOURCES.txt +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk.egg-info/dependency_links.txt +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk.egg-info/requires.txt +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk.egg-info/top_level.txt +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/setup.cfg +0 -0
- {logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: logos-sdk
|
|
3
|
-
Version: 0.0.25.
|
|
3
|
+
Version: 0.0.25.dev11
|
|
4
4
|
Summary: SDK for Logos platform
|
|
5
5
|
Home-page: https://bitbucket.org/databy/logos-sdk-pip/src/master/
|
|
6
6
|
Author: Databy.io
|
|
@@ -19,6 +19,14 @@ Requires-Dist: httplib2
|
|
|
19
19
|
Requires-Dist: pandas
|
|
20
20
|
Requires-Dist: db-dtypes
|
|
21
21
|
Requires-Dist: numpy
|
|
22
|
+
Dynamic: author
|
|
23
|
+
Dynamic: author-email
|
|
24
|
+
Dynamic: classifier
|
|
25
|
+
Dynamic: description
|
|
26
|
+
Dynamic: description-content-type
|
|
27
|
+
Dynamic: home-page
|
|
28
|
+
Dynamic: requires-dist
|
|
29
|
+
Dynamic: summary
|
|
22
30
|
|
|
23
31
|
# Logos Software Development Kit
|
|
24
32
|
|
|
@@ -32,17 +32,18 @@ class CampaignManagerService:
|
|
|
32
32
|
self._QUERY_DIMENSION_VALUES = self._URL + "/query-dimension-values"
|
|
33
33
|
self._GET_ACCESSIBLE_PARENT_ACCOUNTS = self._URL + "/get-parent-accounts"
|
|
34
34
|
self._GET_ACCESSIBLE_ADVERTISERS = self._URL + "/get-advertisers"
|
|
35
|
+
self._GET_ACCOUNT_ACCESSIBILITY = self._URL + "/get-account-accessibility"
|
|
35
36
|
|
|
36
37
|
def create_report(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
self,
|
|
39
|
+
account_id: str,
|
|
40
|
+
name: str,
|
|
41
|
+
start_date: str,
|
|
42
|
+
end_date: str,
|
|
43
|
+
dimensions: list,
|
|
44
|
+
metrics_names: list,
|
|
45
|
+
dimension_filters: list,
|
|
46
|
+
secret_id: str,
|
|
46
47
|
) -> Dict:
|
|
47
48
|
"""
|
|
48
49
|
Method for creating a report in API and returning a dict containing its ID for further use
|
|
@@ -181,7 +182,7 @@ class CampaignManagerService:
|
|
|
181
182
|
raise CampaignManagerServiceException(response.content)
|
|
182
183
|
|
|
183
184
|
def check_report_ready_with_exponential_backoff(
|
|
184
|
-
|
|
185
|
+
self, report_id: str, file_id: str, secret_id: str, backoff_attempts: int = 10
|
|
185
186
|
) -> bool:
|
|
186
187
|
"""
|
|
187
188
|
Implements exponential backoff for pooling the API for readiness of the report, suggested in
|
|
@@ -196,7 +197,7 @@ class CampaignManagerService:
|
|
|
196
197
|
if self.check_report_ready(report_id, file_id, secret_id):
|
|
197
198
|
return True
|
|
198
199
|
else:
|
|
199
|
-
time.sleep((2**attempt) + randint(1, 20))
|
|
200
|
+
time.sleep((2 ** attempt) + randint(1, 20))
|
|
200
201
|
|
|
201
202
|
return False
|
|
202
203
|
|
|
@@ -290,14 +291,14 @@ class CampaignManagerService:
|
|
|
290
291
|
raise CampaignManagerServiceException(response.content)
|
|
291
292
|
|
|
292
293
|
def query_dimension_values(
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
294
|
+
self,
|
|
295
|
+
account_id: str,
|
|
296
|
+
secret_id: str,
|
|
297
|
+
dimension_name: str,
|
|
298
|
+
filters: List,
|
|
299
|
+
start_date: str,
|
|
300
|
+
end_date: int,
|
|
301
|
+
max_results: int = 100,
|
|
301
302
|
) -> List[Dict]:
|
|
302
303
|
"""
|
|
303
304
|
Retrieves values of selected dimensions for data filtered according to rules set in list of filters
|
|
@@ -348,16 +349,16 @@ class CampaignManagerService:
|
|
|
348
349
|
yield service_response["data"]["items"]
|
|
349
350
|
|
|
350
351
|
def create_and_get_report_results(
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
352
|
+
self,
|
|
353
|
+
account_id: str,
|
|
354
|
+
name: str,
|
|
355
|
+
start_date: str,
|
|
356
|
+
end_date: str,
|
|
357
|
+
dimensions: list,
|
|
358
|
+
metrics_names: list,
|
|
359
|
+
dimension_filters: list,
|
|
360
|
+
secret_id: str,
|
|
361
|
+
backoff_attempts: int,
|
|
361
362
|
) -> Dict:
|
|
362
363
|
"""
|
|
363
364
|
Method to create report, run it and fetch results in one go
|
|
@@ -380,10 +381,10 @@ class CampaignManagerService:
|
|
|
380
381
|
secret_id=secret_id,
|
|
381
382
|
)
|
|
382
383
|
if self.check_report_ready_with_exponential_backoff(
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
384
|
+
report_id=report["id"],
|
|
385
|
+
file_id=run_report["id"],
|
|
386
|
+
secret_id=secret_id,
|
|
387
|
+
backoff_attempts=backoff_attempts,
|
|
387
388
|
):
|
|
388
389
|
return self.get_report_results(
|
|
389
390
|
report_id=report["id"],
|
|
@@ -444,3 +445,27 @@ class CampaignManagerService:
|
|
|
444
445
|
return service_response["data"]
|
|
445
446
|
else:
|
|
446
447
|
raise CampaignManagerServiceException(response.content)
|
|
448
|
+
|
|
449
|
+
def get_account_accessibility(self, secret_id: str,account_id, advertiser_id: str) -> bool:
|
|
450
|
+
"""
|
|
451
|
+
Gets account accessibility
|
|
452
|
+
:param secret_id: The ID of the secret in secret manager
|
|
453
|
+
:param account_id: Account ID
|
|
454
|
+
:param advertiser_id: The ID of the advertiser.
|
|
455
|
+
:return: True if account has access
|
|
456
|
+
"""
|
|
457
|
+
body = {
|
|
458
|
+
"secret_id": secret_id,
|
|
459
|
+
"account_id": account_id,
|
|
460
|
+
"advertiser_id": advertiser_id
|
|
461
|
+
}
|
|
462
|
+
header = get_headers(self._GET_ACCOUNT_ACCESSIBILITY)
|
|
463
|
+
response = request(
|
|
464
|
+
"post", url=self._GET_ACCOUNT_ACCESSIBILITY, json=body, headers=header
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
if response.status_code == HTTPStatus.OK:
|
|
468
|
+
service_response = response.json()
|
|
469
|
+
return service_response["data"]
|
|
470
|
+
else:
|
|
471
|
+
raise CampaignManagerServiceException(response.content)
|
|
@@ -20,10 +20,10 @@ class DV360Service:
|
|
|
20
20
|
self._URL = url or os.environ.get("DV360_SERVICE_PATH")
|
|
21
21
|
self._LIST_LINE_ITEMS = self._URL + "/line-items"
|
|
22
22
|
self._BULK_LIST_LINE_ITEM_ASSIGNED_TARGETING_OPTIONS = (
|
|
23
|
-
|
|
23
|
+
self._URL + "/bulk-list-line-item-assigned-targeting-options"
|
|
24
24
|
)
|
|
25
25
|
self._BULK_EDIT_LINE_ITEM_ASSIGNED_TARGETING_OPTIONS = (
|
|
26
|
-
|
|
26
|
+
self._URL + "/bulk-edit-line-item-assigned-targeting-options"
|
|
27
27
|
)
|
|
28
28
|
self._CREATE_CHANNEL = self._URL + "/create-channel"
|
|
29
29
|
self._LIST_CHANNELS = self._URL + "/list-channels"
|
|
@@ -36,6 +36,7 @@ class DV360Service:
|
|
|
36
36
|
self._DELETE_QUERY = self._URL + "/delete-query"
|
|
37
37
|
self._GET_ACCESSIBLE_PARTNERS = self._URL + "/get-accessible-partners"
|
|
38
38
|
self._GET_ACCESSIBLE_ADVERTISERS = self._URL + "/get-accessible-advertisers"
|
|
39
|
+
self._GET_ACCOUNT_ACCESSIBILITY = self._URL + "/get-account-accessibility"
|
|
39
40
|
|
|
40
41
|
def list_line_items(self, advertiser_id, secret_id, filter_string=None):
|
|
41
42
|
"""
|
|
@@ -60,11 +61,11 @@ class DV360Service:
|
|
|
60
61
|
raise DV360ServiceException(response.content)
|
|
61
62
|
|
|
62
63
|
def bulk_list_line_item_assigned_targeting_options(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
self,
|
|
65
|
+
advertiser_id,
|
|
66
|
+
secret_id,
|
|
67
|
+
line_item_ids,
|
|
68
|
+
filter_string,
|
|
68
69
|
):
|
|
69
70
|
"""
|
|
70
71
|
Bulk lists targeting options under multiple line items
|
|
@@ -96,12 +97,12 @@ class DV360Service:
|
|
|
96
97
|
raise DV360ServiceException(response.content)
|
|
97
98
|
|
|
98
99
|
def bulk_edit_line_item_assigned_targeting_options(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
self,
|
|
101
|
+
advertiser_id,
|
|
102
|
+
secret_id,
|
|
103
|
+
line_item_ids,
|
|
104
|
+
delete_requests=None,
|
|
105
|
+
create_requests=None,
|
|
105
106
|
):
|
|
106
107
|
"""
|
|
107
108
|
Bulk edits targeting options under multiple line items
|
|
@@ -182,7 +183,7 @@ class DV360Service:
|
|
|
182
183
|
raise DV360ServiceException(response.content)
|
|
183
184
|
|
|
184
185
|
def list_channel_sites(
|
|
185
|
-
|
|
186
|
+
self, advertiser_id, secret_id, channel_id, filter_string=None
|
|
186
187
|
):
|
|
187
188
|
"""
|
|
188
189
|
Lists channels for advertiser
|
|
@@ -213,12 +214,12 @@ class DV360Service:
|
|
|
213
214
|
raise DV360ServiceException(response.content)
|
|
214
215
|
|
|
215
216
|
def bulk_edit_channels_sites(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
217
|
+
self,
|
|
218
|
+
advertiser_id,
|
|
219
|
+
secret_id,
|
|
220
|
+
channel_id,
|
|
221
|
+
deleted_sites=None,
|
|
222
|
+
created_sites=None,
|
|
222
223
|
):
|
|
223
224
|
"""
|
|
224
225
|
Bulk edits sites under a single channel
|
|
@@ -353,8 +354,30 @@ class DV360Service:
|
|
|
353
354
|
else:
|
|
354
355
|
raise DV360ServiceException(response.content)
|
|
355
356
|
|
|
357
|
+
def get_account_accessibility(self, secret_id: str, advertiser_id: str) -> bool:
|
|
358
|
+
"""
|
|
359
|
+
Gets account accessibility
|
|
360
|
+
:param secret_id: The ID of the secret in secret manager
|
|
361
|
+
:param advertiser_id: The ID of the advertiser.
|
|
362
|
+
:return: True if account has access
|
|
363
|
+
"""
|
|
364
|
+
body = {
|
|
365
|
+
"secret_id": secret_id,
|
|
366
|
+
"advertiser_id": advertiser_id
|
|
367
|
+
}
|
|
368
|
+
header = get_headers(self._GET_ACCOUNT_ACCESSIBILITY)
|
|
369
|
+
response = request(
|
|
370
|
+
"post", url=self._GET_ACCOUNT_ACCESSIBILITY, json=body, headers=header
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
if response.status_code == HTTPStatus.OK:
|
|
374
|
+
service_response = response.json()
|
|
375
|
+
return service_response["data"]
|
|
376
|
+
else:
|
|
377
|
+
raise DV360ServiceException(response.content)
|
|
378
|
+
|
|
356
379
|
def _check_report_ready_with_exponential_backoff(
|
|
357
|
-
|
|
380
|
+
self, secret_id: str, query_id: str, report_id: str, backoff_attempts: int = 10
|
|
358
381
|
) -> bool:
|
|
359
382
|
"""
|
|
360
383
|
Implements exponential backoff for pooling the API for readiness of the report, suggested in
|
|
@@ -370,7 +393,7 @@ class DV360Service:
|
|
|
370
393
|
elif state == "FAILED":
|
|
371
394
|
raise DV360ServiceException("Report failed to generate")
|
|
372
395
|
else:
|
|
373
|
-
sleep((2**attempt) + randint(1, 20))
|
|
396
|
+
sleep((2 ** attempt) + randint(1, 20))
|
|
374
397
|
|
|
375
398
|
return False
|
|
376
399
|
|
|
@@ -404,7 +427,7 @@ class DV360Service:
|
|
|
404
427
|
:return: The results
|
|
405
428
|
"""
|
|
406
429
|
if not self._check_report_ready_with_exponential_backoff(
|
|
407
|
-
|
|
430
|
+
secret_id, query_id, report_id
|
|
408
431
|
):
|
|
409
432
|
raise DV360ServiceException("Report did not generate in time")
|
|
410
433
|
|
|
@@ -27,6 +27,7 @@ class FacebookService:
|
|
|
27
27
|
self._FEED_ERRORS = self._URL + "/feed-errors"
|
|
28
28
|
self._FEED_ERRORS_REPORT_STATUS = self._URL + "/feed-errors-report-status"
|
|
29
29
|
self._FEED_ERRORS_REPORT = self._URL + "/feed-errors-report"
|
|
30
|
+
self._GET_ACCOUNT_ACCESSIBILITY = self._URL + "/get-account-accessibility"
|
|
30
31
|
|
|
31
32
|
def get_accessible_accounts(
|
|
32
33
|
self, secret_id: str, timeout: int = None
|
|
@@ -61,6 +62,27 @@ class FacebookService:
|
|
|
61
62
|
else:
|
|
62
63
|
raise FacebookServiceException(response.content)
|
|
63
64
|
|
|
65
|
+
def get_account_accessibility(self, secret_id: str, account_id: str) -> bool:
|
|
66
|
+
"""
|
|
67
|
+
Gets account accessibility
|
|
68
|
+
:param secret_id: The ID of the secret in secret manager
|
|
69
|
+
:param account_id: The ID of the account.
|
|
70
|
+
:return: True if account has access
|
|
71
|
+
"""
|
|
72
|
+
body = {
|
|
73
|
+
"secret_id": secret_id,
|
|
74
|
+
"account_id": account_id
|
|
75
|
+
}
|
|
76
|
+
header = get_headers(self._GET_ACCOUNT_ACCESSIBILITY)
|
|
77
|
+
response = request(
|
|
78
|
+
"post", url=self._GET_ACCOUNT_ACCESSIBILITY, json=body, headers=header
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
if response.status_code == HTTPStatus.OK:
|
|
82
|
+
service_response = response.json()
|
|
83
|
+
return service_response["data"]
|
|
84
|
+
else:
|
|
85
|
+
raise FacebookServiceException(response.content)
|
|
64
86
|
def get_insights(
|
|
65
87
|
self,
|
|
66
88
|
account_id: str,
|
|
@@ -22,6 +22,7 @@ class GoogleAdsService:
|
|
|
22
22
|
self._EXCLUDE_FOR_ACCOUNT = self._URL + "/exclude-for-account"
|
|
23
23
|
self._EXCLUDE_FOR_AD_GROUP = self._URL + "/exclude-for-ad-group"
|
|
24
24
|
self._GET_ACCESSIBLE_ACCOUNTS = self._URL + "/list-accessible-accounts"
|
|
25
|
+
self._GET_ACCOUNT_ACCESSIBILITY = self._URL + "/get-account-accessibility"
|
|
25
26
|
|
|
26
27
|
@staticmethod
|
|
27
28
|
def fetch_with_retry_on_timeout(url, json, headers):
|
|
@@ -29,7 +30,7 @@ class GoogleAdsService:
|
|
|
29
30
|
try:
|
|
30
31
|
return request("post", url, json=json, headers=headers, timeout=25)
|
|
31
32
|
except Timeout:
|
|
32
|
-
delay = 2 * (2**attempt) + random.randint(0, 9)
|
|
33
|
+
delay = 2 * (2 ** attempt) + random.randint(0, 9)
|
|
33
34
|
print(
|
|
34
35
|
f"there was a timeout when contacting the service, going to sleep for {delay} seconds"
|
|
35
36
|
)
|
|
@@ -38,10 +39,10 @@ class GoogleAdsService:
|
|
|
38
39
|
raise Exception("The service is not able to reply within 30 seconds.")
|
|
39
40
|
|
|
40
41
|
def search_stream(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
self,
|
|
43
|
+
query: str,
|
|
44
|
+
queried_account_id: str,
|
|
45
|
+
secret_id: str,
|
|
45
46
|
) -> List[Union[List, Dict]]:
|
|
46
47
|
"""
|
|
47
48
|
:param query Sql query for google ads. Best way to build it is https://developers.google.com/google-ads/api/fields/v14/accessible_bidding_strategy_query_builder
|
|
@@ -67,11 +68,11 @@ class GoogleAdsService:
|
|
|
67
68
|
raise GoogleAdsServiceException(response.content)
|
|
68
69
|
|
|
69
70
|
def search(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
self,
|
|
72
|
+
query: str,
|
|
73
|
+
queried_account_id: str,
|
|
74
|
+
secret_id: str,
|
|
75
|
+
page_size: int,
|
|
75
76
|
) -> List[Dict]:
|
|
76
77
|
"""
|
|
77
78
|
:param query Sql query for google ads. Best way to build it is https://developers.google.com/google-ads/api/fields/v14/accessible_bidding_strategy_query_builder
|
|
@@ -111,7 +112,7 @@ class GoogleAdsService:
|
|
|
111
112
|
yield service_response["data"]["results"]
|
|
112
113
|
|
|
113
114
|
def exclude_criterion_for_account(
|
|
114
|
-
|
|
115
|
+
self, client_id: str, exclusion_raw: List[str], mode: str, secret_id: str = None
|
|
115
116
|
) -> None:
|
|
116
117
|
"""
|
|
117
118
|
Excludes list of unwanted urls/YouTube channels for account with client_id
|
|
@@ -140,11 +141,11 @@ class GoogleAdsService:
|
|
|
140
141
|
raise GoogleAdsServiceException(response.content)
|
|
141
142
|
|
|
142
143
|
def exclude_criterion_for_ad_group(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
144
|
+
self,
|
|
145
|
+
client_id: str,
|
|
146
|
+
ad_group_id: str,
|
|
147
|
+
exclusion_raw: List[str],
|
|
148
|
+
secret_id: str = None,
|
|
148
149
|
) -> None:
|
|
149
150
|
"""
|
|
150
151
|
Excludes list of unwanted urls/YouTube channels for given ad_group with client_id
|
|
@@ -172,9 +173,9 @@ class GoogleAdsService:
|
|
|
172
173
|
raise GoogleAdsServiceException(response.content)
|
|
173
174
|
|
|
174
175
|
def get_accessible_accounts(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
176
|
+
self,
|
|
177
|
+
secret_id: str,
|
|
178
|
+
page_size: int = 1000,
|
|
178
179
|
) -> List[Dict]:
|
|
179
180
|
body = {
|
|
180
181
|
"secret_id": secret_id,
|
|
@@ -209,3 +210,25 @@ class GoogleAdsService:
|
|
|
209
210
|
all_results.extend(service_response["data"]["results"])
|
|
210
211
|
|
|
211
212
|
return all_results
|
|
213
|
+
|
|
214
|
+
def get_account_accessibility(self, secret_id: str, account_id: str) -> bool:
|
|
215
|
+
"""
|
|
216
|
+
Gets account accessibility
|
|
217
|
+
:param secret_id: The ID of the secret in secret manager
|
|
218
|
+
:param account_id: The ID of the account.
|
|
219
|
+
:return: True if account has access
|
|
220
|
+
"""
|
|
221
|
+
body = {
|
|
222
|
+
"secret_id": secret_id,
|
|
223
|
+
"account_id": account_id
|
|
224
|
+
}
|
|
225
|
+
header = get_headers(self._GET_ACCOUNT_ACCESSIBILITY)
|
|
226
|
+
response = request(
|
|
227
|
+
"post", url=self._GET_ACCOUNT_ACCESSIBILITY, json=body, headers=header
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
if response.status_code == HTTPStatus.OK:
|
|
231
|
+
service_response = response.json()
|
|
232
|
+
return service_response["data"]
|
|
233
|
+
else:
|
|
234
|
+
raise GoogleAdsServiceException(response.content)
|
|
@@ -15,6 +15,7 @@ class MerchantCenterService:
|
|
|
15
15
|
self._URL = url or os.environ.get("MERCHANT_CENTER_SERVICE_PATH")
|
|
16
16
|
self._LIST_ACCOUNTS = self._URL + "/account-service/accounts"
|
|
17
17
|
self._LIST_ACCESSIBLE_ACCOUNTS = self._URL + "/account-service/list-accessible-accounts"
|
|
18
|
+
self._GET_ACCOUNT_ACCESSIBILITY = self._URL + "/account-service/get-account-accessibility"
|
|
18
19
|
self._LIST_ACCOUNT_STATUSES = self._URL + "/account-service/account-statuses"
|
|
19
20
|
self._LIST_PRODUCTS = self._URL + "/product-service/products"
|
|
20
21
|
self._LIST_PRODUCT_STATUSES = self._URL + "/product-service/product-statuses"
|
|
@@ -199,3 +200,27 @@ class MerchantCenterService:
|
|
|
199
200
|
|
|
200
201
|
service_response = response.json()
|
|
201
202
|
yield service_response["data"]["results"]
|
|
203
|
+
|
|
204
|
+
def get_account_accessibility(self, secret_id: str,merchant_account_id:str, account_id: str) -> bool:
|
|
205
|
+
"""
|
|
206
|
+
Gets account accessibility
|
|
207
|
+
:param secret_id: The ID of the secret in secret manager
|
|
208
|
+
:param merchant_account_id: The ID of the managing account. This must be a multi-client account.
|
|
209
|
+
:param account_id: The ID of the account.
|
|
210
|
+
:return: True if account has access
|
|
211
|
+
"""
|
|
212
|
+
body = {
|
|
213
|
+
"secret_id": secret_id,
|
|
214
|
+
"merchant_account_id": merchant_account_id,
|
|
215
|
+
"account_id": account_id
|
|
216
|
+
}
|
|
217
|
+
header = get_headers(self._GET_ACCOUNT_ACCESSIBILITY)
|
|
218
|
+
response = request(
|
|
219
|
+
"post", url=self._GET_ACCOUNT_ACCESSIBILITY, json=body, headers=header
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
if response.status_code == HTTPStatus.OK:
|
|
223
|
+
service_response = response.json()
|
|
224
|
+
return service_response["data"]
|
|
225
|
+
else:
|
|
226
|
+
raise MerchantServiceException(response.content)
|
{logos_sdk-0.0.25.dev10 → logos_sdk-0.0.25.dev11}/logos_sdk/services/MicrosoftAdvertising.py
RENAMED
|
@@ -23,6 +23,7 @@ class MicrosoftAdvertising:
|
|
|
23
23
|
load_dotenv()
|
|
24
24
|
self._URL = url or os.environ.get("MICROSOFT_ADVERTISING_PATH")
|
|
25
25
|
self._GET_ACCESSIBLE_ACCOUNTS = self._URL + "/accessible-accounts"
|
|
26
|
+
self._GET_ACCOUNT_ACCESSIBILITY = self._URL + "/get-account-accessibility"
|
|
26
27
|
self._GET_DESTINATION_URL_REPORT = self._URL + "/destination-url-report"
|
|
27
28
|
self._GET_CAMPAIGN_PERFORMANCE_REPORT = self._URL + "/campaign-performance-report"
|
|
28
29
|
self._GET_GEOGRAPHIC_PERFORMANCE_REPORT = self._URL + "/geographic-performance-report"
|
|
@@ -226,3 +227,25 @@ class MicrosoftAdvertising:
|
|
|
226
227
|
return service_response["data"]
|
|
227
228
|
else:
|
|
228
229
|
raise MicrosoftAdvertisingException(response.content)
|
|
230
|
+
|
|
231
|
+
def get_account_accessibility(self, secret_id: str, account_id: str) -> bool:
|
|
232
|
+
"""
|
|
233
|
+
Gets account accessibility
|
|
234
|
+
:param secret_id: The ID of the secret in secret manager
|
|
235
|
+
:param account_id: The ID of the account in Microsoft Advertising
|
|
236
|
+
:return: True if account has access
|
|
237
|
+
"""
|
|
238
|
+
body = {
|
|
239
|
+
"secret_id": secret_id,
|
|
240
|
+
"account_id": account_id
|
|
241
|
+
}
|
|
242
|
+
header = get_headers(self._GET_ACCOUNT_ACCESSIBILITY)
|
|
243
|
+
response = request(
|
|
244
|
+
"post", url=self._GET_ACCOUNT_ACCESSIBILITY, json=body, headers=header
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
if response.status_code == HTTPStatus.OK:
|
|
248
|
+
service_response = response.json()
|
|
249
|
+
return service_response["data"]
|
|
250
|
+
else:
|
|
251
|
+
raise MicrosoftAdvertisingException(response.content)
|
|
@@ -434,3 +434,18 @@ class SklikService:
|
|
|
434
434
|
return service_response["data"]
|
|
435
435
|
else:
|
|
436
436
|
raise SklikServiceException(response.content)
|
|
437
|
+
|
|
438
|
+
def get_account_accessibility(self, secret_id: str, account_email: str) -> bool:
|
|
439
|
+
"""
|
|
440
|
+
Gets account accessibility
|
|
441
|
+
:param secret_id: The ID of the secret in secret manager
|
|
442
|
+
:param account_email: Account email to refers to Sklik accountId
|
|
443
|
+
:return: True if account has access
|
|
444
|
+
"""
|
|
445
|
+
body = {"account_email": account_email, "secret_id": secret_id}
|
|
446
|
+
response = execute_request("post", url=self._GET_SESSION, json=body)
|
|
447
|
+
if response.status_code == 200:
|
|
448
|
+
return True
|
|
449
|
+
if response.status_code == 401 or response.status_code == 403 or response.status_code == 404:
|
|
450
|
+
return False
|
|
451
|
+
raise SklikServiceException(response.content)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: logos-sdk
|
|
3
|
-
Version: 0.0.25.
|
|
3
|
+
Version: 0.0.25.dev11
|
|
4
4
|
Summary: SDK for Logos platform
|
|
5
5
|
Home-page: https://bitbucket.org/databy/logos-sdk-pip/src/master/
|
|
6
6
|
Author: Databy.io
|
|
@@ -19,6 +19,14 @@ Requires-Dist: httplib2
|
|
|
19
19
|
Requires-Dist: pandas
|
|
20
20
|
Requires-Dist: db-dtypes
|
|
21
21
|
Requires-Dist: numpy
|
|
22
|
+
Dynamic: author
|
|
23
|
+
Dynamic: author-email
|
|
24
|
+
Dynamic: classifier
|
|
25
|
+
Dynamic: description
|
|
26
|
+
Dynamic: description-content-type
|
|
27
|
+
Dynamic: home-page
|
|
28
|
+
Dynamic: requires-dist
|
|
29
|
+
Dynamic: summary
|
|
22
30
|
|
|
23
31
|
# Logos Software Development Kit
|
|
24
32
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|