From 65c9fa5dcabaa4bed82362cecfad8fb892256259 Mon Sep 17 00:00:00 2001 From: UncleGoogle Date: Thu, 18 Jul 2019 12:54:47 +0200 Subject: [PATCH] simple download game --- src/consts.py | 32 ++++++++++++++++++++++++++++++++ src/humblegame.py | 28 ++++++++++++++++++++++++++++ src/plugin.py | 39 +++++++++++++++++++++++++++------------ test.py | 9 +++++++++ 4 files changed, 96 insertions(+), 12 deletions(-) create mode 100644 src/consts.py diff --git a/src/consts.py b/src/consts.py new file mode 100644 index 0000000..fe96cbd --- /dev/null +++ b/src/consts.py @@ -0,0 +1,32 @@ +import enum +import sys + + +class PlatformNotSupported(Exception): + pass + + +class HP(enum.Enum): + """HumbleBundle platform code name shown in subproducts>download section""" + WINDOWS = 'windows' + MAC = 'mac' + LINUX = 'linux' + ANDROID = 'android' + AUDIO = 'audio' + EBOOK = 'ebook' + + def __eq__(self, other): + if type(other) == str: + return self.value == other + return super().__eq__(other) + + +GAME_PLATFORMS = [HP.WINDOWS, HP.MAC, HP.LINUX] +DLC_PLATFORMS = [HP.AUDIO, HP.EBOOK] # TODO push those with base game + +if sys.platform == 'win32': + CURRENT_SYSTEM = HP.WINDOWS +elif sys.platform == 'darwin': + CURRENT_SYSTEM = HP.MAC +else: + raise PlatformNotSupported('GOG Galaxy 2.0 supports only Windows and macos for now') diff --git a/src/humblegame.py b/src/humblegame.py index 632213d..73315a2 100644 --- a/src/humblegame.py +++ b/src/humblegame.py @@ -1,5 +1,9 @@ +from typing import Dict + from galaxy.api.types import Game, LicenseType, LicenseInfo +from consts import CURRENT_SYSTEM, PlatformNotSupported + class HumbleGame: def __init__(self, data): @@ -17,3 +21,27 @@ def __repr__(self): def __str__(self): return f"HumbleGame({self.human_name}, {self.downloads})" + +class HumbleDownloader: + """Prepares downloads for specific conditionals""" + def __init__(self, target_platrofm=CURRENT_SYSTEM, target_bitness=None, use_torrent=False): + self.platform = target_platrofm + self.bitness = target_bitness + + def find_best_url(self, downloads: dict) -> Dict[str, str]: + system_downloads = list(filter(lambda x: x['platform'] == self.platform, downloads)) + + if len(system_downloads) == 1: + download_struct = system_downloads[0]['download_struct'] + elif len(system_downloads) == 0: + platforms = [dw.platform for dw in downloads] + raise PlatformNotSupported(f'{self.human_name} has only downloads for {platforms}') + elif len(system_downloads) > 1: + raise NotImplementedError('More system level conditionals required') + + download_items = list(filter(lambda x: x['name'] == 'Download', download_struct)) + + if len(download_items) == 1: + return download_items[0]['url'] + else: + raise NotImplementedError(f'Found downloads: {len(download_items)}. All: {downloads}') diff --git a/src/plugin.py b/src/plugin.py index fca6ea9..1d8be1f 100644 --- a/src/plugin.py +++ b/src/plugin.py @@ -3,6 +3,7 @@ import json import logging import re +import webbrowser from galaxy.api.plugin import Plugin, create_and_run_plugin from galaxy.api.consts import Platform @@ -11,7 +12,8 @@ from version import __version__ from webservice import AuthorizedHumbleAPI -from humblegame import HumbleGame +from humblegame import HumbleGame, HumbleDownloader +from consts import PlatformNotSupported, GAME_PLATFORMS AUTH_PARAMS = { @@ -25,13 +27,12 @@ class HumbleBundlePlugin(Plugin): - GAME_PLATFORMS = ['windows', 'mac', 'linux'] # TODO think about 'android' - DLC_PLATFORMS = ['ebook', 'audio'] # TODO push those with base game def __init__(self, reader, writer, token): super().__init__(Platform.HumbleBundle, __version__, reader, writer, token) self._api = AuthorizedHumbleAPI() self._games = [] + self._downloader = HumbleDownloader() async def authenticate(self, stored_credentials=None): if not stored_credentials: @@ -49,23 +50,37 @@ async def pass_login_credentials(self, step, credentials, cookies): user_id, user_name = await self._api.authenticate(auth_cookie) return Authentication(user_id, user_name) - def _is_game(self, sub): - whitelist = self.GAME_PLATFORMS - default = False - return next(filter(lambda x: x['platform'] in whitelist, sub['downloads']), default) - async def get_owned_games(self): - games = [] + + def is_game(sub): + default = False + return next(filter(lambda x: x['platform'] in GAME_PLATFORMS, sub['downloads']), default) + + games = {} gamekeys = await self._api.get_gamekeys() for gamekey in gamekeys: details = await self._api.get_order_details(gamekey) logging.info(f'Parsing details of order {gamekey}:\n{json.dumps(details, indent=4)}') for sub in details['subproducts']: - if self._is_game(sub): - games.append(HumbleGame(sub)) + if is_game(sub): + games[sub['machine_name']] = HumbleGame(sub) self.games = games - return [g.in_galaxy_format() for g in games] + return [g.in_galaxy_format() for g in games.values()] + + async def install_game(self, game_id): + game = self.games.get(game_id) + if game is None: + logging.error(f'Install game: game {game_id} not found') + return + + try: + url = self._downloader.find_best_url(game.downloads) + except Exception as e: + logging.exception(e) + else: + webbrowser.open(url['web']) + def shutdown(self): self._api._session.close() diff --git a/test.py b/test.py index 97df312..28a84c8 100644 --- a/test.py +++ b/test.py @@ -59,6 +59,15 @@ async def run_server_connection(reader, writer): # ret = await reader.readline() # print("ret", ret) + print("install_game") + writer.write(b'{"jsonrpc": "2.0", "method": "install_game", "params":{"game_id": "samorost2"}}\n') + + # print("launch_game") + # writer.write(b'{"jsonrpc": "2.0", "method": "launch_game", "params":{"game_id": "samorost2"}}\n') + + # print("uninstall_game") + # writer.write(b'{"jsonrpc": "2.0", "method": "uninstall_game", "params":{"game_id": "samorost2"}}\n') + async def wakeup(): while True: await asyncio.sleep(1)