diff --git a/server/app/settings.py b/server/app/settings.py index f09805f..2744c26 100644 --- a/server/app/settings.py +++ b/server/app/settings.py @@ -179,10 +179,13 @@ def __init__(self) -> 'None': # running_mode: server # to be used in a resource-constrained environment # chinese_preference: cn # chinese_preference: tw -chinese_preference: none''') +chinese_preference: none +check_for_updates: false''') self.preferences : 'dict[str, str]' = self._read_settings_from_file(self.PREFERENCES_FILE) if 'chinese_preference' not in self.preferences.keys(): # Backward compatibility self.preferences['chinese_preference'] = 'none' + if 'check_for_updates' not in self.preferences.keys(): # Backward compatibility + self.preferences['check_for_updates'] = False if not self._preferences_valid(): raise ValueError('Invalid preferences file.') diff --git a/server/requirements.txt b/server/requirements.txt index 4a27da4..7b367ad 100644 --- a/server/requirements.txt +++ b/server/requirements.txt @@ -6,4 +6,5 @@ python-idzip>=0.3.9 lxml>=4.9.1 python-lzo>=1.15 xxhash>=3.2.0 -dsl2html>=0.1.2 \ No newline at end of file +dsl2html>=0.1.2 +requests>=2.31.0 \ No newline at end of file diff --git a/server/server.py b/server/server.py index 46199f8..af013a9 100644 --- a/server/server.py +++ b/server/server.py @@ -1,9 +1,10 @@ -from app import create_app from waitress import serve import sys import threading import os import webbrowser +from app import create_app + import logging logging.basicConfig(level=logging.INFO) @@ -19,6 +20,10 @@ else: host = app.extensions['dictionaries'].settings.preferences['listening_address'] port = app.extensions['dictionaries'].settings.PORT + + if app.extensions['dictionaries'].settings.preferences['check_for_updates']: + from updater import update + update() if os.getenv('BROWSER'): # mainly for use on a-Shell server_thread = threading.Thread(target=lambda: serve(app, listen='%s:%s' % (host, port))) diff --git a/server/updater.py b/server/updater.py new file mode 100644 index 0000000..2db75d7 --- /dev/null +++ b/server/updater.py @@ -0,0 +1,51 @@ +import requests +import lxml.etree as ET +from lxml import html +import sys +import os + +import logging + +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) + +timeout = 5 +release_atom_url = 'https://github.com/Crissium/SilverDict/releases.atom' +windows_download_url = 'https://github.com/Crissium/SilverDict/releases/download/%s/SilverDict-windows.zip' +unix_download_url = 'https://github.com/Crissium/SilverDict/releases/download/%s/SilverDict.zip' +project_directory = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +windows_save_path = os.path.join(os.path.dirname(project_directory), 'SilverDict-windows.zip') +unix_save_path = os.path.join(project_directory, 'SilverDict.zip') +current_version = 'v0.11.0' + +def _get_latest_version_and_release_note() -> 'tuple[str, str]': + response = requests.get(release_atom_url, timeout=timeout) + if response.status_code != 200: + raise Exception('Cannot get release atom') + root = ET.fromstring(response.content, parser=ET.XMLParser(encoding='utf-8')) + latest_version = root[5][3].text + release_note = html.fromstring(root[5][4].text).text_content() + return latest_version, release_note + +def _download_release(version: 'str') -> None: + if sys.platform.startswith('win'): + download_url = windows_download_url % version + else: + download_url = unix_download_url % version + response = requests.get(download_url, timeout=timeout) + if response.status_code != 200: + raise Exception('Cannot download release.') + with open(windows_save_path if sys.platform.startswith('win') else unix_save_path, 'wb') as f: + f.write(response.content) + +def update() -> None: + try: + latest_version, release_note = _get_latest_version_and_release_note() + if latest_version == current_version: + return + logger.info('Found new version %s' % latest_version) + logger.info('Release note:\n%s' % release_note) + _download_release(latest_version) + logger.info('Update downloaded to %s' % (windows_save_path if sys.platform.startswith('win') else unix_save_path)) + except requests.exceptions.Timeout: + logger.error('Timeout while connecting to GitHub.')