def __download_file(self, download):
     self.prepare_location(download.save_location)
     download_max_attempts = 5
     download_attempt = 0
     result = False
     while download_attempt < download_max_attempts:
         try:
             start_point, download_mode = self.get_start_point_and_download_mode(
                 download)
             result = self.download_operation(download, start_point,
                                              download_mode)
             break
         except ConnectionError as e:
             print(e)
             download_attempt += 1
     # mark download as complete
     self.__mark_download_as_complete(download, result)
     # Successful downloads
     if result:
         if download.number == download.out_of_amount:
             finish_thread = threading.Thread(target=download.finish)
             finish_thread.start()
         if self.__queue.empty():
             Config.unset("current_download")
     # Unsuccessful downloads and cancels
     else:
         self.__cancel = False
         download.cancel()
         self.__current_download = None
         os.remove(download.save_location)
Example #2
0
    def __download_update(self, game: Game = None) -> None:
        Config.set("current_download", game.id)
        GLib.idle_add(self.__update_to_state, game.state.UPDATE_QUEUED, game)
        download_info = self.api.get_download_info(game)

        # Start the download for all files
        game.downloads = []
        download_path = game.update_path
        finish_func = self.__update
        for key, file_info in enumerate(download_info['files']):
            if key > 0:
                download_path = "{}-{}.bin".format(self.update_path, key)
            download = Download(url=self.api.get_real_download_link(
                file_info["downlink"]),
                                save_location=download_path,
                                finish_func=finish_func,
                                finish_func_args=game,
                                progress_func=self.set_progress,
                                progress_func_args=game,
                                cancel_func=self.__cancel_update,
                                cancel_func_args=game,
                                number=key + 1,
                                out_of_amount=len(download_info['files']))
            game.downloads.append(download)

        DownloadManager.download(game.downloads)
Example #3
0
    def __init__(self, parent):
        Gtk.Dialog.__init__(self, title=_("Preferences"), parent=parent, modal=True)
        self.parent = parent
        self.__set_language_list()
        self.button_file_chooser.set_filename(Config.get("install_dir"))
        self.switch_keep_installers.set_active(Config.get("keep_installers"))
        self.switch_stay_logged_in.set_active(Config.get("stay_logged_in"))
        self.switch_show_fps.set_active(Config.get("show_fps"))
        self.switch_show_windows_games.set_active(Config.get("show_windows_games"))
        self.switch_create_shortcuts.set_active(Config.get("create_shortcuts"))
        self.switch_install_dlcs.set_active(Config.get("install_dlcs"))
        self.switch_automatic_updates.set_active(Config.get("automatic_updates"))
        self.switch_do_not_show_backgrounds.set_active(Config.get("do_not_show_backgrounds"))
        self.switch_do_not_show_media_tab.set_active(Config.get("do_not_show_media_tab"))

        # Set tooltip for keep installers label
        installer_dir = os.path.join(self.button_file_chooser.get_filename(), "installer")
        self.label_keep_installers.set_tooltip_text(
            _("Keep installers after downloading a game.\nInstallers are stored in: {}").format(installer_dir)
        )

        # Only allow showing Windows games if wine is available
        if not shutil.which("wine"):
            self.switch_show_windows_games.set_sensitive(False)
            self.switch_show_windows_games.set_tooltip_text(
                _("Install Wine to enable this feature")
            )
Example #4
0
    def __save_install_dir_choice(self) -> bool:
        choice = self.button_file_chooser.get_filename()
        old_dir = Config.get("install_dir")
        if choice == old_dir:
            return True

        if not os.path.exists(choice):
            try:
                os.makedirs(choice)
            except:
                return False
        else:
            write_test_file = os.path.join(choice, "write_test.txt")
            try:
                with open(write_test_file, "w") as file:
                    file.write("test")
                    file.close()
                os.remove(write_test_file)
            except:
                return False
        # Remove the old directory if it is empty
        try:
            os.rmdir(old_dir)
        except OSError:
            pass

        Config.set("install_dir", choice)
        return True
Example #5
0
 def test_unset(self, mock_isfile):
     mock_isfile.return_value = True
     config = JSON_DEFAULT_CONFIGURATION
     with patch("builtins.open", mock_open(read_data=config)):
         from goodoldgalaxy.config import Config
         Config.unset("lang")
         lang = Config.get("lang")
     exp = None
     obs = lang
     self.assertEqual(exp, obs)
Example #6
0
    def __init__(self, 
                 name: str, 
                 url: str = None, 
                 game_id: int = 0
        ):
        self.name = name
        self.url = url
        self.id = game_id
        self.install_dir: str = None
        self.image_url: str = None
        self.icon_url: str = None
        self.sidebar_icon_url: str = None
        self.logo_url: str = None
        self.background_url: str = None
        self.platform: str = None
        self.supported_platforms: list[str] = []
        self.type : str = "game"
        self.genre: str = None
        self.genres: list[str] = []
        self.updates: int = 0
        self.dlc_count: int = 0
        self.dlcs = []
        self.tags: str = []
        self.release_date: str = None
        self.language: str = None
        self.supported_languages: list[str] = []
        self.installed: int = 0
        self.installed_version: str = None
        self.available_version: str = None
        self.state:Enum = self.state.INSTALLABLE
        self.cache_dir: str = os.path.join(CACHE_DIR, "game/{}".format(game_id))
        if os.path.exists(self.cache_dir) == False:
            os.makedirs(self.cache_dir)
        self.is_gog_game: int = 0
        self.sidebar_tile = None
        self.list_tile = None
        self.grid_tile = None
        self.safe_name = self.__clean_filename(self.name)

        self.dlc_status_list = ["not-installed", "installed", "updatable"]
        self.dlc_status_file_name = "goodoldgalaxy-dlc.json"
        self.dlc_status_file_path = ""
        
        # Set folder for download installer
        self.download_dir = os.path.join(CACHE_DIR, "download")
        self.download_path = os.path.join(self.download_dir, self.safe_name)
        
        # Set folder for update installer
        self.update_dir = os.path.join(CACHE_DIR, "update")
        self.update_path = os.path.join(self.update_dir, self.safe_name)

        # Set folder if user wants to keep installer (disabled by default)
        self.keep_dir = os.path.join(Config.get("install_dir"), "installer")
        self.keep_path = os.path.join(self.keep_dir, self.safe_name)

        if not os.path.exists(CACHE_DIR):
            os.makedirs(CACHE_DIR)
        
        # available downloads
        self.__downloads = []
Example #7
0
    def get_game_achievements(self, game: Game) -> List[Achievement]:
        request_url = "https://gameplay.gog.com/clients/" + str(
            game.id) + "/users/" + str(Config.get("user_id")) + "/achievements"
        game_dir = os.path.join(CACHE_DIR, "game/{}".format(game.id))
        if os.path.exists(game_dir) == False:
            os.makedirs(game_dir)
        file_path = os.path.join(game_dir, "achievements.json")
        do_request = True
        if os.path.exists(file_path) == True and time.time(
        ) - os.path.getmtime(file_path) < 60 * 60 * 24:
            do_request = False
        if do_request == True:
            response = self.__request(request_url)
            with open(file_path, 'w') as outfile:
                json.dump(response, outfile)
        else:
            with open(file_path, 'r') as infile:
                response = json.load(infile)

        achievements = []
        for item in response["items"]:
            try:
                achievement = Achievement(game, item["achievement_id"],
                                          item["achievement_key"])
                achievement.visible = item["visible"]
                achievement.name = item["name"]
                achievement.description = item["description"]
                achievement.image_url_unlocked = item["image_url_unlocked"]
                achievement.image_url_locked = item["image_url_locked"]
                achievement.date_unlocked = item["date_unlocked"]
                achievements.append(achievement)
            except Exception as e:
                print(e)
        return achievements
Example #8
0
    def get_download_info(self,
                          game: Game,
                          operating_system="linux",
                          dlc=False,
                          dlc_installers="") -> tuple:
        if dlc:
            installers = dlc_installers
        else:
            response = self.get_info(game)
            installers = response["downloads"]["installers"]
        possible_downloads = []
        for installer in installers:
            if installer["os"] == operating_system:
                possible_downloads.append(installer)
        if not possible_downloads:
            if operating_system == "linux":
                return self.get_download_info(game, "windows")
            else:
                raise NoDownloadLinkFound(
                    "Error: {} with id {} couldn't be installed".format(
                        game.name, game.id))

        download_info = possible_downloads[0]
        for installer in possible_downloads:
            if installer['language'] == Config.get("lang"):
                download_info = installer
                break
            if installer['language'] == "en":
                download_info = installer

        # Return last entry in possible_downloads. This will either be English or the first language in the list
        # This is just a backup, if the preferred language has been found, this part won't execute
        return download_info
Example #9
0
 def change_view_mode(self, button):
     iconname = self.library_mode_button.get_image().get_icon_name(
     ).icon_name
     if (iconname == "view-list-symbolic"):
         Config.set("viewas", "list")
         self.library_mode = "list"
         self.library_mode_button.set_image(self.image_view_as_grid)
         self.library_mode_button.set_tooltip_text(_("View as Grid"))
         self.view_as_list()
     else:
         Config.set("viewas", "grid")
         self.library_mode = "grid"
         self.library_mode_button.set_image(self.image_view_as_list)
         self.library_mode_button.set_tooltip_text(_("View as List"))
         self.view_as_grid()
     self.sync_library()
Example #10
0
    def __init__(self, parent, library: Library, api: Api):
        Gtk.Viewport.__init__(self)
        self.parent = parent
        self.api = api
        self.library = library
        self.library_mode = "list"
        self.show_installed_only = None

        # Set library view mode
        if (Config.get("viewas") == "list"):
            self.library_mode = "list"
            self.library_mode_button.set_image(self.image_view_as_grid)
            self.library_mode_button.set_tooltip_text(_("View as Grid"))
            self.library_viewport.add(self.listbox)
        else:
            self.library_mode = "grid"
            self.library_mode_button.set_image(self.image_view_as_list)
            self.library_mode_button.set_tooltip_text(_("View as List"))
            self.library_viewport.add(self.flowbox)
        # load library in background
        current_os = platform.system()
        if current_os == "Linux":
            self.ck_os_linux.set_active(True)
        elif current_os == "Windows":
            self.ck_os_windows.set_active(True)
        elif current_os == "Darwin":
            self.ck_os_mac.set_active(True)
Example #11
0
    def __install(self, game: Game = None):
        GLib.idle_add(self.__update_to_state, game.state.INSTALLING, game)
        game.install_dir = game.get_install_dir()
        try:
            if os.path.exists(game.keep_path):
                install_game(game, game.keep_path, main_window=self)
            else:
                install_game(game, game.download_path, main_window=self)
        except (FileNotFoundError, BadZipFile):
            GLib.idle_add(self.__update_to_state, game.state.DOWNLOADABLE,
                          game)
            return
        GLib.idle_add(self.__update_to_state, game.state.INSTALLED, game)
        GLib.idle_add(self.__reload_state, game)
        # make user to add the game to the side bar

        # check if DLCs should also be installed
        if game.type == "game" and Config.get("install_dlcs"):
            # first ensure we know about game dlcs
            self.library.update_dlcs_for_game(game)
            if len(game.dlcs) == 0:
                return
            # now grab DLCs that can be installed
            downloads = []
            for dlc in game.dlcs:
                try:
                    download_info = self.api.get_download_info(
                        dlc, game.platform, True, dlc.get_installers())
                except Exception:
                    # could not find a valid target, ignore it
                    continue
                # set dlc information now, otherwise this will break later
                dlc.platform = game.platform
                dlc.language = game.language
                # add download
                # Start the download for all files
                for key, file_info in enumerate(download_info['files']):
                    if key > 0:
                        download_path = "{}-{}.bin".format(
                            dlc.download_path, key)
                    else:
                        download_path = dlc.download_path
                    download = Download(url=self.api.get_real_download_link(
                        file_info["downlink"]),
                                        title=dlc.name,
                                        associated_object=dlc,
                                        save_location=download_path,
                                        number=key + 1,
                                        file_size=download_info["total_size"],
                                        out_of_amount=len(
                                            download_info['files']))
                    download.register_finish_function(self.__dlc_finish_func,
                                                      [game, dlc])
                    download.register_progress_function(
                        self.set_progress, game)
                    download.register_cancel_function(self.__cancel_download,
                                                      game)
                    downloads.append(download)
            DownloadManager.download(downloads)
Example #12
0
 def __set_avatar(self):
     user_dir = os.path.join(CACHE_DIR,
                             "user/{}".format(Config.get("user_id")))
     avatar = os.path.join(user_dir, "avatar_menu_user_av_small.jpg")
     if os.path.isfile(avatar) and os.path.exists(avatar):
         GLib.idle_add(self.user_photo.set_from_file, avatar)
         return True
     return False
Example #13
0
    def __request(self, url: str = None, params: dict = None) -> tuple:
        # Refresh the token if needed
        if self.active_token_expiration_time < time.time():
            print("Refreshing token")
            refresh_token = Config.get("refresh_token")
            Config.set("refresh_token", self.__refresh_token(refresh_token))

        # Make the request
        headers = {
            'Authorization': "Bearer " + self.active_token,
        }
        response = SESSION.get(url, headers=headers, params=params)
        if self.debug:
            print("Request: {}".format(url))
            print("Return code: {}".format(response.status_code))
            print("Response body: {}".format(response.text))
            print("")
        return response.json()
Example #14
0
    def __download_file(self, game: Game, operating_system=None) -> None:
        Config.set("current_download", game.id)
        GLib.idle_add(self.__update_to_state, game.state.QUEUED, game)

        current_os = platform.system()
        if current_os == "Linux":
            current_os = "linux"
        elif current_os == "Windows":
            current_os = "windows"
        elif current_os == "Darwin":
            current_os = "mac"
        # pick current os if none was passed
        if operating_system is None:
            operating_system = current_os
        if game.platform is None:
            game.platform = operating_system

        download_info = self.api.get_download_info(
            game, operating_system=operating_system)

        # Start the download for all files
        game.downloads = []
        download_path = game.download_path
        finish_func = self.__install
        for key, file_info in enumerate(download_info['files']):
            if key > 0:
                download_path = "{}-{}.bin".format(self.download_path, key)
            download = Download(url=self.api.get_real_download_link(
                file_info["downlink"]),
                                title=download_info["name"],
                                associated_object=game,
                                save_location=download_path,
                                number=key + 1,
                                file_size=download_info["total_size"],
                                out_of_amount=len(download_info['files']))
            download.register_finish_function(finish_func, game)
            download.register_progress_function(self.set_progress, game)
            download.register_cancel_function(self.__cancel_download, game)
            game.downloads.append(download)

        DownloadManager.download(game.downloads)
Example #15
0
 def get_user_info(self, finish_fn=None) -> str:
     username = Config.get("username")
     userid = Config.get("user_id")
     avatar = None
     if userid is not None:
         user_dir = os.path.join(CACHE_DIR, "user/{}".format(userid))
         if os.path.exists(user_dir) == False:
             os.makedirs(user_dir)
         avatar = os.path.join(user_dir, "avatar_menu_user_av_small.jpg")
         if not (os.path.isfile(avatar) and os.path.exists(avatar)):
             avatar = None
         if (avatar is not None and finish_fn is not None):
             finish_fn()
     if not username or not avatar:
         url = "https://embed.gog.com/userData.json"
         response = self.__request(url)
         username = response["username"]
         userid = response["userId"]
         Config.set("user_id", userid)
         Config.set("username", username)
         user_dir = os.path.join(CACHE_DIR, "user/{}".format(userid))
         if os.path.exists(user_dir) == False:
             os.makedirs(user_dir)
         avatar = os.path.join(user_dir, "avatar_menu_user_av_small.jpg")
         download = Download(response["avatar"] + "_menu_user_av_small.jpg",
                             avatar)
         download.register_finish_function(finish_fn)
         DownloadManager.download_now(download)
     return username
Example #16
0
 def __get_installed_games(self) -> List[Game]:
     games = []
     directories = os.listdir(Config.get("install_dir"))
     for directory in directories:
         full_path = os.path.join(Config.get("install_dir"), directory)
         # Only scan directories
         if not os.path.isdir(full_path):
             continue
         # Make sure the gameinfo file exists
         gameinfo = os.path.join(full_path, "gameinfo")
         if os.path.isfile(gameinfo):
             with open(gameinfo, 'r') as file:
                 name = file.readline().strip()
                 version = file.readline().strip()
                 version_dev = file.readline().strip()
                 language = file.readline().strip()
                 game_id = file.readline().strip()
                 if not game_id:
                     game_id = 0
                 else:
                     game_id = int(game_id)
             game = Game(name=name, game_id=game_id)
             game.set_installed("linux", full_path, version)
             game.set_installed_language(language)
             games.append(game)
         else:
             game_files = os.listdir(full_path)
             for file in game_files:
                 if re.match(r'^goggame-[0-9]*\.info$', file):
                     with open(os.path.join(full_path, file),
                               'r') as info_file:
                         info = json.loads(info_file.read())
                         game = Game(name=info["name"],
                                     game_id=int(info["gameId"]))
                         game.set_installed("windows", full_path)
                         game.set_installed_language(info["language"])
                         for lang in info["languages"]:
                             game.add_language(lang)
                         games.append(game)
     return games
Example #17
0
    def __authenticate(self):
        url = None
        if Config.get("stay_logged_in"):
            token = Config.get("refresh_token")
        else:
            Config.unset("username")
            Config.unset("user_id")
            Config.unset("refresh_token")
            token = None

        # Make sure there is an internet connection
        if not self.api.can_connect():
            return

        try:
            authenticated = self.api.authenticate(refresh_token=token,
                                                  login_code=url)
        except Exception as ex:
            print("Could not authenticate with GOG. Cause: {}".format(ex))
            return

        while not authenticated:
            login_url = self.api.get_login_url()
            redirect_url = self.api.get_redirect_url()
            login = Login(login_url=login_url,
                          redirect_url=redirect_url,
                          parent=self)
            response = login.run()
            login.hide()
            if response == Gtk.ResponseType.DELETE_EVENT:
                Gtk.main_quit()
                exit(0)
            if response == Gtk.ResponseType.NONE:
                result = login.get_result()
                authenticated = self.api.authenticate(refresh_token=token,
                                                      login_code=result)

        Config.set("refresh_token", authenticated)
Example #18
0
def set_fps_display():
    error_message = ""
    # Enable FPS Counter for Nvidia or AMD (Mesa) users
    if Config.get("show_fps"):
        os.environ[
            "__GL_SHOW_GRAPHICS_OSD"] = "1"  # For Nvidia users + OpenGL/Vulkan games
        os.environ[
            "GALLIUM_HUD"] = "simple,fps"  # For AMDGPU users + OpenGL games
        os.environ[
            "VK_INSTANCE_LAYERS"] = "VK_LAYER_MESA_overlay"  # For AMDGPU users + Vulkan games
    else:
        os.environ["__GL_SHOW_GRAPHICS_OSD"] = "0"
        os.environ["GALLIUM_HUD"] = ""
        os.environ["VK_INSTANCE_LAYERS"] = ""
    return error_message
Example #19
0
    def __init__(self, name):
        Gtk.ApplicationWindow.__init__(self, title=name)
        self.api = Api()
        self.offline = False
        self.library = Library(self.api)
        self.games = []
        self.library_view = LibraryView(self,
                                        library=self.library,
                                        api=self.api)
        self.details = None

        res = self.get_screen_resolution()
        # we got resolution
        if res[0] > 0 and res[0] <= 1368:
            self.set_default_size(1024, 700)

        # Set the icon
        icon = GdkPixbuf.Pixbuf.new_from_file(LOGO_IMAGE_PATH)
        self.set_default_icon_list([icon])
        self.installed_search.connect("search-changed", self.filter_installed)
        self.selection_button.hide()

        # Show the window
        self.show_all()
        self.selection_button.hide()
        self.selection_label.set_text(_("Library"))

        if not os.path.exists(CACHE_DIR):
            os.makedirs(CACHE_DIR)

        # Create the thumbnails directory
        if not os.path.exists(THUMBNAIL_DIR):
            os.makedirs(THUMBNAIL_DIR)

        # Interact with the API
        self.__authenticate()
        self.user_photo.set_tooltip_text(
            self.api.get_user_info(self.__set_avatar))
        self.sync_library()

        # Check what was the last view
        if Config.get("last_view") == "Game":
            print("last view as game..")
        else:
            self.__show_library()

        # Register self as a download manager listener
        DownloadManager.register_listener(self.__download_listener_func)
Example #20
0
    def __set_language_list(self) -> None:
        languages = Gtk.ListStore(str, str)
        for lang in SUPPORTED_DOWNLOAD_LANGUAGES:
            languages.append(lang)

        self.combobox_language.set_model(languages)
        self.combobox_language.set_entry_text_column(1)
        self.renderer_text = Gtk.CellRendererText()
        self.combobox_language.pack_start(self.renderer_text, False)
        self.combobox_language.add_attribute(self.renderer_text, "text", 1)

        # Set the active option
        current_lang = Config.get("lang")
        for key in range(len(languages)):
            if languages[key][:1][0] == current_lang:
                self.combobox_language.set_active(key)
                break
Example #21
0
    def logout(self, button):
        # Unset everything which is specific to this user
        Config.unset("username")
        Config.unset("user_id")
        Config.unset("refresh_token")
        self.hide()

        # Show the login screen
        self.__authenticate()
        self.user_photo.set_tooltip_text(self.api.get_user_info())
        self.user_photo.set_from_icon_name("contact-new", 4)
        self.sync_library()

        self.show_all()
Example #22
0
    def __init__(self, parent, game: Game, api: Api):
        Gtk.Viewport.__init__(self)
        self.parent = parent
        self.api = api
        self.game = None

        # Set some defaults and adjust the rest in set_game

        # Set folder for download installer
        self.download_dir = os.path.join(CACHE_DIR, "download")
        # Set folder for update installer
        self.update_dir = os.path.join(CACHE_DIR, "update")
        # Set folder if user wants to keep installer (disabled by default)
        self.keep_dir = os.path.join(Config.get("install_dir"), "installer")

        # create cache directory if not existing
        if not os.path.exists(CACHE_DIR):
            os.makedirs(CACHE_DIR)

        # create game supported platforms icons
        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
            ICON_LINUX_PATH if self.__is_light_theme() else
            ICON_LINUX_LIGHT_PATH, 20, 20, True)
        self.image_os_linux.set_from_pixbuf(pixbuf)
        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
            ICON_WINDOWS_PATH if self.__is_light_theme() else
            ICON_WINDOWS_LIGHT_PATH, 20, 20, True)
        self.image_os_windows.set_from_pixbuf(pixbuf)
        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
            ICON_MAC_PATH if self.__is_light_theme() else ICON_MAC_LIGHT_PATH,
            20, 20, True)
        self.image_os_mac.set_from_pixbuf(pixbuf)
        # hide platform icons by default, show on game specific code
        self.image_os_linux.hide()
        self.image_os_windows.show()
        self.image_os_mac.show()

        # handle game specific stuff
        self.set_game(game)
Example #23
0
 def __save_language_choice(self) -> None:
     lang_choice = self.combobox_language.get_active_iter()
     if lang_choice is not None:
         model = self.combobox_language.get_model()
         lang, _ = model[lang_choice][:2]
         Config.set("lang", lang)
Example #24
0
    def save_pressed(self, button):
        self.__save_language_choice()
        Config.set("keep_installers", self.switch_keep_installers.get_active())
        Config.set("stay_logged_in", self.switch_stay_logged_in.get_active())
        Config.set("show_fps", self.switch_show_fps.get_active())
        Config.set("create_shortcuts", self.switch_create_shortcuts.get_active())
        Config.set("install_dlcs", self.switch_install_dlcs.get_active())
        Config.set("automatic_updates", self.switch_automatic_updates.get_active())
        Config.set("do_not_show_backgrounds",self.switch_do_not_show_backgrounds.get_active())
        Config.set("do_not_show_media_tab",self.switch_do_not_show_media_tab.get_active())

        if self.switch_show_windows_games.get_active() != Config.get("show_windows_games"):
            Config.set("show_windows_games", self.switch_show_windows_games.get_active())
            self.parent.reset_library()

        # Only change the install_dir is it was actually changed
        if self.button_file_chooser.get_filename() != Config.get("install_dir"):
            if self.__save_install_dir_choice():
                DownloadManager.cancel_all_downloads()
                self.parent.reset_library()
            else:
                dialog = Gtk.MessageDialog(
                    parent=self,
                    modal=True,
                    destroy_with_parent=True,
                    message_type=Gtk.MessageType.ERROR,
                    buttons=Gtk.ButtonsType.OK,
                    text=_("{} isn't a usable path").format(self.button_file_chooser.get_filename())
                )
                dialog.run()
                dialog.destroy()
        self.destroy()
Example #25
0
    def set_game(self, game: Game = None):
        """
        Sets the game to display
        
        Parameters:
        -----------
            game: Game -> Game instance to display
        """
        # bail out if game was not set or we are doing the same game
        if game is None or self.game == game:
            return
        self.game = game
        self.progress_bar = None
        self.download = None
        self.current_state = self.game.state

        # Update paths for current game

        # Set folder for download installer
        self.download_path = os.path.join(self.download_dir, self.game.name)
        # Set folder for update installer
        self.update_path = os.path.join(self.update_dir, self.game.name)
        # Set folder if user wants to keep installer (disabled by default)
        self.keep_path = os.path.join(self.keep_dir, self.game.name)

        # reload game state
        self.reload_state()

        # Icon if update is available
        self.update_icon.hide()
        if self.game.installed == 1 and self.game.updates is not None and self.game.updates > 0:
            self.update_icon.show()

        # Hide the store icon if there is no game URL
        if not self.game.url:
            self.menu_button_store.hide()

        # Show platform icons that match supported platforms
        if ("linux" in game.supported_platforms):
            self.image_os_linux.show()
        if ("windows" in game.supported_platforms):
            self.image_os_windows.show()
        if ("mac" in game.supported_platforms):
            self.image_os_mac.show()

        # Handle game genres
        genres = ""
        idx = 0
        glen = len(game.genres)
        for genre in game.genres:
            if len(genre.strip()) == 0:
                continue
            genres += genre
            if idx < glen - 1:
                genres += ", "
            idx += 1
        if idx > 0:
            self.genres_label.show()
            self.genres_header.show()
            self.genres_label.set_text(genres)
        else:
            self.genres_label.hide()
            self.genres_header.hide()

        # Set game installed version
        if game.installed_version and game.installed_version is not None and game.installed_version != "":
            self.installed_version_label.show()
            self.installed_version_label.set_text(game.installed_version)
        else:
            self.installed_version_label.hide()

        # Handle game languages
        languages = ""
        idx = 0
        glen = len(game.supported_languages)
        for language in game.supported_languages:
            languages += language
            if idx < glen - 1:
                languages += ", "
            idx += 1
        if idx > 0:
            self.languages_header.show()
            self.languages_label.show()
            self.languages_label.set_text(languages)
        else:
            self.languages_header.hide()
            self.languages_label.hide()

        # Set game release date
        if game.release_date is not None and game.release_date != "":
            dt = None
            if isinstance(game.release_date, str):
                dt = datetime.datetime.strptime(game.release_date,
                                                '%Y-%m-%dT%H:%M:%S%z')
            elif isinstance(game.release_date, dict):
                dt = datetime.datetime.strptime(game.release_date["date"],
                                                '%Y-%m-%d %H:%M:%S.%f')
            if dt is not None:
                self.release_date_header.show()
                self.release_date_label.show()
                self.release_date_label.set_text(dt.strftime('%Y-%m-%d'))
        else:
            self.release_date_header.hide()
            self.release_date_label.hide()

        # grab game details from api
        self.response = self.api.get_info(game)

        # Game description
        if "description" in self.response:
            # note this is
            self.description_header.show()
            self.description_label.show()
            self.description_label.set_property("use-markup", True)
            #self.description_lead_label.set_text(self.response["description"]["lead"])
            try:
                desc = self.__cleanup_html(
                    self.response["description"]["full"])
                self.description_label.set_markup(desc)
            except Exception as e:
                print(e)
        else:
            self.description_header.hide()
            self.description_label.hide()

        # changelog
        if "changelog" in self.response:
            try:
                text = self.__cleanup_html(self.response["changelog"])
                self.changelog.get_buffer().set_text(text)
                # show the tab
                self.notebook.get_nth_page(1).show()
            except Exception as e:
                print(e)
        else:
            # hide the tab
            self.notebook.get_nth_page(1).hide()
            self.changelog.get_buffer().set_text("")

        # first remove existing media
        while len(self.media_flowbox.get_children()) > 0:
            child = self.media_flowbox.get_children()[0]
            self.media_flowbox.remove(child)
            # destroy child which is a gtk image to see if we can get back some memory
            child.destroy()
        # screenshots
        sidx = 0
        # Only handle the media tab if requested
        if Config.get("do_not_show_media_tab") == False:
            if "screenshots" in self.response:
                for screenshot in self.response["screenshots"]:
                    sidx += 1
                    image_id = screenshot["image_id"]
                    template = screenshot["formatter_template_url"]
                    image_url = template.replace("{formatter}",
                                                 "ggvgt_2x").replace(
                                                     ".png", ".jpg")
                    self.__add_screenshot(image_id, image_url)
            # videos
            vidx = 0
            if "videos" in self.response:
                for video in self.response["videos"]:
                    thumbnail_url = video["thumbnail_url"]
                    video_url = video["video_url"]
                    self.__add_video(vidx, video_url, thumbnail_url)
                    sidx += 1
        if sidx == 0:
            self.media_bar.hide()
            self.media_flowbox.hide()
        else:
            self.media_bar.show()
            self.media_flowbox.show()

        # first remove any existing downloads
        if self.downloadstree is not None and self.downloadstree.get_model(
        ) is not None:
            # clear the store
            self.downloadstree.get_model().get_model().clear()
            # remove columns
            while len(self.downloadstree.get_columns()) > 0:
                self.downloadstree.remove_column(
                    self.downloadstree.get_columns()[0])
        if self.goodiestree is not None and self.goodiestree.get_model(
        ) is not None:
            # clear the store
            self.goodiestree.get_model().clear()
            # remove columns
            while len(self.goodiestree.get_columns()) > 0:
                self.goodiestree.remove_column(
                    self.goodiestree.get_columns()[0])
        # downloads
        didx = 0
        gidx = 0
        #GdkPixbuf.Pixbuf
        downloads_store = Gtk.ListStore(str, str, str, str, str, str, str, str,
                                        int, str, str)
        downloads_cols = [
            _("Name"),
            _("OS"),
            _("Language"),
            _("Type"),
            _("Size"),
            _("Version"),
            _("State"), "Location", "Id", "File Size", "Operating System"
        ]
        goodies_store = Gtk.ListStore(str, str, str, str, str, str)
        goodies_cols = [
            _("Name"),
            _("Category"),
            _("Type"),
            _("Size"),
            _("Count"),
            _("Location")
        ]
        self.downloads_languages = set()
        self.downloads_os = []
        self.download_links = []
        self.goodies_links = []
        if "downloads" in self.response:
            downloads = self.response["downloads"]
            for dltype in downloads:
                is_goodies = True if dltype == "bonus_content" else False
                items = downloads[dltype]
                download_type = DL_TYPES[dltype]
                for item in items:
                    if is_goodies:
                        gidx += 1
                        links = self.__append_to_list_store_for_download(
                            goodies_store, item, download_type, is_goodies)
                        for link in links:
                            self.goodies_links.append(link)
                    else:
                        didx += 1
                        state = "N/A"
                        if self.game.installed == 1:
                            if self.game.installed_version == item["version"]:
                                state = _("Installed")
                            else:
                                state = _("Update Available")
                        links = self.__append_to_list_store_for_download(
                            downloads_store,
                            item,
                            download_type,
                            state=state,
                            product_id=self.game.id,
                            file_size=item["total_size"])
                        for link in links:
                            self.download_links.append(link)
        if "expanded_dlcs" in self.response:
            dlcs = self.response["expanded_dlcs"]
            for dlc in dlcs:
                downloads = dlc["downloads"]
                for dltype in downloads:
                    is_goodies = True if dltype == "bonus_content" else False
                    items = downloads[dltype]
                    download_type = DL_TYPES[dltype]
                    for item in items:
                        if is_goodies:
                            gidx += 1
                            links = self.__append_to_list_store_for_download(
                                goodies_store, item, "DLC " + download_type,
                                is_goodies)
                            for link in links:
                                self.goodies_links.append(link)
                        else:
                            didx += 1
                            state = self.game.get_dlc_status(
                                item["name"], item["version"]
                            ) if self.game.installed > 0 else "N/A"
                            if state == "installed":
                                state = _("Installed")
                            elif state == "updatable":
                                state = _("Update Available")
                            elif state == "not-installed":
                                state = _("Install")
                            links = self.__append_to_list_store_for_download(
                                downloads_store,
                                item,
                                "DLC " + download_type,
                                state=state,
                                product_id=dlc["id"],
                                file_size=item["total_size"])
                            # add game to dlc list
                            self.game.add_dlc_from_json(dlc)
                            for link in links:
                                self.download_links.append(link)
        if (didx > 0):
            self.downloads_filter = downloads_store.filter_new()
            self.downloads_filter.set_visible_func(self.__downloads_filter,
                                                   data=None)
            self.downloadstree.set_model(self.downloads_filter)
            self.__create_tree_columns(self.downloadstree, downloads_cols)
            for lang in self.downloads_languages:
                ck = Gtk.CheckButton(lang)
                ck.set_active(
                    lang == IETF_DOWNLOAD_LANGUAGES[Config.get("lang")])
                ck.connect("toggled", self.downloads_filter_changed)
                self.languagebox.pack_start(ck, False, True, 10)
            self.languagebox.show_all()
            self.downloads_header_box.show_all()
            self.downloadstree.show_all()
            # re-filter downloads
            self.downloads_filter.refilter()
        else:
            self.languagebox.hide()
            self.downloads_header_box.hide()
            self.downloadstree.hide()
        if (gidx > 0):
            self.goodiestree.set_model(goodies_store)
            self.__create_tree_columns(self.goodiestree, goodies_cols, True)
            self.goodies_header.show()
            self.goodiestree.show_all()
        else:
            self.goodies_header.hide()
            self.goodiestree.hide()

        # handle achievements
        self.load_achievements()

        # load the background image
        self.__background_width = None
        if self.background_image is not None:
            self.background_image.clear()
        if Config.get("do_not_show_backgrounds") == False:
            self.background_image.show()
            self.__load_background_image()
        else:
            self.background_image.hide()
Example #26
0
 def __get_install_dir(self):
     if self.game.install_dir:
         return self.game.install_dir
     return os.path.join(Config.get("install_dir"),
                         self.game.get_install_directory_name())
Example #27
0
def install_game(game,
                 installer,
                 parent_window=None,
                 main_window=None) -> None:
    if not os.path.exists(installer):
        GLib.idle_add(__show_installation_error, game,
                      _("{} failed to download.").format(installer),
                      parent_window, main_window)
        raise FileNotFoundError(
            "The installer {} does not exist".format(installer))

    if game.platform == "linux":
        if not __verify_installer_integrity(installer):
            GLib.idle_add(
                __show_installation_error, game,
                _("{} was corrupted. Please download it again.").format(
                    installer), parent_window, main_window)
            os.remove(installer)
            raise FileNotFoundError(
                "The installer {} was corrupted".format(installer))

        # Make sure the install directory exists
        library_dir = Config.get("install_dir")
        if not os.path.exists(library_dir):
            os.makedirs(library_dir)

        # Make a temporary empty directory for extracting the installer
        extract_dir = os.path.join(CACHE_DIR, "extract")
        temp_dir = os.path.join(extract_dir, str(game.id))
        if os.path.exists(extract_dir):
            shutil.rmtree(extract_dir, ignore_errors=True)
        os.makedirs(temp_dir, mode=0o755)

        # Extract the installer
        subprocess.call(["unzip", "-qq", installer, "-d", temp_dir])
        if len(os.listdir(temp_dir)) == 0:
            GLib.idle_add(__show_installation_error, game,
                          _("{} could not be unzipped.").format(installer),
                          parent_window, main_window)
            raise CannotOpenZipContent(
                "{} could not be unzipped.".format(installer))

        # Make sure the install directory exists
        library_dir = Config.get("install_dir")
        if not os.path.exists(library_dir):
            os.makedirs(library_dir, mode=0o755)

        # Copy the game files into the correct directory
        tmp_noarch_dir = os.path.join(temp_dir, "data/noarch")
        copytree(tmp_noarch_dir, game.install_dir)

        if game.type == "game" and Config.get("create_shortcuts") == True:
            create_shortcuts(game)

        # Remove the temporary directory
        shutil.rmtree(temp_dir, ignore_errors=True)

    elif game.platform == "windows":
        # Set the prefix for Windows games
        prefix_dir = os.path.join(game.install_dir, "prefix")
        if not os.path.exists(prefix_dir):
            os.makedirs(prefix_dir, mode=0o755)

        os.environ["WINEPREFIX"] = prefix_dir

        # It's possible to set install dir as argument before installation
        command = ["wine", installer, "/dir=" + game.install_dir]
        process = subprocess.Popen(command)
        process.wait()
        if process.returncode != 0:
            GLib.idle_add(
                __show_installation_error, game,
                _("The installation of {} failed. Please try again.").format(
                    installer), main_window)
            return
    else:
        GLib.idle_add(__show_installation_error, game,
                      _("{} platform not supported.").format(installer),
                      parent_window, main_window)
        raise Exception("Platform not supported")

    thumbnail_small = os.path.join(THUMBNAIL_DIR, "{}_100.jpg".format(game.id))
    thumbnail_medium = os.path.join(THUMBNAIL_DIR,
                                    "{}_196.jpg".format(game.id))
    if os.path.exists(thumbnail_small):
        shutil.copyfile(thumbnail_small,
                        os.path.join(game.install_dir, "thumbnail_100.jpg"))
    if os.path.exists(thumbnail_medium):
        shutil.copyfile(thumbnail_medium,
                        os.path.join(game.install_dir, "thumbnail_196.jpg"))

    if Config.get("keep_installers"):
        keep_dir = os.path.join(Config.get("install_dir"), "installer")
        download_dir = os.path.join(CACHE_DIR, "download")
        update_dir = os.path.join(CACHE_DIR, "update")
        if not os.path.exists(keep_dir):
            os.makedirs(keep_dir, mode=0o755)
        try:
            # It's needed for multiple files
            for file in os.listdir(download_dir):
                shutil.move(download_dir + '/' + file, keep_dir + '/' + file)
        except Exception as ex:
            print("Encountered error while copying {} to {}. Got error: {}".
                  format(installer, keep_dir, ex))
        try:
            # It's needed for multiple files
            for file in os.listdir(update_dir):
                shutil.move(update_dir + '/' + file, keep_dir + '/' + file)
        except Exception as ex:
            print("Encountered error while copying {} to {}. Got error: {}".
                  format(installer, keep_dir, ex))
    else:
        os.remove(installer)
    # finish up
    game.istalled = 1
    game.updates = 0
Example #28
0
def uninstall_game(game):
    if Config.get("create_shortcuts") == True:
        remove_shortcuts(game)
    shutil.rmtree(game.install_dir, ignore_errors=True)
    game.install_dir = None
    game.installed_version = None
Example #29
0
 def resume_download_if_expected(self):
     download_id = Config.get("current_download")
     all_games = self.library.get_games()
     for game in all_games:
         if download_id and download_id == game.id and game.state != game.state.INSTALLED:
             self.download_game(game)
Example #30
0
 def prevent_resume_on_startup(self, game):
     download_id = Config.get("current_download")
     if download_id and download_id == game.id:
         Config.unset("current_download")