|
| 1 | +import itertools |
| 2 | +import json |
| 3 | +import os |
| 4 | +import platform |
| 5 | +import shutil |
| 6 | +import sys |
| 7 | +import urllib.error |
| 8 | +import urllib.parse |
| 9 | +import urllib.request |
| 10 | + |
| 11 | +with open(os.environ['NIX_ATTRS_JSON_FILE']) as env_file: |
| 12 | + ENV = json.load(env_file) |
| 13 | + |
| 14 | +USER_AGENT = f'Python/{platform.python_version()} Nixpkgs/{ENV['nixpkgsVersion']}' |
| 15 | +TIMEOUT = float(os.environ.get('NIX_CONNECT_TIMEOUT') or '15') |
| 16 | + |
| 17 | +ENDPOINT = ENV['endpoint'] |
| 18 | +GAME_URL = ENV['gameUrl'] |
| 19 | +UPLOAD_ID = ENV['upload'] |
| 20 | + |
| 21 | +def abort(message): |
| 22 | + if 'extraMessage' in ENV: |
| 23 | + message = f'{message} {ENV['extraMessage']}' |
| 24 | + print(message, file=sys.stderr) |
| 25 | + sys.exit(1) |
| 26 | + |
| 27 | +try: |
| 28 | + API_KEY = os.environ[ENV['apiKeyVar']] |
| 29 | +except KeyError: |
| 30 | + abort( |
| 31 | + f'Either set {ENV['apiKeyVar']} for the nix building process ' |
| 32 | + f'or manually download {ENV.get('uploadName', 'the required file')} ' |
| 33 | + f'from {GAME_URL} and add it to nix store.' |
| 34 | + ) |
| 35 | + |
| 36 | +def urlopen(url_or_request): |
| 37 | + return urllib.request.urlopen(url_or_request, timeout=TIMEOUT) |
| 38 | + |
| 39 | +with urlopen(f'{GAME_URL}/data.json') as response: |
| 40 | + data = json.load(response) |
| 41 | + GAME_ID = data['id'] |
| 42 | + IS_FREE = 'price' not in data |
| 43 | + |
| 44 | +def api(path, params={}, download=False): |
| 45 | + url = f'{ENDPOINT}{path}?{urllib.parse.urlencode({'api_key': API_KEY, **params})}' |
| 46 | + if download and ENV['showUrl']: |
| 47 | + with open(os.environ['out'], 'w') as output_file: |
| 48 | + print(url, file=output_file) |
| 49 | + return |
| 50 | + request = urllib.request.Request(url, headers={'User-Agent': USER_AGENT}) |
| 51 | + with urlopen(request) as response: |
| 52 | + if download: |
| 53 | + with open(os.environ['out'], 'wb') as output_file: |
| 54 | + shutil.copyfileobj(response, output_file) |
| 55 | + else: |
| 56 | + return json.load(response) |
| 57 | + |
| 58 | +if IS_FREE: |
| 59 | + api(f'/uploads/{UPLOAD_ID}/download', download=True) |
| 60 | + sys.exit() |
| 61 | + |
| 62 | +KEY_ID = None |
| 63 | +for page in itertools.count(1): |
| 64 | + data = api('/profile/owned-keys', {'page': page}) |
| 65 | + if 'owned_keys' not in data: |
| 66 | + break |
| 67 | + for key in data['owned_keys']: |
| 68 | + if key['game_id'] == GAME_ID: |
| 69 | + KEY_ID = key['id'] |
| 70 | + break |
| 71 | + if len(data['owned_keys']) < data['per_page']: |
| 72 | + break |
| 73 | +if not KEY_ID: |
| 74 | + abort(f'Cannot find a key associated with {GAME_URL}. Did you buy the game?') |
| 75 | + |
| 76 | +api(f'/uploads/{UPLOAD_ID}/download', {'download_key_id': KEY_ID}, download=True) |
0 commit comments