class UpdateChecker: def __init__(self, log: logger.Log): self.log: logger.Log = log self.api_future: Optional[Future] = None self.checked_response: bool = False self.popup: bool = False # initiate the API request, which runs in a seperate thread def initiate_update_check(self, popup: bool, timeout: float = float( settings.get('request_timeout'))): if self.api_future is not None: self.log.debug( "Skipping update check because it's already running") return self.log.debug(f"Checking for updates, timeout: {timeout} secs") self.popup = popup self.checked_response = False from requests_futures.sessions import FuturesSession self.api_future = FuturesSession(max_workers=1).get( 'https://api.github.com/repos/Kataiser/tf2-rich-presence/releases/latest', timeout=timeout, params={'accept': 'application/vnd.github.v3+json'}, headers={'Connection': 'close'}) # request either finished or failed def update_check_ready(self) -> bool: return self.api_future is not None and self.api_future.done( ) and not self.checked_response # parse API result or handle errors def receive_update_check( self, raise_exceptions: bool = False) -> Optional[Tuple[str, str, str]]: import requests self.checked_response = True try: result = self.api_future.result() except (requests.Timeout, requests.exceptions.ReadTimeout): self.log.error(f"Update check timed out", reportable=False) if raise_exceptions: raise except (requests.RequestException, requests.ConnectionError): self.log.error( f"Connection error in updater: {traceback.format_exc()}", reportable=False) if raise_exceptions: raise except Exception: self.log.error( f"Non-connection based update error: {traceback.format_exc()}") else: self.log.debug( f"Update check took {round(result.elapsed.microseconds / 1000000, 3)} seconds" ) response: dict = result.json() self.api_future = None try: newest_version: str = response['tag_name'] downloads_url: str = response['html_url'] changelog: str = response['body'] except KeyError: if 'message' in response and 'API rate limit exceeded' in response[ 'message']: rate_limit_message: str = f"Github {response['message'].split('(')[0][:-1]}" raise RateLimitError(rate_limit_message) else: raise changelog_formatted: str = format_changelog(changelog) if launcher.VERSION == newest_version: self.log.debug(f"Up to date ({launcher.VERSION})") else: # out of date self.log.error( f"Out of date, newest version is {newest_version} (this is {launcher.VERSION})", reportable=False) # save available version for the launcher db: Dict[str, Union[bool, list, str]] = utils.access_db() db['available_version'] = newest_version utils.access_db(db) return newest_version, downloads_url, changelog_formatted