-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathget_app_sales.py
executable file
·142 lines (121 loc) · 4.55 KB
/
get_app_sales.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/env
# 0 Provider
# 1 Provider Country
# 2 SKU
# 3 Developer
# 4 Title
# 5 Version
# 6 Product Type Identifier
# 7 Units
# 8 Developer Proceed
# 9 Begin Date
# 10 End Date
# 11 Customer Currency
# 12 Country Code
# 13 Currency of Proceeds
# 14 Apple Identifier
# 15 Customer Price
# 16 Promo Code
# 17 Parent Identifier
# 18 Subscription
# 19 Period
# 20 Category
# 21 CMB
# 22 Device
# 23 Supported Platforms
# 24 Proceeds Reason
# 25 Preserved Pricing
# 26 Client
# 27 Order Type
import collections
import configparser
import datetime
import gzip
import json
import os
import time
import jwt
import requests
BASE_URL = "https://api.appstoreconnect.apple.com/v1"
# time that token will be valid for (can't be for more than 20 mins)
VALID_TIME = 20 * 60 # seconds
APP_COLORS = {"1RM": "yellow", "Simple Checklist : Repeat it": "orange", "Quantified Groceries": "green"}
def retrieve_sales(n_weeks=10):
config = configparser.ConfigParser()
config.read(os.path.expanduser("~/.appstore"))
user = config.sections()[0]
key_id = config.get(user, 'key_id')
header = {"alg": "ES256", "kid": key_id, "typ": "JWT"}
now = time.time()
expiration = int(now + VALID_TIME)
issuer_id = config.get(user, "issuer_id")
payload = {"iss": issuer_id, "exp": expiration, "aud": "appstoreconnect-v1"}
private_key_filename = os.path.join(os.path.expanduser("~/data"), f"AuthKey_{key_id}.p8")
with open(private_key_filename, "r") as f:
lines = f.readlines()
key = ''.join(lines)
signature = jwt.encode(payload, key, algorithm="ES256", headers=header)
signature = str(signature, "utf-8")
vendor_number = config.get(user, "vendor_number")
url = f"{BASE_URL}/salesReports"
header = {"Authorization": f"Bearer {signature}"}
parameters = {"filter[frequency]": "WEEKLY",
"filter[reportType]": "SALES",
"filter[reportSubType]": "SUMMARY",
"filter[vendorNumber]": f"{vendor_number}",
"filter[reportDate]": "2019-06-02"}
today = datetime.date.today()
days_ago = (today.weekday() - 6) % 7
last_sunday = today - datetime.timedelta(days=days_ago)
all_counters = list()
apps = set()
for i in range(n_weeks):
counter = collections.defaultdict(int)
parameters['filter[reportDate]'] = last_sunday.strftime('%Y-%m-%d')
response = requests.get(url, params=parameters, headers=header)
#print(f"curl -v -H 'Authorization: Bearer {signature}' \"{url}\"")
#print(f"status code: {response.status_code}")
if response.status_code == 200:
data = str(gzip.decompress(response.content), "utf-8")
# first row is header
# title is column 4, units is column 7, developer proceeds is column 8
lines = data.split("\n")
for i, line in enumerate(lines):
if i == 0: continue
if len(line) == 0: continue
tokens = line.split("\t")
if float(tokens[8]) == 0.0: continue
counter[tokens[4]] += int(tokens[7])
apps.add(tokens[4])
#print(f"Report: {last_sunday}, Product: {tokens[4]}, Units: {tokens[7]}")
else:
print(f"Problem retrieves sales data, response code {response.status_code}")
print(response.content)
last_sunday = last_sunday - datetime.timedelta(days=7)
all_counters.insert(0, {"date": last_sunday, "units": counter})
return apps, all_counters
def translate_to_statusboard(apps, sales_units):
datasequences = []
for app_name in apps:
seq = [{"title": week["date"].strftime("%Y-%V"),
"value": week["units"][app_name]}
for week in sales_units]
app = {"title": app_name, "color": APP_COLORS[app_name], "datapoints": seq}
datasequences.append(app)
return datasequences
def output_json(apps, sales_units, filename):
datasequences = translate_to_statusboard(apps, sales_units)
statusboard = {"graph": {"title": "App sales",
"total": False,
"type": "bar",
"refreshEveryNSeconds": 3600,
"datasequences": datasequences}}
json_output = json.dumps(statusboard)
with open(filename, 'w') as f:
f.write(json_output)
def main():
apps, sales_units = retrieve_sales(n_weeks=26)
data_dir = os.path.expanduser("~/data")
output_json(apps, sales_units, os.path.join(data_dir, "ios-app-sales.json"))
if __name__ == "__main__":
main()