@daemux/store-automator 0.10.26 → 0.10.28
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.
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
},
|
|
6
6
|
"metadata": {
|
|
7
7
|
"description": "App Store & Google Play automation for Flutter apps",
|
|
8
|
-
"version": "0.10.
|
|
8
|
+
"version": "0.10.28"
|
|
9
9
|
},
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "store-automator",
|
|
13
13
|
"source": "./plugins/store-automator",
|
|
14
14
|
"description": "3 agents for app store publishing: reviewer, meta-creator, media-designer",
|
|
15
|
-
"version": "0.10.
|
|
15
|
+
"version": "0.10.28",
|
|
16
16
|
"keywords": [
|
|
17
17
|
"flutter",
|
|
18
18
|
"app-store",
|
package/package.json
CHANGED
|
@@ -24,7 +24,11 @@ from asc_iap_api import BASE_URL, TIMEOUT, print_api_errors
|
|
|
24
24
|
# ---------------------------------------------------------------------------
|
|
25
25
|
|
|
26
26
|
def get_subscription_availability(headers: dict, sub_id: str) -> dict | None:
|
|
27
|
-
"""Fetch current availability settings for a subscription.
|
|
27
|
+
"""Fetch current availability settings for a subscription.
|
|
28
|
+
|
|
29
|
+
Returns the availability resource or None if not yet configured.
|
|
30
|
+
Does not include territory details to avoid ASC API limit errors.
|
|
31
|
+
"""
|
|
28
32
|
resp = requests.get(
|
|
29
33
|
f"{BASE_URL}/subscriptions/{sub_id}/subscriptionAvailability",
|
|
30
34
|
headers=headers,
|
|
@@ -38,6 +42,23 @@ def get_subscription_availability(headers: dict, sub_id: str) -> dict | None:
|
|
|
38
42
|
return resp.json().get("data")
|
|
39
43
|
|
|
40
44
|
|
|
45
|
+
def list_all_territory_ids(headers: dict) -> list[str]:
|
|
46
|
+
"""Fetch all App Store territory IDs."""
|
|
47
|
+
url: str | None = f"{BASE_URL}/territories"
|
|
48
|
+
params: dict | None = {"limit": 200}
|
|
49
|
+
all_ids: list[str] = []
|
|
50
|
+
while url:
|
|
51
|
+
resp = requests.get(url, headers=headers, params=params, timeout=TIMEOUT)
|
|
52
|
+
if not resp.ok:
|
|
53
|
+
print_api_errors(resp, "list territories")
|
|
54
|
+
return all_ids
|
|
55
|
+
data = resp.json()
|
|
56
|
+
all_ids.extend(t["id"] for t in data.get("data", []))
|
|
57
|
+
url = data.get("links", {}).get("next")
|
|
58
|
+
params = None
|
|
59
|
+
return all_ids
|
|
60
|
+
|
|
61
|
+
|
|
41
62
|
def create_subscription_availability(
|
|
42
63
|
headers: dict,
|
|
43
64
|
sub_id: str,
|
|
@@ -40,6 +40,7 @@ from asc_subscription_setup import (
|
|
|
40
40
|
get_review_screenshot,
|
|
41
41
|
get_subscription_availability,
|
|
42
42
|
get_subscription_prices,
|
|
43
|
+
list_all_territory_ids,
|
|
43
44
|
reserve_review_screenshot,
|
|
44
45
|
upload_screenshot_chunks,
|
|
45
46
|
)
|
|
@@ -119,21 +120,32 @@ def sync_subscription_group(
|
|
|
119
120
|
|
|
120
121
|
|
|
121
122
|
def _sync_availability(headers: dict, sub_id: str, sub_config: dict) -> None:
|
|
122
|
-
"""Ensure subscription territory availability is configured.
|
|
123
|
-
avail_config = sub_config.get("availability", {})
|
|
124
|
-
available_in_new = avail_config.get("available_in_new_territories", True)
|
|
125
|
-
territory_ids = avail_config.get("territories", [])
|
|
123
|
+
"""Ensure subscription territory availability is configured with all territories.
|
|
126
124
|
|
|
125
|
+
If availability already exists, it is left as-is (idempotent skip).
|
|
126
|
+
Otherwise fetches all App Store territories and creates availability.
|
|
127
|
+
"""
|
|
127
128
|
existing = get_subscription_availability(headers, sub_id)
|
|
128
129
|
if existing:
|
|
129
|
-
print("
|
|
130
|
+
print(" Availability already configured")
|
|
130
131
|
return
|
|
131
132
|
|
|
133
|
+
avail_config = sub_config.get("availability", {})
|
|
134
|
+
available_in_new = avail_config.get("available_in_new_territories", True)
|
|
135
|
+
territory_ids = avail_config.get("territories", [])
|
|
136
|
+
|
|
137
|
+
# If no territories specified, fetch all to make available everywhere
|
|
138
|
+
if not territory_ids:
|
|
139
|
+
territory_ids = list_all_territory_ids(headers)
|
|
140
|
+
if not territory_ids:
|
|
141
|
+
print(" WARNING: Could not fetch territories", file=sys.stderr)
|
|
142
|
+
return
|
|
143
|
+
|
|
132
144
|
result = create_subscription_availability(
|
|
133
145
|
headers, sub_id, territory_ids, available_in_new=available_in_new,
|
|
134
146
|
)
|
|
135
147
|
if result:
|
|
136
|
-
print("
|
|
148
|
+
print(f" Availability set ({len(territory_ids)} territories)")
|
|
137
149
|
else:
|
|
138
150
|
print(" WARNING: Failed to configure availability", file=sys.stderr)
|
|
139
151
|
|
|
@@ -178,16 +190,38 @@ def _sync_pricing(headers: dict, sub_id: str, sub_config: dict) -> None:
|
|
|
178
190
|
def _sync_review_screenshot(
|
|
179
191
|
headers: dict, sub_id: str, sub_config: dict, project_root: str,
|
|
180
192
|
) -> None:
|
|
181
|
-
"""Upload a review screenshot for the subscription if configured.
|
|
193
|
+
"""Upload a review screenshot for the subscription if configured.
|
|
194
|
+
|
|
195
|
+
Falls back to the first iPhone screenshot from fastlane/screenshots/ios/en-US/
|
|
196
|
+
when the configured path does not exist.
|
|
197
|
+
"""
|
|
182
198
|
screenshot_path = sub_config.get("review_screenshot")
|
|
183
199
|
if not screenshot_path:
|
|
184
200
|
print(" WARNING: No review_screenshot configured, skipping", file=sys.stderr)
|
|
185
201
|
return
|
|
186
202
|
|
|
187
203
|
full_path = os.path.join(project_root, screenshot_path)
|
|
204
|
+
|
|
205
|
+
# Fallback: if configured path doesn't exist, pick first iPhone screenshot
|
|
188
206
|
if not os.path.isfile(full_path):
|
|
189
|
-
|
|
190
|
-
|
|
207
|
+
fallback = None
|
|
208
|
+
ios_dir = os.path.join(project_root, "fastlane", "screenshots", "ios", "en-US")
|
|
209
|
+
if os.path.isdir(ios_dir):
|
|
210
|
+
for f in sorted(os.listdir(ios_dir)):
|
|
211
|
+
if f.lower().endswith(".png") and "iphone" in f.lower():
|
|
212
|
+
fallback = os.path.join(ios_dir, f)
|
|
213
|
+
break
|
|
214
|
+
if not fallback:
|
|
215
|
+
for f in sorted(os.listdir(ios_dir)):
|
|
216
|
+
if f.lower().endswith(".png"):
|
|
217
|
+
fallback = os.path.join(ios_dir, f)
|
|
218
|
+
break
|
|
219
|
+
if fallback:
|
|
220
|
+
full_path = fallback
|
|
221
|
+
print(f" Using fallback screenshot: {os.path.basename(full_path)}")
|
|
222
|
+
else:
|
|
223
|
+
print(f" WARNING: Screenshot not found: {full_path}", file=sys.stderr)
|
|
224
|
+
return
|
|
191
225
|
|
|
192
226
|
existing = get_review_screenshot(headers, sub_id)
|
|
193
227
|
if existing:
|