-
Notifications
You must be signed in to change notification settings - Fork 3
/
android_version_checker.py
128 lines (115 loc) · 4.98 KB
/
android_version_checker.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
# -*- coding: utf-8 -*-
import sys
import logging.handlers
import os
import re
# noinspection PyUnresolvedReferences
import apiclient
import httplib2
from oauth2client.service_account import ServiceAccountCredentials
from flask import Flask, request
from flask_restful import Resource, Api, abort
from flask_cache import Cache
app = Flask(__name__)
api = Api(app)
cache = Cache(app, config={'CACHE_TYPE': 'simple'})
class GetAppVersion(Resource):
credentials = None
package_name = ''
package_name_undefined = ("The package name undefined. Example:"
"com.android.sample")
cache_empty = ("Cache for {0} is empty or expired. Try to get version"
" from Google. Loading key file")
cant_load_credentials = ("Can`t load credentials. The key file is empty "
"or corrupted. Contact your server "
"administrator.")
version_notfound = "No one valid version for {0} was found."
cant_find = "Can`t find package {0}"
error_400 = "Can`t get android version for some reason"
# noinspection PyBroadException
@property
def get(self):
args = request.args
if args['id'].isspace():
self.abort(400, self.package_name_undefined)
self.package_name = args['id']
app.logger.info('Try loading version from cache')
formatted_version = cache.get
if formatted_version is not None:
app.logger.info('Done from cache')
return {'last_version': formatted_version}
app.logger.info(self.cache_empty.format(self.package_name))
try:
self.load_credentials()
except:
abort(501, message=self.cant_load_credentials)
try:
return{"last_version": self.proceed_query(*self.parse_mask(args))}
except IndexError:
self.abort(422, self.version_notfound.format(self.package_name))
except apiclient.errors.HttpError:
self.abort(422, self.cant_find.format(self.package_name))
except:
self.abort(400, self.error_400)
def abort(self, error, message):
app.logger.error(sys.exc_info()[0])
abort(error, message=message)
@staticmethod
def parse_mask(args):
# mask of your version code. H - Major, L- Minor, P-Patch, I-ignore
mask = 'HILPIII' if 'mask' not in args else args['mask']
# get list of index ignored symbols
ignore = [m.start() for m in re.finditer('I', mask)]
major = mask.count('H') # calc Major symbols
minor = mask.count('L') # calc Minor symbols
patch = mask.count('P') # calc Patch symbols
return ignore, major, minor, patch
def load_credentials(self):
self.credentials = ServiceAccountCredentials.from_json_keyfile_name(
os.path.dirname(os.path.abspath(__file__)) + '/key.json',
scopes='https://www.googleapis.com/auth/androidpublisher')
def proceed_query(self, ignore, major, minor, patch):
app.logger.info("Request for {0} started".format(self.package_name))
http = httplib2.Http()
http = self.credentials.authorize(http)
service = apiclient.discovery.build('androidpublisher', 'v2',
http=http)
edit_request = service.edits().insert(body={},
packageName=self.package_name)
result = edit_request.execute()
edit_id = result['id']
apks_result = service.edits().apks().list(
editId=edit_id, packageName=self.package_name).execute()
app.logger.info("Request for {0} completed".format(self.package_name))
last_version = str(apks_result['apks'][-1]['versionCode'])
# remove ignored symbols
for i in range(len(ignore)):
last_version = last_version[:ignore[i] - i] + \
last_version[ignore[i] + 1 - i:]
formatted_version = '{0}.{1}.{2}'.format(
last_version[0:major],
last_version[major:major + minor],
last_version[major + minor:major + minor + patch])
app.logger.info('Save to cache')
# Usually releasing new app version take 4 hours. That's why we
# save version to cache for 4 hours
cache.set(self.package_name, formatted_version, timeout=4 * 60 * 60)
return formatted_version
api.add_resource(GetAppVersion, '/')
if __name__ == '__main__':
handler = logging.handlers.RotatingFileHandler(
os.path.dirname(os.path.abspath(__file__)) +
'/logs/android_version_checker.log',
maxBytes=10000,
backupCount=1)
formatter = logging.Formatter(
"[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s")
handler.setLevel(logging.INFO)
handler.setFormatter(formatter)
app.logger.addHandler(handler)
app.logger.info('Android app version checker started on port 5005')
app.run(
host="0.0.0.0",
port=5005,
debug=True
)