amazon-ads-cli 0.1.0__py3-none-any.whl

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.
File without changes
amazon_ads_cli/main.py ADDED
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env python3
2
+ """Amazon Ads CLI - Command line interface for Amazon Advertising API v3."""
3
+
4
+ import click
5
+ import json
6
+ from datetime import datetime, timedelta
7
+ from ad_api.api import sponsored_products, reports
8
+ from ad_api.base import Marketplaces
9
+
10
+
11
+ @click.group()
12
+ @click.option('--profile', '-p', default='default', help='Credential profile')
13
+ @click.pass_context
14
+ def cli(ctx, profile):
15
+ """Amazon Ads CLI - Manage campaigns, keywords, and reports."""
16
+ ctx.ensure_object(dict)
17
+ ctx.obj['profile'] = profile
18
+
19
+
20
+ @cli.group()
21
+ def campaigns():
22
+ """Campaign management commands."""
23
+ pass
24
+
25
+
26
+ @campaigns.command('list')
27
+ @click.pass_context
28
+ def list_campaigns(ctx):
29
+ """List all campaigns."""
30
+ result = sponsored_products.CampaignsV3(marketplace=Marketplaces.NA).list_campaigns(body={})
31
+ campaigns = result.payload.get('campaigns', [])
32
+
33
+ click.echo(f"\n{'Campaign':<30} {'State':<10} {'Budget':<10} {'Type'}")
34
+ click.echo("-" * 65)
35
+ for camp in campaigns:
36
+ name = camp['name'][:28]
37
+ state = camp['state']
38
+ budget = f"${camp['budget']['budget']}"
39
+ ctype = camp.get('targetingType', 'N/A')
40
+ click.echo(f"{name:<30} {state:<10} {budget:<10} {ctype}")
41
+
42
+
43
+ @campaigns.command('pause')
44
+ @click.argument('campaign-id')
45
+ @click.pass_context
46
+ def pause_campaign(ctx, campaign_id):
47
+ """Pause a campaign."""
48
+ try:
49
+ result = sponsored_products.CampaignsV3(marketplace=Marketplaces.NA).edit_campaigns(
50
+ body={"campaigns": [{"campaignId": campaign_id, "state": "PAUSED"}]}
51
+ )
52
+ click.echo(f"✅ Campaign {campaign_id} paused")
53
+ except Exception as e:
54
+ click.echo(f"❌ Error: {e}")
55
+
56
+
57
+ @campaigns.command('enable')
58
+ @click.argument('campaign-id')
59
+ @click.pass_context
60
+ def enable_campaign(ctx, campaign_id):
61
+ """Enable a campaign."""
62
+ try:
63
+ result = sponsored_products.CampaignsV3(marketplace=Marketplaces.NA).edit_campaigns(
64
+ body={"campaigns": [{"campaignId": campaign_id, "state": "ENABLED"}]}
65
+ )
66
+ click.echo(f"✅ Campaign {campaign_id} enabled")
67
+ except Exception as e:
68
+ click.echo(f"❌ Error: {e}")
69
+
70
+
71
+ @cli.group()
72
+ def keywords():
73
+ """Keyword management commands."""
74
+ pass
75
+
76
+
77
+ @keywords.command('list')
78
+ @click.argument('campaign-id')
79
+ @click.pass_context
80
+ def list_keywords(ctx, campaign_id):
81
+ """List keywords for a campaign."""
82
+ result = sponsored_products.KeywordsV3(marketplace=Marketplaces.NA).list_keywords(body={})
83
+ keywords = [k for k in result.payload.get('keywords', []) if k.get('campaignId') == campaign_id]
84
+
85
+ click.echo(f"\n{'Keyword':<35} {'Match':<10} {'Bid':<8} {'State'}")
86
+ click.echo("-" * 70)
87
+ for kw in keywords:
88
+ text = kw['keywordText'][:33]
89
+ match = kw['matchType']
90
+ bid = f"${kw['bid']}"
91
+ state = kw['state']
92
+ click.echo(f"{text:<35} {match:<10} {bid:<8} {state}")
93
+
94
+
95
+ @cli.group()
96
+ def report():
97
+ """Report commands."""
98
+ pass
99
+
100
+
101
+ @report.command('today')
102
+ @click.pass_context
103
+ def report_today(ctx):
104
+ """Get today's performance report."""
105
+ today = datetime.now().strftime('%Y-%m-%d')
106
+
107
+ click.echo(f"Requesting report for {today}...")
108
+
109
+ report_body = {
110
+ "name": f"SP_Today_{today}",
111
+ "startDate": today,
112
+ "endDate": today,
113
+ "configuration": {
114
+ "adProduct": "SPONSORED_PRODUCTS",
115
+ "columns": [
116
+ "impressions", "clicks", "cost",
117
+ "purchases14d", "sales14d",
118
+ "campaignName", "campaignId"
119
+ ],
120
+ "reportTypeId": "spCampaigns",
121
+ "format": "GZIP_JSON",
122
+ "groupBy": ["campaign"],
123
+ "timeUnit": "SUMMARY"
124
+ }
125
+ }
126
+
127
+ try:
128
+ # Submit report
129
+ result = reports.Reports(marketplace=Marketplaces.NA).post_report(body=report_body)
130
+ report_id = result.payload['reportId']
131
+
132
+ click.echo(f"Report submitted: {report_id}")
133
+ click.echo("Polling for completion...")
134
+
135
+ # Poll
136
+ import time
137
+ for i in range(20):
138
+ result = reports.Reports(marketplace=Marketplaces.NA).get_report(reportId=report_id)
139
+ status = result.payload.get('status')
140
+
141
+ if status == 'COMPLETED':
142
+ # Download
143
+ import requests
144
+ import gzip
145
+
146
+ url = result.payload.get('url')
147
+ response = requests.get(url)
148
+ data = gzip.decompress(response.content)
149
+ report_data = json.loads(data)
150
+
151
+ click.echo(f"\n{'Campaign':<30} {'Impr':>8} {'Clicks':>7} {'Spend':>8} {'Sales':>8} {'ACOS'}")
152
+ click.echo("-" * 75)
153
+
154
+ for row in report_data:
155
+ camp_name = row.get('campaignName', 'N/A')[:28]
156
+ impr = int(row.get('impressions', 0) or 0)
157
+ clicks = int(row.get('clicks', 0) or 0)
158
+ cost = float(row.get('cost', 0) or 0)
159
+ sales = float(row.get('sales14d', 0) or 0)
160
+ acos = (cost / sales * 100) if sales > 0 else 0
161
+
162
+ click.echo(f"{camp_name:<30} {impr:>8} {clicks:>7} ${cost:>7.2f} ${sales:>7.2f} {acos:>5.1f}%")
163
+
164
+ return
165
+
166
+ elif status == 'FAILED':
167
+ click.echo(f"❌ Report failed: {result.payload.get('failureReason')}")
168
+ return
169
+
170
+ time.sleep(3)
171
+
172
+ click.echo("⏳ Report still processing...")
173
+
174
+ except Exception as e:
175
+ click.echo(f"❌ Error: {e}")
176
+
177
+
178
+ if __name__ == '__main__':
179
+ cli()
@@ -0,0 +1,26 @@
1
+ Metadata-Version: 2.4
2
+ Name: amazon-ads-cli
3
+ Version: 0.1.0
4
+ Summary: CLI tool for Amazon Advertising API v3
5
+ Home-page: https://github.com/stellaraether/amazon-ads-cli
6
+ Author: Lunan Li
7
+ Author-email: lunan@stellaraether.com
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Requires-Python: >=3.8
17
+ Requires-Dist: click>=8.0
18
+ Requires-Dist: python-amazon-ad-api>=0.8.0
19
+ Requires-Dist: requests>=2.27.0
20
+ Dynamic: author
21
+ Dynamic: author-email
22
+ Dynamic: classifier
23
+ Dynamic: home-page
24
+ Dynamic: requires-dist
25
+ Dynamic: requires-python
26
+ Dynamic: summary
@@ -0,0 +1,7 @@
1
+ amazon_ads_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ amazon_ads_cli/main.py,sha256=GdFvKFk-YED1aEpR62CaxAPE23_TFdQFOvAdXp8HO2c,5721
3
+ amazon_ads_cli-0.1.0.dist-info/METADATA,sha256=jhg00whQ_oDToRRPsBQGkKho1CtCu8ornaUQP0azHM8,875
4
+ amazon_ads_cli-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
5
+ amazon_ads_cli-0.1.0.dist-info/entry_points.txt,sha256=P38Vgnekn6df-4yzQA8Orq2lh-PI3vsrzjlgmUOfijE,52
6
+ amazon_ads_cli-0.1.0.dist-info/top_level.txt,sha256=GRjjCDi-AmBdH1rQI6sZocWzPi9pMEZx8V05VXiBNcw,15
7
+ amazon_ads_cli-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ amz-ads = amazon_ads_cli.main:cli
@@ -0,0 +1 @@
1
+ amazon_ads_cli