logos-sdk 0.0.25.dev8__tar.gz → 0.0.25.dev10__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.
Files changed (26) hide show
  1. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/PKG-INFO +1 -1
  2. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/big_query/BigQuery.py +28 -10
  3. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/services/CampaignManager.py +47 -0
  4. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/services/DV360.py +53 -1
  5. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/services/Facebook.py +6 -1
  6. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/services/GoogleAds.py +50 -4
  7. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/services/MerchantCenter.py +36 -6
  8. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/services/MicrosoftAdvertising.py +3 -0
  9. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/services/Sklik.py +125 -35
  10. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk.egg-info/PKG-INFO +1 -1
  11. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/LICENSE +0 -0
  12. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/README.md +0 -0
  13. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/__init__.py +0 -0
  14. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/big_query/__init__.py +0 -0
  15. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/logging/LogosLogger.py +0 -0
  16. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/logging/__init__.py +0 -0
  17. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/services/Collabim.py +0 -0
  18. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/services/GoogleSheets.py +0 -0
  19. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/services/MarketMiner.py +0 -0
  20. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk/services/__init__.py +0 -0
  21. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk.egg-info/SOURCES.txt +0 -0
  22. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk.egg-info/dependency_links.txt +0 -0
  23. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk.egg-info/requires.txt +0 -0
  24. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/logos_sdk.egg-info/top_level.txt +0 -0
  25. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/setup.cfg +0 -0
  26. {logos_sdk-0.0.25.dev8 → logos_sdk-0.0.25.dev10}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: logos-sdk
3
- Version: 0.0.25.dev8
3
+ Version: 0.0.25.dev10
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
@@ -36,6 +36,19 @@ class BigQuery:
36
36
  except DefaultCredentialsError:
37
37
  self.logger = None
38
38
 
39
+ def parse_fields(self, fields):
40
+ result = []
41
+ for row in fields:
42
+ result.append(
43
+ bigquery.schema.SchemaField(
44
+ row["name"],
45
+ row["col_type"],
46
+ mode=row["mode"],
47
+ fields=self.parse_fields(row["fields"]) if "fields" in row else [],
48
+ )
49
+ )
50
+ return result
51
+
39
52
  def get_dataset(self, dataset_id: str):
40
53
  return self._service.get_dataset(dataset_id)
41
54
 
@@ -57,17 +70,17 @@ class BigQuery:
57
70
  return self._service.get_table(sql_format)
58
71
 
59
72
  def insert_into_table(
60
- self, dataset_id: str, table_id: str, records: List[Dict]
73
+ self, dataset_id: str, table_id: str, records: List[Dict]
61
74
  ) -> None:
62
75
  bq_table = self.get_table(dataset_id, table_id)
63
76
  self._insert_into_table(bq_table, records)
64
77
 
65
78
  def insert_create_table(
66
- self,
67
- dataset_id: str,
68
- table_id: str,
69
- records: List[Dict],
70
- schema_columns: List[Dict],
79
+ self,
80
+ dataset_id: str,
81
+ table_id: str,
82
+ records: List[Dict],
83
+ schema_columns: List[Dict],
71
84
  ) -> None:
72
85
  bq_table = self.check_table_exists(dataset_id, table_id)
73
86
  if bq_table is None:
@@ -87,10 +100,15 @@ class BigQuery:
87
100
  return None
88
101
 
89
102
  def create_table(
90
- self, dataset_id: str, table_id: str, schema_columns: List[Dict]
103
+ self, dataset_id: str, table_id: str, schema_columns: List[Dict]
91
104
  ) -> Union[bool, Table]:
92
105
  table_schema = [
93
- bigquery.schema.SchemaField(row["name"], row["col_type"], mode=row["mode"])
106
+ bigquery.schema.SchemaField(
107
+ row["name"],
108
+ row["col_type"],
109
+ mode=row["mode"],
110
+ fields=self.parse_fields(row["fields"]) if "fields" in row else [],
111
+ )
94
112
  for row in schema_columns
95
113
  ]
96
114
  try:
@@ -132,13 +150,13 @@ class BigQuery:
132
150
 
133
151
  @retry_on_not_found
134
152
  def _insert_into_table(
135
- self, bq_table: Table, records: List[Dict], attempts: int
153
+ self, bq_table: Table, records: List[Dict], attempts: int
136
154
  ) -> None:
137
155
  if len(records) > self.BQ_ROWS_LIMIT:
138
156
  for index in range(0, len(records), self.BQ_ROWS_LIMIT):
139
157
  errors = self._service.insert_rows(
140
158
  bq_table,
141
- records[index: (index + self.BQ_ROWS_LIMIT)],
159
+ records[index : (index + self.BQ_ROWS_LIMIT)],
142
160
  retry=Retry(
143
161
  total=2, connect=4, backoff_factor=2, allowed_methods=None
144
162
  ),
@@ -30,6 +30,8 @@ class CampaignManagerService:
30
30
  self._GET_FILE = self._URL + "/get-file"
31
31
  self._GET_FILE_MEDIA_REQUEST = self._URL + "/get-file-media-request"
32
32
  self._QUERY_DIMENSION_VALUES = self._URL + "/query-dimension-values"
33
+ self._GET_ACCESSIBLE_PARENT_ACCOUNTS = self._URL + "/get-parent-accounts"
34
+ self._GET_ACCESSIBLE_ADVERTISERS = self._URL + "/get-advertisers"
33
35
 
34
36
  def create_report(
35
37
  self,
@@ -397,3 +399,48 @@ class CampaignManagerService:
397
399
  report_id=report["id"],
398
400
  secret_id=secret_id,
399
401
  )
402
+
403
+ def get_accessible_parent_accounts(self, secret_id):
404
+ """
405
+ Returns accessible parent accounts
406
+ :param secret_id: The ID of the secret in secret manager
407
+ :return: list of parent accounts
408
+ """
409
+
410
+ header = get_headers(self._GET_ACCESSIBLE_PARENT_ACCOUNTS)
411
+ body = {"secret_id": secret_id}
412
+
413
+ response = request(
414
+ "post", url=self._GET_ACCESSIBLE_PARENT_ACCOUNTS, json=body, headers=header
415
+ )
416
+
417
+ if response.status_code == HTTPStatus.OK:
418
+ service_response = response.json()
419
+ return service_response["data"]
420
+ else:
421
+ raise CampaignManagerServiceException(response.content)
422
+
423
+ def get_accessible_advertisers(self, secret_id):
424
+ """
425
+ Returns accessible advertisers
426
+ :param secret_id: The ID of the secret in secret manager
427
+ :return: list of advertisers
428
+ """
429
+
430
+ header = get_headers(self._GET_ACCESSIBLE_ADVERTISERS)
431
+ body = {
432
+ "secret_id": secret_id,
433
+ "filters": {
434
+ "hide_inactive": True,
435
+ },
436
+ }
437
+
438
+ response = request(
439
+ "post", url=self._GET_ACCESSIBLE_ADVERTISERS, json=body, headers=header
440
+ )
441
+
442
+ if response.status_code == HTTPStatus.OK:
443
+ service_response = response.json()
444
+ return service_response["data"]
445
+ else:
446
+ raise CampaignManagerServiceException(response.content)
@@ -34,6 +34,8 @@ class DV360Service:
34
34
  self._GET_QUERY_METADATA = self._URL + "/get-query-metadata"
35
35
  self._RUN_QUERY = self._URL + "/run-query"
36
36
  self._DELETE_QUERY = self._URL + "/delete-query"
37
+ self._GET_ACCESSIBLE_PARTNERS = self._URL + "/get-accessible-partners"
38
+ self._GET_ACCESSIBLE_ADVERTISERS = self._URL + "/get-accessible-advertisers"
37
39
 
38
40
  def list_line_items(self, advertiser_id, secret_id, filter_string=None):
39
41
  """
@@ -301,6 +303,56 @@ class DV360Service:
301
303
  else:
302
304
  raise DV360ServiceException(response.content)
303
305
 
306
+ def get_accessible_partners(self, secret_id):
307
+ """
308
+ Returns accessible partners
309
+ :param secret_id: The ID of the secret in secret manager
310
+ :return: list of partners
311
+ """
312
+
313
+ header = get_headers(self._GET_ACCESSIBLE_PARTNERS)
314
+ body = {
315
+ "secret_id": secret_id,
316
+ "filters": {
317
+ "hide_inactive": True,
318
+ },
319
+ }
320
+
321
+ response = request(
322
+ "post", url=self._GET_ACCESSIBLE_PARTNERS, json=body, headers=header
323
+ )
324
+
325
+ if response.status_code == HTTPStatus.OK:
326
+ service_response = response.json()
327
+ return service_response["data"]
328
+ else:
329
+ raise DV360ServiceException(response.content)
330
+
331
+ def get_accessible_advertisers(self, secret_id):
332
+ """
333
+ Returns accessible advertisers
334
+ :param secret_id: The ID of the secret in secret manager
335
+ :return: list of advertisers
336
+ """
337
+
338
+ header = get_headers(self._GET_ACCESSIBLE_ADVERTISERS)
339
+ body = {
340
+ "secret_id": secret_id,
341
+ "filters": {
342
+ "hide_inactive": True,
343
+ },
344
+ }
345
+
346
+ response = request(
347
+ "post", url=self._GET_ACCESSIBLE_ADVERTISERS, json=body, headers=header
348
+ )
349
+
350
+ if response.status_code == HTTPStatus.OK:
351
+ service_response = response.json()
352
+ return service_response["data"]
353
+ else:
354
+ raise DV360ServiceException(response.content)
355
+
304
356
  def _check_report_ready_with_exponential_backoff(
305
357
  self, secret_id: str, query_id: str, report_id: str, backoff_attempts: int = 10
306
358
  ) -> bool:
@@ -393,5 +445,5 @@ class DV360Service:
393
445
 
394
446
  if response.status_code == HTTPStatus.OK:
395
447
  return True
396
- print("Query was not deleted!")
448
+
397
449
  return False
@@ -38,7 +38,12 @@ class FacebookService:
38
38
  :return: all accessible accounts List(Dict)
39
39
  """
40
40
 
41
- body = {"secret_id": secret_id}
41
+ body = {
42
+ "secret_id": secret_id,
43
+ "filters": {
44
+ "hide_inactive": True,
45
+ }
46
+ }
42
47
 
43
48
  header = get_headers(self._ACCESSIBLE_ACCOUNTS)
44
49
 
@@ -21,6 +21,7 @@ class GoogleAdsService:
21
21
  self._SEARCH = self._URL + "/search"
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
+ self._GET_ACCESSIBLE_ACCOUNTS = self._URL + "/list-accessible-accounts"
24
25
 
25
26
  @staticmethod
26
27
  def fetch_with_retry_on_timeout(url, json, headers):
@@ -28,8 +29,10 @@ class GoogleAdsService:
28
29
  try:
29
30
  return request("post", url, json=json, headers=headers, timeout=25)
30
31
  except Timeout:
31
- delay = 2 * (2 ** attempt) + random.randint(0, 9)
32
- print(f"there was a timeout when contacting the service, going to sleep for {delay} seconds")
32
+ delay = 2 * (2**attempt) + random.randint(0, 9)
33
+ print(
34
+ f"there was a timeout when contacting the service, going to sleep for {delay} seconds"
35
+ )
33
36
  time.sleep(delay)
34
37
 
35
38
  raise Exception("The service is not able to reply within 30 seconds.")
@@ -53,7 +56,9 @@ class GoogleAdsService:
53
56
  }
54
57
 
55
58
  header = get_headers(self._SEARCH_STREAM)
56
- response = self.fetch_with_retry_on_timeout(url=self._SEARCH_STREAM, json=body, headers=header)
59
+ response = self.fetch_with_retry_on_timeout(
60
+ url=self._SEARCH_STREAM, json=body, headers=header
61
+ )
57
62
 
58
63
  if response.status_code == HTTPStatus.OK:
59
64
  service_response = response.json()
@@ -84,7 +89,9 @@ class GoogleAdsService:
84
89
  }
85
90
 
86
91
  header = get_headers(self._SEARCH)
87
- response = self.fetch_with_retry_on_timeout(url=self._SEARCH, json=body, headers=header)
92
+ response = self.fetch_with_retry_on_timeout(
93
+ url=self._SEARCH, json=body, headers=header
94
+ )
88
95
 
89
96
  if response.status_code != HTTPStatus.OK:
90
97
  raise GoogleAdsServiceException(response.content)
@@ -163,3 +170,42 @@ class GoogleAdsService:
163
170
  return
164
171
  else:
165
172
  raise GoogleAdsServiceException(response.content)
173
+
174
+ def get_accessible_accounts(
175
+ self,
176
+ secret_id: str,
177
+ page_size: int = 1000,
178
+ ) -> List[Dict]:
179
+ body = {
180
+ "secret_id": secret_id,
181
+ "filters": {
182
+ "hide_inactive": True,
183
+ },
184
+ "page_token": None,
185
+ "page_size": page_size,
186
+ }
187
+
188
+ header = get_headers(self._GET_ACCESSIBLE_ACCOUNTS)
189
+ response = self.fetch_with_retry_on_timeout(
190
+ url=self._GET_ACCESSIBLE_ACCOUNTS, json=body, headers=header
191
+ )
192
+
193
+ if response.status_code != HTTPStatus.OK:
194
+ raise GoogleAdsServiceException(response.content)
195
+
196
+ service_response = response.json()
197
+ all_results = service_response["data"]["results"]
198
+
199
+ while service_response["data"]["next_page_token"]:
200
+ body["page_token"] = service_response["data"]["next_page_token"]
201
+ response = request(
202
+ "post", url=self._GET_ACCESSIBLE_ACCOUNTS, json=body, headers=header
203
+ )
204
+
205
+ if response.status_code != HTTPStatus.OK:
206
+ raise GoogleAdsServiceException(response.content)
207
+
208
+ service_response = response.json()
209
+ all_results.extend(service_response["data"]["results"])
210
+
211
+ return all_results
@@ -14,6 +14,7 @@ class MerchantCenterService:
14
14
  load_dotenv()
15
15
  self._URL = url or os.environ.get("MERCHANT_CENTER_SERVICE_PATH")
16
16
  self._LIST_ACCOUNTS = self._URL + "/account-service/accounts"
17
+ self._LIST_ACCESSIBLE_ACCOUNTS = self._URL + "/account-service/list-accessible-accounts"
17
18
  self._LIST_ACCOUNT_STATUSES = self._URL + "/account-service/account-statuses"
18
19
  self._LIST_PRODUCTS = self._URL + "/product-service/products"
19
20
  self._LIST_PRODUCT_STATUSES = self._URL + "/product-service/product-statuses"
@@ -36,6 +37,22 @@ class MerchantCenterService:
36
37
  else:
37
38
  raise MerchantServiceException(response.content)
38
39
 
40
+ def list_accessible_accounts(self, secret_id: str):
41
+ """
42
+ Lists accessible accounts in Merchant Center
43
+ :param secret_id: The ID of the secret in secret manager
44
+ :return: List[Dict]
45
+ """
46
+ body = {"secret_id": secret_id}
47
+ header = get_headers(self._LIST_ACCESSIBLE_ACCOUNTS)
48
+ response = request("post", url=self._LIST_ACCESSIBLE_ACCOUNTS, json=body, headers=header)
49
+
50
+ if response.status_code == HTTPStatus.OK:
51
+ service_response = response.json()
52
+ return service_response["data"]
53
+ else:
54
+ raise MerchantServiceException(response.content)
55
+
39
56
  def list_account_statuses(
40
57
  self, merchant_account_id: str, account_id: str, secret_id: str
41
58
  ):
@@ -92,26 +109,39 @@ class MerchantCenterService:
92
109
  service_response = response.json()
93
110
  yield service_response["data"]["results"]
94
111
 
95
- def list_products_statuses(self, merchant_account_id: str, secret_id: str):
112
+ def list_products_statuses(self, merchant_account_id: str, secret_id: str, page_size: int = 250):
96
113
  """
97
114
  Lists the statuses of the products in your Merchant Center account
98
115
  :param merchant_account_id: The ID of the
99
116
  account that contains the products. This account cannot be a multi-client account
100
117
  :param secret_id: The ID of the secret in secret manager
118
+ :param page_size: size of the page
101
119
  :return: List[Dict]
102
120
  """
103
- body = {"merchant_account_id": merchant_account_id, "secret_id": secret_id}
121
+ body = {"merchant_account_id": merchant_account_id, "secret_id": secret_id, "page_size": page_size}
104
122
  header = get_headers(self._LIST_PRODUCT_STATUSES)
105
123
  response = request(
106
124
  "post", url=self._LIST_PRODUCT_STATUSES, json=body, headers=header
107
125
  )
108
126
 
109
- if response.status_code == HTTPStatus.OK:
110
- service_response = response.json()
111
- return service_response["data"]
112
- else:
127
+ if response.status_code != HTTPStatus.OK:
113
128
  raise MerchantServiceException(response.content)
114
129
 
130
+ service_response = response.json()
131
+ yield service_response["data"]["results"]
132
+
133
+ while service_response["data"]["nextPageToken"] is not None:
134
+ body["page_token"] = service_response["data"]["nextPageToken"]
135
+ response = request(
136
+ "post", url=self._LIST_PRODUCT_STATUSES, json=body, headers=header
137
+ )
138
+
139
+ if response.status_code != HTTPStatus.OK:
140
+ raise MerchantServiceException(response.content)
141
+
142
+ service_response = response.json()
143
+ yield service_response["data"]["results"]
144
+
115
145
  def reports_search(
116
146
  self,
117
147
  merchant_account_id: str,
@@ -212,6 +212,9 @@ class MicrosoftAdvertising:
212
212
  """
213
213
  body = {
214
214
  "secret_id": secret_id,
215
+ "filters": {
216
+ "hide_inactive": True
217
+ }
215
218
  }
216
219
  header = get_headers(self._GET_ACCESSIBLE_ACCOUNTS)
217
220
  response = request(
@@ -46,13 +46,15 @@ def get_session_if_malformed(wrapped_function):
46
46
 
47
47
  return inner
48
48
 
49
+
49
50
  def get_report_results_if_expired(wrapped_function):
50
51
  @wraps(wrapped_function)
51
52
  def inner(*args, **kwargs):
52
53
  try:
53
54
  return wrapped_function(*args, **kwargs)
54
55
  except SklikServiceException as err:
55
- if json.loads(err.args[0].decode("utf8")).get("detail") == "Requested report has expired. Please create a new report by calling createReport endpoint.":
56
+ if json.loads(err.args[0].decode("utf8")).get(
57
+ "detail") == "Requested report has expired. Please create a new report by calling createReport endpoint.":
56
58
  print("Report expired, creating new report")
57
59
  args[0].get_session(args[0]._secret_id, args[0]._account_email)
58
60
  return wrapped_function(*args, **kwargs)
@@ -69,10 +71,12 @@ class SklikService:
69
71
  self._CREATE_REPORT = self._URL + "/create-report"
70
72
  self._READ_REPORT = self._URL + "/read-report"
71
73
  self._API = self._URL + "/call-api"
74
+ self._GET_CLIENT = self._URL + "/get-client"
72
75
  self._CHECK_DATA_READY = self._URL + "/check-data-ready"
73
76
  self._LOGOUT = self._URL + "/logout"
74
77
  self._API_LIMITS = self._URL + "/api-limits"
75
78
  self._GET_SESSION = self._URL + "/get-session"
79
+ self._GET_SESSION_WITHOUT_ACCOUNT = self._URL + "/get-session-without-account"
76
80
  self.session = None # dict {"sklik_session": "", "user_id": ""}
77
81
  self._secret_id = None
78
82
  self._account_email = None
@@ -98,6 +102,25 @@ class SklikService:
98
102
  else:
99
103
  raise SklikServiceException(response.content)
100
104
 
105
+ def get_session_without_account(self, secret_id: str) -> None:
106
+ """
107
+ Manages initial login of the sessions, returns dict with sklik session string without user id int
108
+ :param secret_id: The ID of the secret in secret manager
109
+ :return: Dict
110
+ """
111
+ body = {"secret_id": secret_id}
112
+ response = execute_request("post", url=self._GET_SESSION_WITHOUT_ACCOUNT, json=body)
113
+
114
+ if response.status_code == HTTPStatus.OK:
115
+ service_response = response.json()
116
+ self.session = {
117
+ "sklik_session": service_response["data"]["sklik_session"],
118
+ "user_id": None,
119
+ }
120
+ self._secret_id = secret_id
121
+ else:
122
+ raise SklikServiceException(response.content)
123
+
101
124
  def logout_of_current_session(self) -> None:
102
125
  """
103
126
  Attempts to log out of the current session, nothing happens if not ok
@@ -112,15 +135,15 @@ class SklikService:
112
135
  @get_session_if_malformed
113
136
  @get_report_results_if_expired
114
137
  def get_report_results(
115
- self,
116
- secret_id: str,
117
- account_email: str,
118
- report_type: str,
119
- date_from: str,
120
- date_to: str,
121
- columns: List[str],
122
- create_params: Dict[str, Union[int, str]] = None,
123
- read_params: Dict[str, Union[int, str]] = None,
138
+ self,
139
+ secret_id: str,
140
+ account_email: str,
141
+ report_type: str,
142
+ date_from: str,
143
+ date_to: str,
144
+ columns: List[str],
145
+ create_params: Dict[str, Union[int, str]] = None,
146
+ read_params: Dict[str, Union[int, str]] = None,
124
147
  ) -> List[Dict]:
125
148
  """
126
149
  It creates sklik report with /create-report call in sklik service and reads sklik report with pagination
@@ -165,14 +188,14 @@ class SklikService:
165
188
 
166
189
  @get_session_if_malformed
167
190
  def get_streamed_report_results(
168
- self,
169
- secret_id: str,
170
- account_email: str,
171
- report_type: str,
172
- date_from: str,
173
- date_to: str,
174
- columns: List[str],
175
- create_params: Dict[str, Union[int, str]] = None,
191
+ self,
192
+ secret_id: str,
193
+ account_email: str,
194
+ report_type: str,
195
+ date_from: str,
196
+ date_to: str,
197
+ columns: List[str],
198
+ create_params: Dict[str, Union[int, str]] = None,
176
199
  ) -> List[Dict]:
177
200
  """
178
201
  It creates sklik report with /create-report call in sklik service and reads sklik report with pagination
@@ -212,13 +235,13 @@ class SklikService:
212
235
  raise SklikServiceException(response.content)
213
236
 
214
237
  def _create_report(
215
- self,
216
- secret_id: str,
217
- account_email: str,
218
- report_type: str,
219
- date_from: str,
220
- date_to: str,
221
- params: Dict[str, Union[int, str]] = None,
238
+ self,
239
+ secret_id: str,
240
+ account_email: str,
241
+ report_type: str,
242
+ date_from: str,
243
+ date_to: str,
244
+ params: Dict[str, Union[int, str]] = None,
222
245
  ) -> Dict:
223
246
  """
224
247
  Function creates sklik report with /create-report call
@@ -255,7 +278,7 @@ class SklikService:
255
278
 
256
279
  @get_session_if_malformed
257
280
  def call_api(
258
- self, secret_id: str, account_email: str, method: str, params: List[Dict]
281
+ self, secret_id: str, account_email: str, method: str, params: List[Dict]
259
282
  ) -> Union[List, Dict]:
260
283
  """
261
284
  Function to call SklikService get-api route
@@ -282,12 +305,79 @@ class SklikService:
282
305
  else:
283
306
  raise SklikServiceException(response.content)
284
307
 
308
+ @get_session_if_malformed
309
+ def get_client(
310
+ self,
311
+ secret_id: str,
312
+ account_email: str,
313
+ ) -> Union[List, Dict]:
314
+ """
315
+ Function to call SklikService get-client route
316
+ :param secret_id: The ID of the secret in secret manager
317
+ :param account_email: Account email to refers to Sklik accountId
318
+ :return:
319
+ """
320
+
321
+ if self.session is None:
322
+ self.get_session(secret_id, account_email)
323
+
324
+ response = execute_request(
325
+ "post",
326
+ url=self._GET_CLIENT,
327
+ json={"sklik_session": self.session["sklik_session"]},
328
+ )
329
+
330
+ if response.status_code == HTTPStatus.OK:
331
+ service_response = response.json()
332
+ return service_response["data"]
333
+ else:
334
+ raise SklikServiceException(response.content)
335
+
336
+ @get_session_if_malformed
337
+ def get_accessible_accounts(
338
+ self,
339
+ secret_id: str,
340
+ ) -> Union[List, Dict]:
341
+ """
342
+ Function to retrieve accessible accounts
343
+ :param secret_id: The ID of the secret in secret manager
344
+ :return:
345
+ """
346
+
347
+ if self.session is None:
348
+ self.get_session_without_account(secret_id)
349
+
350
+ response = execute_request(
351
+ "post",
352
+ url=self._GET_CLIENT,
353
+ json={
354
+ "sklik_session": self.session["sklik_session"],
355
+ "filters": {
356
+ "hide_inactive": True
357
+ }
358
+ },
359
+ )
360
+
361
+ if response.status_code == HTTPStatus.OK:
362
+ accounts = []
363
+ service_response = response.json()
364
+ data = service_response["data"]
365
+ for account in data["foreignAccounts"]:
366
+ accounts.append({
367
+ "id": account['userId'],
368
+ "name": account['username'],
369
+ "active": account["relationStatus"] == "live"
370
+ })
371
+ return accounts
372
+ else:
373
+ raise SklikServiceException(response.content)
374
+
285
375
  @get_session_if_malformed
286
376
  def check_data_ready(
287
- self,
288
- secret_id: str,
289
- account_email: str,
290
- date: str = None,
377
+ self,
378
+ secret_id: str,
379
+ account_email: str,
380
+ date: str = None,
291
381
  ) -> int:
292
382
  """
293
383
  Checks if data on server are ready
@@ -301,8 +391,8 @@ class SklikService:
301
391
  self.get_session(secret_id, account_email)
302
392
 
303
393
  date = date or (
304
- datetime.now(timezone("UTC")).astimezone(timezone("Europe/Prague"))
305
- - timedelta(days=1)
394
+ datetime.now(timezone("UTC")).astimezone(timezone("Europe/Prague"))
395
+ - timedelta(days=1)
306
396
  ).strftime("%Y-%m-%d")
307
397
 
308
398
  body = {"date": date}
@@ -323,9 +413,9 @@ class SklikService:
323
413
 
324
414
  @get_session_if_malformed
325
415
  def fetch_api_limits(
326
- self,
327
- secret_id: str,
328
- account_email: str,
416
+ self,
417
+ secret_id: str,
418
+ account_email: str,
329
419
  ) -> Union[List, Dict]:
330
420
  """
331
421
  Function to call SklikService api/limits route
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: logos-sdk
3
- Version: 0.0.25.dev8
3
+ Version: 0.0.25.dev10
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