mcm-cli 1.4.0__py3-none-any.whl → 1.4.2__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mcm-cli
3
- Version: 1.4.0
3
+ Version: 1.4.2
4
4
  Summary: A command-line interface for Moloco Commerde Media
5
5
  Home-page: https://github.com/moloco-mcm/mcm-cli
6
6
  Author: Moloco MCM Team
7
7
  Author-email: mcm-help@moloco.com
8
8
  License: Apache-2.0 license
9
9
  Classifier: Programming Language :: Python :: 3
10
- Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
11
  Classifier: Operating System :: OS Independent
12
12
  Requires-Python: >=3.6
13
13
  Description-Content-Type: text/markdown
@@ -20,6 +20,7 @@ Requires-Dist: pygithub
20
20
  Requires-Dist: python-terraform
21
21
  Requires-Dist: requests
22
22
  Requires-Dist: rich
23
+ Requires-Dist: setuptools
23
24
  Requires-Dist: shortuuid
24
25
  Requires-Dist: toml
25
26
  Requires-Dist: typer
@@ -0,0 +1,32 @@
1
+ mcmcli/__init__.py,sha256=-U6lMZ9_99IXAKwnqnYXYr6NcO6TSmG-kxewgvJjU4k,575
2
+ mcmcli/__main__.py,sha256=8rr--sz02pkM_Z6u90JYm8f1s6sbHmgXF82xfIF6rqg,1844
3
+ mcmcli/logging.py,sha256=xjRS5ey1ONx_d34qB1Fetb_SwPysoh2hzNDuNAaYYWQ,1739
4
+ mcmcli/requests.py,sha256=IuySBQ8P_GoGF3f_TRysfgQNOhi2n9M84WK_eRXnoEU,2945
5
+ mcmcli/command/account.py,sha256=FWXmzOLj4rVLVLEv-w0eDVlQVrkONvR1UewZbcTDgE4,24994
6
+ mcmcli/command/admin.py,sha256=2GC0B3oqQsT5N5mHUyezgZvzPkB4-oGtddguOWfdLJs,15980
7
+ mcmcli/command/auth.py,sha256=Ak7ZNEskWPpMoeTJcbYlEpDBgzxn8N33Q2dNf67SsCs,2926
8
+ mcmcli/command/campaign.py,sha256=SU6TrDy6YhqM0JWPzbYWLpXZrz7Ymw31pd168dK2LZk,10638
9
+ mcmcli/command/config.py,sha256=08C5ftAvdvpQ26Z329LqhP8AxTI629LS7Ou6glzrRgw,4396
10
+ mcmcli/command/decision.py,sha256=iLvEDEa2k0LAgoXrOvcdn-HcFRo90E8Dxht_Ls9EGCY,8690
11
+ mcmcli/command/report.py,sha256=N8IMyDZ5QpY11-KkZG-n5_ZzEeh-ME5s2s3wrAKEGjY,5387
12
+ mcmcli/command/wallet.py,sha256=vG2rg7tPwGsV9YB7cpvkiocbqtB1reqXn7dmolFmzD4,11536
13
+ mcmcli/data/account.py,sha256=pe7tPapP6vlUD5D5L5Nh5k2bkWdYOK01Mpt5fBYFnJs,1782
14
+ mcmcli/data/account_user.py,sha256=27nQp52nMma5a3QszSJGqgq5Z0ivIb-nMZcZuhEgbEg,1328
15
+ mcmcli/data/campaign.py,sha256=-HR-SbEfe44Ys_UXnYr9HRG0TPcGkO2k61iEsz9uET0,2284
16
+ mcmcli/data/decision.py,sha256=bQ5j_PbPRSFa0sY5g9UVqdNzl_2epchcz1lHoDVuV90,2880
17
+ mcmcli/data/error.py,sha256=d6xa_jTXumlA0EzXy2PJQ86ajBb0Pm90fss9R3LuHUc,1094
18
+ mcmcli/data/item.py,sha256=Z2xTRhU8T4vyJADO0l6-XPyQXvb9DX_OAjExhSXpW2A,1091
19
+ mcmcli/data/item_blocking_result.py,sha256=daK4c8--aCe2vRsnTzLBjgKQo0C-zcDH09dC0GgrN7E,1429
20
+ mcmcli/data/platform_user.py,sha256=AC4ps5DdC8XdDpfBMKtVCne2UtnOKtQbVY8D-bLbcIY,1638
21
+ mcmcli/data/report.py,sha256=lJAKQUsaU6g_Kqbx3KpYtBPZ5RSWAJfAmVXxw3KHaUE,2933
22
+ mcmcli/data/seller.py,sha256=40SA7QekM3a3svDrDYLo_QYJ68VUxDO0KeGejJMp4k4,1004
23
+ mcmcli/data/token.py,sha256=11wtyLHCAZHu0LVbNDPa-yipcL6lenxoYIKEI58VzFs,1744
24
+ mcmcli/data/user_join_request.py,sha256=lXMO2hE_VpRg0JofVrYAVM82S-RLFkPrZk8-drvhoDI,1251
25
+ mcmcli/data/wallet.py,sha256=eMUi8N0vJdg_E10TPhSPoZkZtmIG7gHyqgabQ8C5Lg8,3217
26
+ mcm_cli-1.4.2.dist-info/LICENSE,sha256=RFhQPdSOiMTguUX7JSoIuTxA7HVzCbj_p8WU36HjUQQ,10947
27
+ mcm_cli-1.4.2.dist-info/METADATA,sha256=6Y7vHnYzLC2-4-7AHMDyL2mprCj0BKVMCUAP8sOGob8,3056
28
+ mcm_cli-1.4.2.dist-info/NOTICE,sha256=Ldnl2MjRaXPxcldUdbI2NTybq60XAa2LowRhFrRTuiI,76
29
+ mcm_cli-1.4.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
30
+ mcm_cli-1.4.2.dist-info/entry_points.txt,sha256=qTHAWZ-ejSiU4t11RYwtAU8ScqhQPDeMVTG9y4wMVLg,60
31
+ mcm_cli-1.4.2.dist-info/top_level.txt,sha256=sh7oqIaqLQlMtKHlxHHgpV2xGMrBMPFWpSp0C6nvJ_Y,7
32
+ mcm_cli-1.4.2.dist-info/RECORD,,
mcmcli/__main__.py CHANGED
@@ -22,8 +22,10 @@ from typing import Optional
22
22
  import mcmcli.command.account
23
23
  import mcmcli.command.admin
24
24
  import mcmcli.command.auth
25
+ import mcmcli.command.campaign
25
26
  import mcmcli.command.config
26
27
  import mcmcli.command.decision
28
+ import mcmcli.command.report
27
29
  import mcmcli.command.wallet
28
30
  import mcmcli.logging
29
31
  import typer
@@ -35,13 +37,15 @@ def version():
35
37
  """
36
38
  Show the tool version
37
39
  """
38
- typer.echo(f"Version: mcm-cli v1.4.0")
40
+ typer.echo(f"Version: mcm-cli v1.4.2")
39
41
 
40
42
  app.add_typer(mcmcli.command.account.app, name="account", help="Ad account management")
41
43
  app.add_typer(mcmcli.command.admin.app, name="admin", help="Platform administration")
42
44
  app.add_typer(mcmcli.command.auth.app, name="auth", help="Authentication management")
45
+ app.add_typer(mcmcli.command.campaign.app, name="campaign", help="Campaign management")
43
46
  app.add_typer(mcmcli.command.config.app, name="config", help="Configurations")
44
47
  app.add_typer(mcmcli.command.decision.app, name="decision", help="Decision command")
48
+ app.add_typer(mcmcli.command.report.app, name="report", help="Report commands")
45
49
  app.add_typer(mcmcli.command.wallet.app, name="wallet", help="Wallet management")
46
50
 
47
51
  if __name__ == "__main__":
mcmcli/command/account.py CHANGED
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  from enum import Enum
16
+ from mcmcli.command.auth import AuthCommand, AuthHeaderName, AuthHeaderValue
16
17
  from mcmcli.data.account import Account, AccountListWrapper
17
18
  from mcmcli.data.account_user import User, UserWrapper, UserListWrapper
18
19
  from mcmcli.data.error import Error
@@ -348,8 +349,7 @@ class AccountCommand:
348
349
  def __init__(
349
350
  self,
350
351
  profile,
351
- auth_command: mcmcli.command.auth.AuthCommand,
352
- token
352
+ auth_command: AuthCommand,
353
353
  ):
354
354
  self.config = mcmcli.command.config.get_config(profile)
355
355
  if (self.config is None):
@@ -362,18 +362,20 @@ class AccountCommand:
362
362
  self.headers = {
363
363
  "accept": "application/json",
364
364
  "content-type": "application/json",
365
- "Authorization": f"Bearer {token}"
366
365
  }
367
366
 
367
+ self.refresh_token()
368
+
368
369
 
369
370
  def refresh_token(
370
371
  self,
371
372
  ) -> None:
372
- _, error, token = self.auth_command.get_token()
373
+ error, auth_header_name, auth_header_value = self.auth_command.get_auth_credential()
373
374
  if error:
374
375
  print(f"ERROR: {error.message}", file=sys.stderr, flush=True)
375
- return
376
- self.headers["Authorization"] = f"Bearer {token.token}"
376
+ sys.exit()
377
+
378
+ self.headers[auth_header_name] = auth_header_value
377
379
 
378
380
 
379
381
  def retry_with_token_refresh(
@@ -760,12 +762,8 @@ class AccountCommand:
760
762
  def _create_account_command(
761
763
  profile: str
762
764
  ) -> Optional[AccountCommand]:
763
- auth = mcmcli.command.auth.AuthCommand(profile)
764
- _, error, token = auth.get_token()
765
- if error:
766
- print(f"ERROR: {error.message}", file=sys.stderr, flush=True)
767
- return None
768
- return AccountCommand(profile, auth, token.token)
765
+ auth = AuthCommand(profile)
766
+ return AccountCommand(profile, auth)
769
767
 
770
768
 
771
769
  def _read_csv_file(
mcmcli/command/admin.py CHANGED
@@ -12,28 +12,33 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  from datetime import datetime, timedelta, timezone
15
- from mcmcli.data.error import Error
15
+ from mcmcli.command.auth import AuthCommand, AuthHeaderName, AuthHeaderValue
16
+ from mcmcli.data.account import Account
16
17
  from mcmcli.data.item_blocking_result import ItemBlockingResult
18
+ from mcmcli.data.campaign import Campaign
19
+ from mcmcli.data.error import Error
20
+ from mcmcli.data.item import Item
21
+ from mcmcli.data.platform_user import PlatformUser, PlatformUserListWrapper, PlatformUserWrapper
17
22
  from mcmcli.requests import CurlString, api_request
18
23
  from typing import Optional
19
24
 
25
+ import csv
20
26
  import mcmcli.command.account
21
27
  import mcmcli.command.auth
28
+ import mcmcli.command.campaign
22
29
  import mcmcli.command.config
23
30
  import mcmcli.command.wallet
24
31
  import mcmcli.requests
25
32
  import sys
26
33
  import typer
27
34
 
35
+ from mcmcli.logging import echo, echo_newline, start_dot_printing, stop_dot_printing, print_error
36
+
28
37
  app = typer.Typer(add_completion=False)
29
38
 
30
39
  def _create_admin_command(profile):
31
- auth = mcmcli.command.auth.AuthCommand(profile)
32
- _, error, token = auth.get_token()
33
- if error:
34
- print(f"ERROR: {error.message}")
35
- return None
36
- return AdminCommand(profile, auth, token.token)
40
+ auth = AuthCommand(profile)
41
+ return AdminCommand(profile, auth)
37
42
 
38
43
  @app.command()
39
44
  def list_wallet_balances(
@@ -48,6 +53,182 @@ def list_wallet_balances(
48
53
  admin.list_wallet_balances()
49
54
 
50
55
 
56
+ @app.command()
57
+ def list_all_campaigns(
58
+ profile: str = "default",
59
+ ):
60
+ """
61
+ List the campaigigns of all of the active ad accounts
62
+ """
63
+ admin = _create_admin_command(profile)
64
+ if admin is None:
65
+ return
66
+ error, account_campaigns = admin.list_all_campaigns()
67
+ if error:
68
+ print(error, file=sys.stderr, flush=True)
69
+ return
70
+
71
+ print("Account ID,Account Title,Campaign ID,Campaign Title,Ad Type,Start,End,Budget Period,Budget Amount,Enabling State,State,Created At,Updated At")
72
+ for account_campaign in account_campaigns:
73
+ a, c = account_campaign
74
+
75
+ print(f'"{a.id}","{a.title}",', end="", flush=True)
76
+ print(f'"{c.id}","{c.title}","{c.ad_type}",', end="", flush=True)
77
+ print(f'"{c.schedule.start}","{c.schedule.end}",', end="", flush=True)
78
+ print(f'"{c.budget.period}","{int(c.budget.amount.amount_micro) / 1000000}",', end="", flush=True)
79
+ print(f'"{c.enabling_state}","{c.state}",', end="", flush=True)
80
+ print(f'"{c.created_at}","{c.updated_at}",', end="", flush=True)
81
+ # print(f'"{";".join(c.catalog_item_ids)}"')
82
+ print("", flush=True)
83
+
84
+ @app.command()
85
+ def list_platform_users(
86
+ to_curl: bool = typer.Option(False, help="Generate the curl command instead of executing it."),
87
+ to_json: bool = typer.Option(False, help="Print raw output in json"),
88
+ profile: str = "default",
89
+ ):
90
+ """
91
+ List the users of the platform
92
+ """
93
+ admin = _create_admin_command(profile)
94
+ if admin is None:
95
+ return
96
+
97
+ curl, error, users = admin.list_platform_users(to_curl)
98
+ if to_curl:
99
+ print(curl)
100
+ return
101
+ if error:
102
+ print(error, file=sys.stderr, flush=True)
103
+ return
104
+ if to_json:
105
+ json_dumps = [x.model_dump_json() for x in users]
106
+ print(f"[{','.join(json_dumps)}]")
107
+ return
108
+
109
+ print('User ID,Created At,Updated At,Status,Email,Name,Roles')
110
+ for u in users:
111
+ roles = [f'{x.name} of {x.resource_type} {x.resource_id}' for x in u.roles]
112
+ print(f'{u.id},{u.created_at},{u.updated_at},{u.status},{u.email},{u.name},{';'.join(roles)}')
113
+
114
+
115
+ @app.command()
116
+ def get_platform_user(
117
+ user_email: str = typer.Option(help="User's email address"),
118
+ to_curl: bool = typer.Option(False, help="Generate the curl command instead of executing it."),
119
+ to_json: bool = typer.Option(False, help="Print raw output in json"),
120
+ profile: str = typer.Option("default", help="profile name of the MCM CLI."),
121
+ ):
122
+ """
123
+ Get the email user's profile.
124
+ """
125
+ a = _create_admin_command(profile)
126
+ if a is None:
127
+ return
128
+
129
+ curl, error, user = a.get_platform_user(user_email, to_curl)
130
+ if to_curl:
131
+ print(curl)
132
+ return
133
+ if error:
134
+ print(f"ERROR: {error.message}")
135
+ return
136
+
137
+ if user is not None:
138
+ print(f"{user.model_dump_json()}")
139
+ return
140
+
141
+
142
+ @app.command()
143
+ def list_items(
144
+ account_id: str = typer.Option(help="Ad account ID"),
145
+ profile: str = "default",
146
+ ):
147
+ """
148
+ List the itmes, item status, and attached campaigns of a given ad account
149
+ """
150
+ admin = _create_admin_command(profile)
151
+ if admin is None:
152
+ return
153
+
154
+ error, campaigns = admin.list_campaigns(account_id)
155
+ if error:
156
+ print(f"ERROR: {error.message}")
157
+ return
158
+
159
+ campaign_item_obj = {} # build item list into item object with the item_id as an index
160
+ # print("Campaign ID, Campaign Title, Item ID, Item Title, Item Status")
161
+
162
+ for c in campaigns:
163
+ error, campaign_items = admin.list_campaign_items(account_id, c.id)
164
+ if error:
165
+ print(f"ERROR: {error.message}")
166
+ return
167
+ for ci in campaign_items:
168
+ if ci.id in campaign_item_obj:
169
+ campaign_item_obj[ci.id].append({
170
+ 'campaign_id': c.id,
171
+ 'campaign_title': c.title
172
+ })
173
+ else:
174
+ campaign_item_obj[ci.id] = [{
175
+ 'campaign_id': c.id,
176
+ 'campaign_title': c.title
177
+ }]
178
+ # print(f"{c['id']}, {c['title']}, {ci['id']}, {ci['title']}, {ci['is_active']}")
179
+
180
+ error, items = admin.list_items(account_id)
181
+ if error:
182
+ print(f"ERROR: {error.message}")
183
+
184
+ print("Ad Account ID,Item ID,Is Item Active,Item Title,Campaign ID,Campaign Title")
185
+ for i in items:
186
+ if i.id in campaign_item_obj:
187
+ ci = campaign_item_obj[i.id]
188
+ campaign_id_list = ""
189
+ campaign_title_list = ""
190
+ for c in ci:
191
+ campaign_id_list += f"{c['campaign_id']};"
192
+ campaign_title_list += f"{c['campaign_title']};"
193
+ campaign_id_list = campaign_id_list[:-1]
194
+ campaign_title_list = campaign_title_list[:-1]
195
+
196
+ print(f"{account_id},{i.id},{i.is_active},\"{i.title}\",{campaign_id_list},\"{campaign_title_list}\"")
197
+ else:
198
+ print(f"{account_id},{i.id},{i.is_active},\"{i.title}\",,")
199
+
200
+ @app.command()
201
+ def list_off_campaign_items(
202
+ account_id: str = typer.Option(help="Ad account ID"),
203
+ profile: str = "default",
204
+ ):
205
+ """
206
+ Lists the items that are not in any of campaigns
207
+ """
208
+ admin = _create_admin_command(profile)
209
+ if admin is None:
210
+ return
211
+
212
+ error, items = admin.list_items(account_id)
213
+ if error:
214
+ print(f"ERROR: {error.message}")
215
+ return
216
+ error, campaigns = admin.list_campaigns(account_id)
217
+ if error:
218
+ print(f"ERROR: {error.message}")
219
+ return
220
+
221
+ campaign_item_obj = {} # build item list into item object with the item_id as an index
222
+ for c in campaigns:
223
+ error, campaign_items = admin.list_campaign_items(account_id, c.id)
224
+ for ci in campaign_items:
225
+ campaign_item_obj[ci.id] = ci.title
226
+
227
+ print("Item ID, Item Title")
228
+ for i in items:
229
+ if i.id not in campaign_item_obj and i.is_active:
230
+ print(f"{i.id}, {i.title}")
231
+
51
232
  @app.command()
52
233
  def block_item(
53
234
  item_id: str = typer.Option(help="Item ID"),
@@ -77,26 +258,40 @@ def block_item(
77
258
  print(result.model_dump_json())
78
259
  return
79
260
 
261
+
80
262
  class AdminCommand:
81
263
  def __init__(
82
264
  self,
83
265
  profile,
84
- auth_command: mcmcli.command.auth.AuthCommand,
85
- token
266
+ auth_command: AuthCommand,
86
267
  ):
87
- self.profile = profile
88
- self.auth_command = auth_command
89
268
  self.config = mcmcli.command.config.get_config(profile)
90
- mcmcli.command.config.assert_config_exists(self.config)
269
+ if (self.config is None):
270
+ print(f"ERROR: Failed to load the CLI profile", file=sys.stderr, flush=True)
271
+ sys.exit()
91
272
 
92
- self.token = token
273
+ self.profile = profile
274
+ self.auth_command = auth_command
93
275
  self.api_base_url = f"{self.config['management_api_hostname']}/rmp/mgmt/v1/platforms/{self.config['platform_id']}"
94
276
  self.headers = {
95
277
  "accept": "application/json",
96
278
  "content-type": "application/json",
97
- "Authorization": f"Bearer {token}"
98
279
  }
99
280
 
281
+ self.refresh_token()
282
+
283
+
284
+ def refresh_token(
285
+ self,
286
+ ) -> None:
287
+ error, auth_header_name, auth_header_value = self.auth_command.get_auth_credential()
288
+ if error:
289
+ print(f"ERROR: {error.message}", file=sys.stderr, flush=True)
290
+ sys.exit()
291
+
292
+ self.headers[auth_header_name] = auth_header_value
293
+
294
+
100
295
  def block_item(
101
296
  self,
102
297
  item_id,
@@ -112,13 +307,12 @@ class AdminCommand:
112
307
  _payload = {
113
308
  "items": [{
114
309
  "item_id": item_id,
115
- "seller_id": account_id,
116
310
  "updated_time": _requested_at,
117
311
  "blocked": f'Requested at {_requested_at}',
118
312
  }]
119
313
  }
120
- if account_id is None:
121
- del _payload["items"][0]["seller_id"]
314
+ if account_id is not None:
315
+ _payload["items"][0]["seller_id"] = account_id
122
316
 
123
317
  curl, error, json_obj = api_request('POST', to_curl, _api_url, self.headers, _payload)
124
318
  if curl:
@@ -127,11 +321,52 @@ class AdminCommand:
127
321
  return None, error, None
128
322
  return None, None, ItemBlockingResult(**json_obj)
129
323
 
324
+
325
+ def get_platform_user(
326
+ self,
327
+ user_email,
328
+ to_curl = False,
329
+ ) -> tuple[
330
+ Optional[CurlString],
331
+ Optional[Error],
332
+ Optional[PlatformUser],
333
+ ]:
334
+ _api_url = f"{self.api_base_url}/users/{user_email}"
335
+ curl, error, json_obj = api_request('GET', to_curl, _api_url, self.headers)
336
+ if curl:
337
+ return curl, None, None
338
+ if error:
339
+ return None, error, None
340
+
341
+ ret = PlatformUserWrapper(**json_obj).user
342
+ return None, None, ret
343
+
344
+
345
+ def list_platform_users(
346
+ self,
347
+ to_curl=False,
348
+ ) -> tuple [
349
+ Optional[CurlString],
350
+ Optional[Error],
351
+ list[PlatformUser],
352
+ ]:
353
+ _api_url = f"{self.api_base_url}/users"
354
+
355
+ curl, error, json_obj = api_request('GET', to_curl, _api_url, self.headers)
356
+ if curl:
357
+ return curl, None, []
358
+ if error:
359
+ return None, error, []
360
+
361
+ user_list_wrapper = PlatformUserListWrapper(**json_obj)
362
+ users = user_list_wrapper.users
363
+ return None, None, users
364
+
130
365
  def list_wallet_balances(
131
366
  self
132
367
  ):
133
- ac = mcmcli.command.account.AccountCommand(self.profile, self.auth_command, self.token)
134
- wc = mcmcli.command.wallet.WalletCommand(self.profile, self.auth_command, self.token)
368
+ ac = mcmcli.command.account.AccountCommand(self.profile, self.auth_command)
369
+ wc = mcmcli.command.wallet.WalletCommand(self.profile, self.auth_command)
135
370
  _, error, accounts = ac.list_accounts()
136
371
  if error:
137
372
  print(error, file=sys.stderr, flush=True)
@@ -148,5 +383,103 @@ class AdminCommand:
148
383
  prepaid = w1 if w1.type == 'PRE_PAID' else w0
149
384
  credits = int(credits.balance.amount_micro) / 1000000
150
385
  prepaid = int(prepaid.balance.amount_micro) / 1000000
386
+
151
387
  print(f'"{accounts[id].title}", {id}, {credits}, {prepaid}')
152
388
 
389
+
390
+
391
+ def list_all_campaigns(
392
+ self
393
+ ) -> tuple [
394
+ Optional[Error],
395
+ list[tuple[Account, Campaign]]
396
+ ]:
397
+ ac = mcmcli.command.account.AccountCommand(self.profile, self.auth_command)
398
+ cc = mcmcli.command.campaign.CampaignCommand(self.profile, self.auth_command)
399
+ _, error, accounts = ac.list_accounts()
400
+ if error:
401
+ return error, []
402
+
403
+ echo('Collecting campaigns...')
404
+ return_value = []
405
+ for id in accounts:
406
+ account = accounts[id]
407
+ echo('.')
408
+ # print(f'{account.id}, \"{account.title}\"')
409
+ _, error, campaigns = cc.list_campaigns(account.id)
410
+ if error:
411
+ echo_newline(error)
412
+ continue
413
+ for c in campaigns:
414
+ return_value.append((account, c))
415
+
416
+ echo_newline(' done')
417
+ return None, return_value
418
+
419
+
420
+ def list_items(
421
+ self,
422
+ account_id
423
+ ) -> tuple [
424
+ Optional[Error],
425
+ list[Item],
426
+ ]:
427
+ ac = mcmcli.command.account.AccountCommand(self.profile, self.auth_command)
428
+ echo("Gathering the account's items ")
429
+ thread, stopper = start_dot_printing()
430
+ _, error, items = ac.list_account_items(account_id)
431
+ stop_dot_printing(thread, stopper)
432
+ echo_newline(" done")
433
+
434
+ if error:
435
+ return error, []
436
+ if items == []:
437
+ return Error(code=0, message=str("Cannot find items")), []
438
+
439
+ return None, items
440
+
441
+ def list_campaigns(
442
+ self,
443
+ ad_account_id
444
+ ) -> tuple [
445
+ Optional[Error],
446
+ list[Campaign],
447
+ ]:
448
+ cam = mcmcli.command.campaign.CampaignCommand(self.profile, self.auth_command)
449
+
450
+ echo("Gathering the account's campaigns ")
451
+ thread, stopper = start_dot_printing()
452
+ _, error, campaigns = cam.list_campaigns(ad_account_id)
453
+ stop_dot_printing(thread, stopper)
454
+ echo_newline(" done")
455
+
456
+ if error:
457
+ return error, []
458
+ if campaigns == []:
459
+ return Error(code=0, message=str("Cannot find campaigns")), []
460
+
461
+ return None, campaigns
462
+
463
+
464
+ def list_campaign_items(
465
+ self,
466
+ ad_account_id,
467
+ campaign_id
468
+ ) -> tuple [
469
+ Optional[Error],
470
+ list[Item]
471
+ ]:
472
+ cam = mcmcli.command.campaign.CampaignCommand(self.profile, self.auth_command)
473
+
474
+ echo(f"Gathering the items of the campaign {campaign_id} ")
475
+ thread, stopper = start_dot_printing()
476
+ _, error, campaign_items = cam.list_campaign_items(ad_account_id, campaign_id)
477
+ stop_dot_printing(thread, stopper)
478
+ echo_newline(" done")
479
+
480
+ if error:
481
+ return error, []
482
+ if campaign_items == []:
483
+ return Error(code=0, message=str("Cannot find campaign items")), []
484
+
485
+ return None, campaign_items
mcmcli/command/auth.py CHANGED
@@ -21,6 +21,9 @@ import mcmcli.logging
21
21
  import sys
22
22
  import typer
23
23
 
24
+ AuthHeaderName = str
25
+ AuthHeaderValue = str
26
+
24
27
  app = typer.Typer(add_completion=False)
25
28
 
26
29
  #
@@ -79,4 +82,15 @@ class AuthCommand:
79
82
  return None, error, None
80
83
 
81
84
  return None, None, Token(**json_obj)
85
+
86
+ def get_auth_credential(self) -> tuple[Error, AuthHeaderName, AuthHeaderValue]:
87
+ if 'management_api_key' in self.config:
88
+ return None, "x-api-key", self.config['management_api_key']
89
+
90
+ _, error, token = self.get_token(to_curl=False)
91
+ if error:
92
+ return error, None, None
93
+
94
+ else:
95
+ return None, "Authorization", f"Bearer {token.token}"
82
96