direct-cli 0.0.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.
- direct_cli/__init__.py +14 -0
- direct_cli/api.py +94 -0
- direct_cli/auth.py +58 -0
- direct_cli/cli.py +85 -0
- direct_cli/commands/__init__.py +61 -0
- direct_cli/commands/adextensions.py +96 -0
- direct_cli/commands/adgroups.py +189 -0
- direct_cli/commands/adimages.py +63 -0
- direct_cli/commands/ads.py +306 -0
- direct_cli/commands/agencyclients.py +64 -0
- direct_cli/commands/audiencetargets.py +187 -0
- direct_cli/commands/bidmodifiers.py +110 -0
- direct_cli/commands/bids.py +108 -0
- direct_cli/commands/businesses.py +61 -0
- direct_cli/commands/campaigns.py +311 -0
- direct_cli/commands/changes.py +97 -0
- direct_cli/commands/clients.py +98 -0
- direct_cli/commands/creatives.py +68 -0
- direct_cli/commands/dictionaries.py +64 -0
- direct_cli/commands/dynamicads.py +104 -0
- direct_cli/commands/feeds.py +99 -0
- direct_cli/commands/keywordbids.py +111 -0
- direct_cli/commands/keywords.py +309 -0
- direct_cli/commands/keywordsresearch.py +71 -0
- direct_cli/commands/leads.py +65 -0
- direct_cli/commands/negativekeywordsharedsets.py +97 -0
- direct_cli/commands/reports.py +128 -0
- direct_cli/commands/retargeting.py +104 -0
- direct_cli/commands/sitelinks.py +92 -0
- direct_cli/commands/smartadtargets.py +104 -0
- direct_cli/commands/turbopages.py +97 -0
- direct_cli/commands/vcards.py +93 -0
- direct_cli/output.py +143 -0
- direct_cli/utils.py +120 -0
- direct_cli-0.0.0.dist-info/METADATA +393 -0
- direct_cli-0.0.0.dist-info/RECORD +39 -0
- direct_cli-0.0.0.dist-info/WHEEL +5 -0
- direct_cli-0.0.0.dist-info/entry_points.txt +2 -0
- direct_cli-0.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Creatives commands
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from ..api import create_client
|
|
8
|
+
from ..output import format_output, print_error
|
|
9
|
+
from ..utils import parse_ids
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@click.group()
|
|
13
|
+
def creatives():
|
|
14
|
+
"""Manage creatives"""
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@creatives.command()
|
|
19
|
+
@click.option("--ids", help="Comma-separated creative IDs")
|
|
20
|
+
@click.option("--campaign-ids", help="Comma-separated campaign IDs")
|
|
21
|
+
@click.option("--limit", type=int, help="Limit number of results")
|
|
22
|
+
@click.option("--fetch-all", is_flag=True, help="Fetch all pages")
|
|
23
|
+
@click.option("--format", "output_format", default="json", help="Output format")
|
|
24
|
+
@click.option("--output", help="Output file")
|
|
25
|
+
@click.option("--fields", help="Comma-separated field names")
|
|
26
|
+
@click.pass_context
|
|
27
|
+
def get(ctx, ids, campaign_ids, limit, fetch_all, output_format, output, fields):
|
|
28
|
+
"""Get creatives"""
|
|
29
|
+
try:
|
|
30
|
+
client = create_client(
|
|
31
|
+
token=ctx.obj.get("token"),
|
|
32
|
+
login=ctx.obj.get("login"),
|
|
33
|
+
sandbox=ctx.obj.get("sandbox"),
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
field_names = (
|
|
37
|
+
fields.split(",")
|
|
38
|
+
if fields
|
|
39
|
+
else ["Id", "Name", "Type", "Status", "CampaignId"]
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
criteria = {}
|
|
43
|
+
if ids:
|
|
44
|
+
criteria["Ids"] = parse_ids(ids)
|
|
45
|
+
if campaign_ids:
|
|
46
|
+
criteria["CampaignIds"] = parse_ids(campaign_ids)
|
|
47
|
+
|
|
48
|
+
params = {"SelectionCriteria": criteria, "FieldNames": field_names}
|
|
49
|
+
|
|
50
|
+
if limit:
|
|
51
|
+
params["Page"] = {"Limit": limit}
|
|
52
|
+
|
|
53
|
+
body = {"method": "get", "params": params}
|
|
54
|
+
|
|
55
|
+
result = client.creatives().post(data=body)
|
|
56
|
+
|
|
57
|
+
if fetch_all:
|
|
58
|
+
items = []
|
|
59
|
+
for item in result().iter_items():
|
|
60
|
+
items.append(item)
|
|
61
|
+
format_output(items, output_format, output)
|
|
62
|
+
else:
|
|
63
|
+
data = result().extract()
|
|
64
|
+
format_output(data, output_format, output)
|
|
65
|
+
|
|
66
|
+
except Exception as e:
|
|
67
|
+
print_error(str(e))
|
|
68
|
+
raise click.Abort()
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Dictionaries commands
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from ..api import create_client
|
|
8
|
+
from ..output import format_output, print_error
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
DICTIONARY_NAMES = [
|
|
12
|
+
"Currencies",
|
|
13
|
+
"MetroStations",
|
|
14
|
+
"GeoRegions",
|
|
15
|
+
"TimeZones",
|
|
16
|
+
"Constants",
|
|
17
|
+
"AdCategories",
|
|
18
|
+
"OperationSystemVersions",
|
|
19
|
+
"ProductivityAssertions",
|
|
20
|
+
"SupplySidePlatforms",
|
|
21
|
+
"Interests",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@click.group()
|
|
26
|
+
def dictionaries():
|
|
27
|
+
"""Get reference dictionaries"""
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dictionaries.command()
|
|
32
|
+
@click.option(
|
|
33
|
+
"--names",
|
|
34
|
+
required=True,
|
|
35
|
+
help="Comma-separated dictionary names (Currencies,GeoRegions,...)",
|
|
36
|
+
)
|
|
37
|
+
@click.option("--format", "output_format", default="json", help="Output format")
|
|
38
|
+
@click.option("--output", help="Output file")
|
|
39
|
+
@click.pass_context
|
|
40
|
+
def get(ctx, names, output_format, output):
|
|
41
|
+
"""Get dictionaries"""
|
|
42
|
+
try:
|
|
43
|
+
client = create_client(
|
|
44
|
+
token=ctx.obj.get("token"),
|
|
45
|
+
login=ctx.obj.get("login"),
|
|
46
|
+
sandbox=ctx.obj.get("sandbox"),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
dictionary_names = [n.strip() for n in names.split(",")]
|
|
50
|
+
|
|
51
|
+
body = {"method": "get", "params": {"DictionaryNames": dictionary_names}}
|
|
52
|
+
|
|
53
|
+
result = client.dictionaries().post(data=body)
|
|
54
|
+
format_output(result.data, output_format, output)
|
|
55
|
+
|
|
56
|
+
except Exception as e:
|
|
57
|
+
print_error(str(e))
|
|
58
|
+
raise click.Abort()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dictionaries.command()
|
|
62
|
+
def list_names():
|
|
63
|
+
"""List available dictionary names"""
|
|
64
|
+
format_output(DICTIONARY_NAMES, "json", None)
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""
|
|
2
|
+
DynamicAds (Webpages) commands
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
from ..api import create_client
|
|
9
|
+
from ..output import format_output, print_error
|
|
10
|
+
from ..utils import parse_ids
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@click.group()
|
|
14
|
+
def dynamicads():
|
|
15
|
+
"""Manage dynamic ad targets"""
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dynamicads.command()
|
|
20
|
+
@click.option("--ids", help="Comma-separated target IDs")
|
|
21
|
+
@click.option("--adgroup-ids", help="Comma-separated ad group IDs")
|
|
22
|
+
@click.option("--limit", type=int, help="Limit number of results")
|
|
23
|
+
@click.option("--fetch-all", is_flag=True, help="Fetch all pages")
|
|
24
|
+
@click.option("--format", "output_format", default="json", help="Output format")
|
|
25
|
+
@click.option("--output", help="Output file")
|
|
26
|
+
@click.option("--fields", help="Comma-separated field names")
|
|
27
|
+
@click.pass_context
|
|
28
|
+
def get(ctx, ids, adgroup_ids, limit, fetch_all, output_format, output, fields):
|
|
29
|
+
"""Get dynamic ad targets"""
|
|
30
|
+
try:
|
|
31
|
+
client = create_client(
|
|
32
|
+
token=ctx.obj.get("token"),
|
|
33
|
+
login=ctx.obj.get("login"),
|
|
34
|
+
sandbox=ctx.obj.get("sandbox"),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
field_names = (
|
|
38
|
+
fields.split(",") if fields else ["Id", "AdGroupId", "Condition", "Bid"]
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
criteria = {}
|
|
42
|
+
if ids:
|
|
43
|
+
criteria["Ids"] = parse_ids(ids)
|
|
44
|
+
if adgroup_ids:
|
|
45
|
+
criteria["AdGroupIds"] = parse_ids(adgroup_ids)
|
|
46
|
+
|
|
47
|
+
params = {"SelectionCriteria": criteria, "FieldNames": field_names}
|
|
48
|
+
|
|
49
|
+
if limit:
|
|
50
|
+
params["Page"] = {"Limit": limit}
|
|
51
|
+
|
|
52
|
+
body = {"method": "get", "params": params}
|
|
53
|
+
|
|
54
|
+
result = client.dynamicads().post(data=body)
|
|
55
|
+
|
|
56
|
+
if fetch_all:
|
|
57
|
+
items = []
|
|
58
|
+
for item in result().iter_items():
|
|
59
|
+
items.append(item)
|
|
60
|
+
format_output(items, output_format, output)
|
|
61
|
+
else:
|
|
62
|
+
data = result().extract()
|
|
63
|
+
format_output(data, output_format, output)
|
|
64
|
+
|
|
65
|
+
except Exception as e:
|
|
66
|
+
print_error(str(e))
|
|
67
|
+
raise click.Abort()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dynamicads.command()
|
|
71
|
+
@click.option("--adgroup-id", required=True, type=int, help="Ad group ID")
|
|
72
|
+
@click.option(
|
|
73
|
+
"--condition", required=True, help='Target condition (e.g., "contains:product")'
|
|
74
|
+
)
|
|
75
|
+
@click.option("--json", "extra_json", help="Additional JSON parameters")
|
|
76
|
+
@click.option("--dry-run", is_flag=True, help="Show request without sending")
|
|
77
|
+
@click.pass_context
|
|
78
|
+
def add(ctx, adgroup_id, condition, extra_json, dry_run):
|
|
79
|
+
"""Add dynamic ad target"""
|
|
80
|
+
try:
|
|
81
|
+
target_data = {"AdGroupId": adgroup_id, "Condition": condition}
|
|
82
|
+
|
|
83
|
+
if extra_json:
|
|
84
|
+
extra = json.loads(extra_json)
|
|
85
|
+
target_data.update(extra)
|
|
86
|
+
|
|
87
|
+
body = {"method": "add", "params": {"Webpages": [target_data]}}
|
|
88
|
+
|
|
89
|
+
if dry_run:
|
|
90
|
+
format_output(body, "json", None)
|
|
91
|
+
return
|
|
92
|
+
|
|
93
|
+
client = create_client(
|
|
94
|
+
token=ctx.obj.get("token"),
|
|
95
|
+
login=ctx.obj.get("login"),
|
|
96
|
+
sandbox=ctx.obj.get("sandbox"),
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
result = client.dynamicads().post(data=body)
|
|
100
|
+
format_output(result().extract(), "json", None)
|
|
101
|
+
|
|
102
|
+
except Exception as e:
|
|
103
|
+
print_error(str(e))
|
|
104
|
+
raise click.Abort()
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Feeds commands
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
from ..api import create_client
|
|
9
|
+
from ..output import format_output, print_error
|
|
10
|
+
from ..utils import parse_ids
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@click.group()
|
|
14
|
+
def feeds():
|
|
15
|
+
"""Manage feeds"""
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@feeds.command()
|
|
20
|
+
@click.option("--ids", help="Comma-separated feed IDs")
|
|
21
|
+
@click.option("--limit", type=int, help="Limit number of results")
|
|
22
|
+
@click.option("--fetch-all", is_flag=True, help="Fetch all pages")
|
|
23
|
+
@click.option("--format", "output_format", default="json", help="Output format")
|
|
24
|
+
@click.option("--output", help="Output file")
|
|
25
|
+
@click.option("--fields", help="Comma-separated field names")
|
|
26
|
+
@click.pass_context
|
|
27
|
+
def get(ctx, ids, limit, fetch_all, output_format, output, fields):
|
|
28
|
+
"""Get feeds"""
|
|
29
|
+
try:
|
|
30
|
+
client = create_client(
|
|
31
|
+
token=ctx.obj.get("token"),
|
|
32
|
+
login=ctx.obj.get("login"),
|
|
33
|
+
sandbox=ctx.obj.get("sandbox"),
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
field_names = (
|
|
37
|
+
fields.split(",") if fields else ["Id", "Name", "Source", "Status"]
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
criteria = {}
|
|
41
|
+
if ids:
|
|
42
|
+
criteria["Ids"] = parse_ids(ids)
|
|
43
|
+
|
|
44
|
+
params = {"SelectionCriteria": criteria, "FieldNames": field_names}
|
|
45
|
+
|
|
46
|
+
if limit:
|
|
47
|
+
params["Page"] = {"Limit": limit}
|
|
48
|
+
|
|
49
|
+
body = {"method": "get", "params": params}
|
|
50
|
+
|
|
51
|
+
result = client.feeds().post(data=body)
|
|
52
|
+
|
|
53
|
+
if fetch_all:
|
|
54
|
+
items = []
|
|
55
|
+
for item in result().iter_items():
|
|
56
|
+
items.append(item)
|
|
57
|
+
format_output(items, output_format, output)
|
|
58
|
+
else:
|
|
59
|
+
data = result().extract()
|
|
60
|
+
format_output(data, output_format, output)
|
|
61
|
+
|
|
62
|
+
except Exception as e:
|
|
63
|
+
print_error(str(e))
|
|
64
|
+
raise click.Abort()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@feeds.command()
|
|
68
|
+
@click.option("--name", required=True, help="Feed name")
|
|
69
|
+
@click.option("--url", required=True, help="Feed URL")
|
|
70
|
+
@click.option("--json", "extra_json", help="Additional JSON parameters")
|
|
71
|
+
@click.option("--dry-run", is_flag=True, help="Show request without sending")
|
|
72
|
+
@click.pass_context
|
|
73
|
+
def add(ctx, name, url, extra_json, dry_run):
|
|
74
|
+
"""Add feed"""
|
|
75
|
+
try:
|
|
76
|
+
feed_data = {"Name": name, "Source": url}
|
|
77
|
+
|
|
78
|
+
if extra_json:
|
|
79
|
+
extra = json.loads(extra_json)
|
|
80
|
+
feed_data.update(extra)
|
|
81
|
+
|
|
82
|
+
body = {"method": "add", "params": {"Feeds": [feed_data]}}
|
|
83
|
+
|
|
84
|
+
if dry_run:
|
|
85
|
+
format_output(body, "json", None)
|
|
86
|
+
return
|
|
87
|
+
|
|
88
|
+
client = create_client(
|
|
89
|
+
token=ctx.obj.get("token"),
|
|
90
|
+
login=ctx.obj.get("login"),
|
|
91
|
+
sandbox=ctx.obj.get("sandbox"),
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
result = client.feeds().post(data=body)
|
|
95
|
+
format_output(result().extract(), "json", None)
|
|
96
|
+
|
|
97
|
+
except Exception as e:
|
|
98
|
+
print_error(str(e))
|
|
99
|
+
raise click.Abort()
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""
|
|
2
|
+
KeywordBids commands
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
from ..api import create_client
|
|
9
|
+
from ..output import format_output, print_error
|
|
10
|
+
from ..utils import parse_ids
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@click.group()
|
|
14
|
+
def keywordbids():
|
|
15
|
+
"""Manage keyword bids"""
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@keywordbids.command()
|
|
20
|
+
@click.option("--keyword-ids", help="Comma-separated keyword IDs")
|
|
21
|
+
@click.option("--adgroup-ids", help="Comma-separated ad group IDs")
|
|
22
|
+
@click.option("--campaign-ids", help="Comma-separated campaign IDs")
|
|
23
|
+
@click.option("--limit", type=int, help="Limit number of results")
|
|
24
|
+
@click.option("--fetch-all", is_flag=True, help="Fetch all pages")
|
|
25
|
+
@click.option("--format", "output_format", default="json", help="Output format")
|
|
26
|
+
@click.option("--output", help="Output file")
|
|
27
|
+
@click.pass_context
|
|
28
|
+
def get(
|
|
29
|
+
ctx, keyword_ids, adgroup_ids, campaign_ids, limit, fetch_all, output_format, output
|
|
30
|
+
):
|
|
31
|
+
"""Get keyword bids"""
|
|
32
|
+
try:
|
|
33
|
+
client = create_client(
|
|
34
|
+
token=ctx.obj.get("token"),
|
|
35
|
+
login=ctx.obj.get("login"),
|
|
36
|
+
sandbox=ctx.obj.get("sandbox"),
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
criteria = {}
|
|
40
|
+
if keyword_ids:
|
|
41
|
+
criteria["KeywordIds"] = parse_ids(keyword_ids)
|
|
42
|
+
if adgroup_ids:
|
|
43
|
+
criteria["AdGroupIds"] = parse_ids(adgroup_ids)
|
|
44
|
+
if campaign_ids:
|
|
45
|
+
criteria["CampaignIds"] = parse_ids(campaign_ids)
|
|
46
|
+
|
|
47
|
+
params = {
|
|
48
|
+
"SelectionCriteria": criteria,
|
|
49
|
+
"FieldNames": ["KeywordId", "AdGroupId", "CampaignId", "Bid", "ContextBid"],
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if limit:
|
|
53
|
+
params["Page"] = {"Limit": limit}
|
|
54
|
+
|
|
55
|
+
body = {"method": "get", "params": params}
|
|
56
|
+
|
|
57
|
+
result = client.keywordbids().post(data=body)
|
|
58
|
+
|
|
59
|
+
if fetch_all:
|
|
60
|
+
items = []
|
|
61
|
+
for item in result().iter_items():
|
|
62
|
+
items.append(item)
|
|
63
|
+
format_output(items, output_format, output)
|
|
64
|
+
else:
|
|
65
|
+
data = result().extract()
|
|
66
|
+
format_output(data, output_format, output)
|
|
67
|
+
|
|
68
|
+
except Exception as e:
|
|
69
|
+
print_error(str(e))
|
|
70
|
+
raise click.Abort()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@keywordbids.command()
|
|
74
|
+
@click.option("--keyword-id", required=True, type=int, help="Keyword ID")
|
|
75
|
+
@click.option("--search-bid", type=float, help="Search bid")
|
|
76
|
+
@click.option("--network-bid", type=float, help="Network bid")
|
|
77
|
+
@click.option("--json", "extra_json", help="Additional JSON parameters")
|
|
78
|
+
@click.option("--dry-run", is_flag=True, help="Show request without sending")
|
|
79
|
+
@click.pass_context
|
|
80
|
+
def set(ctx, keyword_id, search_bid, network_bid, extra_json, dry_run):
|
|
81
|
+
"""Set keyword bids"""
|
|
82
|
+
try:
|
|
83
|
+
bid_data = {"KeywordId": keyword_id}
|
|
84
|
+
|
|
85
|
+
if search_bid:
|
|
86
|
+
bid_data["SearchBid"] = int(search_bid * 1000000)
|
|
87
|
+
if network_bid:
|
|
88
|
+
bid_data["NetworkBid"] = int(network_bid * 1000000)
|
|
89
|
+
|
|
90
|
+
if extra_json:
|
|
91
|
+
extra = json.loads(extra_json)
|
|
92
|
+
bid_data.update(extra)
|
|
93
|
+
|
|
94
|
+
body = {"method": "set", "params": {"KeywordBids": [bid_data]}}
|
|
95
|
+
|
|
96
|
+
if dry_run:
|
|
97
|
+
format_output(body, "json", None)
|
|
98
|
+
return
|
|
99
|
+
|
|
100
|
+
client = create_client(
|
|
101
|
+
token=ctx.obj.get("token"),
|
|
102
|
+
login=ctx.obj.get("login"),
|
|
103
|
+
sandbox=ctx.obj.get("sandbox"),
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
result = client.keywordbids().post(data=body)
|
|
107
|
+
format_output(result().extract(), "json", None)
|
|
108
|
+
|
|
109
|
+
except Exception as e:
|
|
110
|
+
print_error(str(e))
|
|
111
|
+
raise click.Abort()
|