mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-08 13:14:17 +02:00
[web] improvement -> environment settings being cached for 24 hours
This commit is contained in:
@@ -24,6 +24,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
- the index is now stored at **~/.cache/bauh/arch/aur/index.txt**.
|
- the index is now stored at **~/.cache/bauh/arch/aur/index.txt**.
|
||||||
- info window
|
- info window
|
||||||
- date fields format changed to numbers (e.g: Thu Dec 17 17:19:55 2020 -> 2020-12-17 17:19:55)
|
- date fields format changed to numbers (e.g: Thu Dec 17 17:19:55 2020 -> 2020-12-17 17:19:55)
|
||||||
|
- Web
|
||||||
|
- now the environment settings are cached for 24 hours. This period can be controlled through the new settings property **environment.update_interval** (in minutes -> default: 1440 = 24 hours. Use **0** so that they are always updated).
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://raw.githubusercontent.com/vinifmor/bauh-files/master/pictures/releases/0.9.11/web_env_exp.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
- AppImage
|
- AppImage
|
||||||
@@ -205,7 +211,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
- new settings property **suggest_unneeded_uninstall**: defines if the dependencies apparently no longer necessary associated with the uninstalled packages should be suggested for uninstallation. When this property is enabled it automatically disables the property **suggest_optdep_uninstall**. Default: false (to prevent new users from making mistakes)
|
- new settings property **suggest_unneeded_uninstall**: defines if the dependencies apparently no longer necessary associated with the uninstalled packages should be suggested for uninstallation. When this property is enabled it automatically disables the property **suggest_optdep_uninstall**. Default: false (to prevent new users from making mistakes)
|
||||||
- new settings property **suggest_optdep_uninstall**: defines if the optional dependencies associated with uninstalled packages should be suggested for uninstallation. Only the optional dependencies that are not dependencies of other packages will be suggested. Default: false (to prevent new users from making mistakes)
|
- new settings property **suggest_optdep_uninstall**: defines if the optional dependencies associated with uninstalled packages should be suggested for uninstallation. Only the optional dependencies that are not dependencies of other packages will be suggested. Default: false (to prevent new users from making mistakes)
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://raw.githubusercontent.com/vinifmor/bauh-files/master/pictures/releases/0.9.7/arch_opt_uni.png"">
|
<img src="https://raw.githubusercontent.com/vinifmor/bauh-files/master/pictures/releases/0.9.7/arch_opt_uni.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
- AUR
|
- AUR
|
||||||
|
|||||||
@@ -267,6 +267,7 @@ environment:
|
|||||||
electron:
|
electron:
|
||||||
version: null # set a custom Electron version here (e.g: '6.1.4')
|
version: null # set a custom Electron version here (e.g: '6.1.4')
|
||||||
system: false # set it to 'true' if you want to use the nativefier version globally installed on your system
|
system: false # set it to 'true' if you want to use the nativefier version globally installed on your system
|
||||||
|
cache_exp: 1440 # defines the period (in minutes) in which the stored environment settings are considered valid. Use 0 so that they are always updated. Default: 1440 (24 hours)
|
||||||
```
|
```
|
||||||
- Required dependencies:
|
- Required dependencies:
|
||||||
- Arch-based systems: **python-lxml**, **python-beautifulsoup4**
|
- Arch-based systems: **python-lxml**, **python-beautifulsoup4**
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from bauh.api.constants import DESKTOP_ENTRIES_DIR, CONFIG_PATH, TEMP_DIR
|
from bauh.api.constants import DESKTOP_ENTRIES_DIR, CONFIG_PATH, TEMP_DIR, CACHE_PATH
|
||||||
from bauh.commons import user, resource
|
from bauh.commons import resource
|
||||||
|
|
||||||
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||||
WEB_PATH = '{}/.local/share/bauh/web'.format(Path.home())
|
WEB_PATH = '{}/.local/share/bauh/web'.format(Path.home())
|
||||||
@@ -30,6 +30,8 @@ SEARCH_INDEX_FILE = '{}/index.yml'.format(TEMP_PATH)
|
|||||||
SUGGESTIONS_CACHE_FILE = '{}/suggestions.txt'.format(TEMP_PATH)
|
SUGGESTIONS_CACHE_FILE = '{}/suggestions.txt'.format(TEMP_PATH)
|
||||||
CONFIG_FILE = '{}/web.yml'.format(CONFIG_PATH)
|
CONFIG_FILE = '{}/web.yml'.format(CONFIG_PATH)
|
||||||
URL_NATIVEFIER = 'https://github.com/jiahaog/nativefier/archive/v{version}.tar.gz'
|
URL_NATIVEFIER = 'https://github.com/jiahaog/nativefier/archive/v{version}.tar.gz'
|
||||||
|
ENVIRONMENT_SETTINGS_CACHED_FILE = '{}/web/environment.yml'.format(CACHE_PATH)
|
||||||
|
ENVIRONMENT_SETTINGS_TS_FILE = '{}/web/environment.ts'.format(CACHE_PATH)
|
||||||
|
|
||||||
|
|
||||||
def get_icon_path() -> str:
|
def get_icon_path() -> str:
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ def read_config(update_file: bool = False) -> dict:
|
|||||||
default_config = {
|
default_config = {
|
||||||
'environment': {
|
'environment': {
|
||||||
'system': False,
|
'system': False,
|
||||||
'electron': {'version': None}
|
'electron': {'version': None},
|
||||||
|
'cache_exp': 1440
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
file_downloader=context.file_downloader, i18n=context.i18n)
|
file_downloader=context.file_downloader, i18n=context.i18n)
|
||||||
self.enabled = True
|
self.enabled = True
|
||||||
self.i18n = context.i18n
|
self.i18n = context.i18n
|
||||||
self.env_settings = {}
|
|
||||||
self.logger = context.logger
|
self.logger = context.logger
|
||||||
self.env_thread = None
|
self.env_thread = None
|
||||||
self.suggestions_downloader = suggestions_downloader
|
self.suggestions_downloader = suggestions_downloader
|
||||||
@@ -207,8 +206,8 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
return BeautifulSoup(url_res.text, 'lxml', parse_only=SoupStrainer('head')), url_res
|
return BeautifulSoup(url_res.text, 'lxml', parse_only=SoupStrainer('head')), url_res
|
||||||
|
|
||||||
def search(self, words: str, disk_loader: DiskCacheLoader, limit: int = -1, is_url: bool = False) -> SearchResult:
|
def search(self, words: str, disk_loader: DiskCacheLoader, limit: int = -1, is_url: bool = False) -> SearchResult:
|
||||||
local_config = {}
|
web_config = {}
|
||||||
thread_config = Thread(target=self._fill_config_async, args=(local_config,))
|
thread_config = Thread(target=self._fill_config_async, args=(web_config,))
|
||||||
thread_config.start()
|
thread_config.start()
|
||||||
|
|
||||||
res = SearchResult([], [], 0)
|
res = SearchResult([], [], 0)
|
||||||
@@ -241,8 +240,11 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
|
|
||||||
app = WebApplication(url=final_url, source_url=url, name=name, description=desc, icon_url=icon_url)
|
app = WebApplication(url=final_url, source_url=url, name=name, description=desc, icon_url=icon_url)
|
||||||
|
|
||||||
if self.env_settings.get('electron') and self.env_settings['electron'].get('version'):
|
thread_config.join()
|
||||||
app.version = self.env_settings['electron']['version']
|
env_settings = self.env_updater.read_settings(web_config=web_config, cache=True)
|
||||||
|
|
||||||
|
if env_settings.get('electron') and env_settings['electron'].get('version'):
|
||||||
|
app.version = env_settings['electron']['version']
|
||||||
app.latest_version = app.version
|
app.latest_version = app.version
|
||||||
|
|
||||||
res.new = [app]
|
res.new = [app]
|
||||||
@@ -295,6 +297,9 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
else:
|
else:
|
||||||
matched_suggestions.sort(key=lambda s: s.get('priority', 0), reverse=True)
|
matched_suggestions.sort(key=lambda s: s.get('priority', 0), reverse=True)
|
||||||
|
|
||||||
|
thread_config.join()
|
||||||
|
env_settings = self.env_updater.read_settings(web_config=web_config, cache=True)
|
||||||
|
|
||||||
if installed_matches:
|
if installed_matches:
|
||||||
# checking if any of the installed matches is one of the matched suggestions
|
# checking if any of the installed matches is one of the matched suggestions
|
||||||
|
|
||||||
@@ -306,11 +311,11 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
if found:
|
if found:
|
||||||
res.installed.extend(found)
|
res.installed.extend(found)
|
||||||
else:
|
else:
|
||||||
res.new.append(self._map_suggestion(sug).package)
|
res.new.append(self._map_suggestion(sug, env_settings).package)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
for sug in matched_suggestions:
|
for sug in matched_suggestions:
|
||||||
res.new.append(self._map_suggestion(sug).package)
|
res.new.append(self._map_suggestion(sug, env_settings).package)
|
||||||
|
|
||||||
res.total += len(res.installed)
|
res.total += len(res.installed)
|
||||||
res.total += len(res.new)
|
res.total += len(res.new)
|
||||||
@@ -318,9 +323,9 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
if res.new:
|
if res.new:
|
||||||
thread_config.join()
|
thread_config.join()
|
||||||
|
|
||||||
if local_config['environment']['electron']['version']:
|
if web_config['environment']['electron']['version']:
|
||||||
for app in res.new:
|
for app in res.new:
|
||||||
app.version = str(local_config['environment']['electron']['version'])
|
app.version = str(web_config['environment']['electron']['version'])
|
||||||
app.latest_version = app.version
|
app.latest_version = app.version
|
||||||
|
|
||||||
return res
|
return res
|
||||||
@@ -332,7 +337,7 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
else:
|
else:
|
||||||
self.logger.warning("No search index found at {}".format(SEARCH_INDEX_FILE))
|
self.logger.warning("No search index found at {}".format(SEARCH_INDEX_FILE))
|
||||||
|
|
||||||
def read_installed(self, disk_loader: DiskCacheLoader, limit: int = -1, only_apps: bool = False, pkg_types: Set[Type[SoftwarePackage]] = None, internet_available: bool = True) -> SearchResult:
|
def read_installed(self, disk_loader: Optional[DiskCacheLoader], limit: int = -1, only_apps: bool = False, pkg_types: Set[Type[SoftwarePackage]] = None, internet_available: bool = True) -> SearchResult:
|
||||||
res = SearchResult([], [], 0)
|
res = SearchResult([], [], 0)
|
||||||
|
|
||||||
if os.path.exists(INSTALLED_PATH):
|
if os.path.exists(INSTALLED_PATH):
|
||||||
@@ -620,7 +625,6 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
def install(self, pkg: WebApplication, root_password: str, disk_loader: DiskCacheLoader, watcher: ProcessWatcher) -> TransactionResult:
|
def install(self, pkg: WebApplication, root_password: str, disk_loader: DiskCacheLoader, watcher: ProcessWatcher) -> TransactionResult:
|
||||||
|
|
||||||
continue_install, install_options = self._ask_install_options(pkg, watcher)
|
continue_install, install_options = self._ask_install_options(pkg, watcher)
|
||||||
widevine_support = '--widevine' in install_options
|
widevine_support = '--widevine' in install_options
|
||||||
|
|
||||||
@@ -630,16 +634,16 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
watcher.change_substatus(self.i18n['web.env.checking'])
|
watcher.change_substatus(self.i18n['web.env.checking'])
|
||||||
handler = ProcessHandler(watcher)
|
handler = ProcessHandler(watcher)
|
||||||
|
|
||||||
env_settings = self.env_updater.read_settings()
|
web_config = read_config()
|
||||||
local_config = read_config()
|
env_settings = self.env_updater.read_settings(web_config=web_config)
|
||||||
|
|
||||||
if local_config['environment']['system'] and not nativefier.is_available():
|
if web_config['environment']['system'] and not nativefier.is_available():
|
||||||
watcher.show_message(title=self.i18n['error'].capitalize(),
|
watcher.show_message(title=self.i18n['error'].capitalize(),
|
||||||
body=self.i18n['web.install.global_nativefier.unavailable'].format(n=bold('Nativefier'), app=bold(pkg.name)) + '.',
|
body=self.i18n['web.install.global_nativefier.unavailable'].format(n=bold('Nativefier'), app=bold(pkg.name)) + '.',
|
||||||
type_=MessageType.ERROR)
|
type_=MessageType.ERROR)
|
||||||
return TransactionResult(success=False, installed=[], removed=[])
|
return TransactionResult(success=False, installed=[], removed=[])
|
||||||
|
|
||||||
env_components = self.env_updater.check_environment(app=pkg, local_config=local_config, env=env_settings,
|
env_components = self.env_updater.check_environment(app=pkg, local_config=web_config, env=env_settings,
|
||||||
is_x86_x64_arch=self.context.is_system_x86_64(),
|
is_x86_x64_arch=self.context.is_system_x86_64(),
|
||||||
widevine=widevine_support)
|
widevine=widevine_support)
|
||||||
|
|
||||||
@@ -695,7 +699,7 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
electron_version = str(next((c for c in env_components if c.id == 'electron')).version)
|
electron_version = str(next((c for c in env_components if c.id == 'electron')).version)
|
||||||
installed = handler.handle_simple(nativefier.install(url=pkg.url, name=app_id, output_dir=app_dir,
|
installed = handler.handle_simple(nativefier.install(url=pkg.url, name=app_id, output_dir=app_dir,
|
||||||
electron_version=electron_version if not widevine_support else None,
|
electron_version=electron_version if not widevine_support else None,
|
||||||
system=bool(local_config['environment']['system']),
|
system=bool(web_config['environment']['system']),
|
||||||
cwd=INSTALLED_PATH,
|
cwd=INSTALLED_PATH,
|
||||||
extra_options=install_options))
|
extra_options=install_options))
|
||||||
|
|
||||||
@@ -805,11 +809,7 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
def requires_root(self, action: SoftwareAction, pkg: SoftwarePackage) -> bool:
|
def requires_root(self, action: SoftwareAction, pkg: SoftwarePackage) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _update_env_settings(self, task_manager: TaskManager = None):
|
def _download_suggestions(self, downloader: SuggestionsDownloader):
|
||||||
self.env_settings = self.env_updater.read_settings(task_manager)
|
|
||||||
|
|
||||||
def _download_suggestions(self, taskman: TaskManager = None):
|
|
||||||
downloader = SuggestionsDownloader(logger=self.logger, http_client=self.http_client, i18n=self.i18n, taskman=taskman)
|
|
||||||
self.suggestions = downloader.download()
|
self.suggestions = downloader.download()
|
||||||
|
|
||||||
if self.suggestions:
|
if self.suggestions:
|
||||||
@@ -818,12 +818,20 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
|
|
||||||
def prepare(self, task_manager: TaskManager, root_password: str, internet_available: bool):
|
def prepare(self, task_manager: TaskManager, root_password: str, internet_available: bool):
|
||||||
if internet_available:
|
if internet_available:
|
||||||
self.env_thread = Thread(target=self._update_env_settings, args=(task_manager,), daemon=True)
|
downloader = SuggestionsDownloader(logger=self.logger, http_client=self.http_client,
|
||||||
self.env_thread.start()
|
i18n=self.i18n, taskman=task_manager)
|
||||||
|
downloader.register_task()
|
||||||
|
|
||||||
self.suggestions_downloader = Thread(target=self._download_suggestions, args=(task_manager,), daemon=True)
|
self.suggestions_downloader = Thread(target=self._download_suggestions, args=(downloader,), daemon=True)
|
||||||
self.suggestions_downloader.start()
|
self.suggestions_downloader.start()
|
||||||
|
|
||||||
|
web_config = read_config()
|
||||||
|
|
||||||
|
if self.env_updater.should_download_settings(web_config):
|
||||||
|
self.env_updater.register_task_read_settings(taskman=task_manager)
|
||||||
|
self.env_thread = Thread(target=self.env_updater.read_settings, args=(web_config, False, task_manager), daemon=True)
|
||||||
|
self.env_thread.start()
|
||||||
|
|
||||||
def list_updates(self, internet_available: bool) -> List[PackageUpdate]:
|
def list_updates(self, internet_available: bool) -> List[PackageUpdate]:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -857,7 +865,7 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
|
|
||||||
app.status = PackageStatus.READY
|
app.status = PackageStatus.READY
|
||||||
|
|
||||||
def _map_suggestion(self, suggestion: dict) -> PackageSuggestion:
|
def _map_suggestion(self, suggestion: dict, env_settings: Optional[dict]) -> PackageSuggestion:
|
||||||
app = WebApplication(name=suggestion.get('name'),
|
app = WebApplication(name=suggestion.get('name'),
|
||||||
url=suggestion.get('url'),
|
url=suggestion.get('url'),
|
||||||
icon_url=suggestion.get('icon_url'),
|
icon_url=suggestion.get('icon_url'),
|
||||||
@@ -874,8 +882,8 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
elif isinstance(description, str):
|
elif isinstance(description, str):
|
||||||
app.description = description
|
app.description = description
|
||||||
|
|
||||||
if not app.version and self.env_settings and self.env_settings.get('electron'):
|
if not app.version and env_settings and env_settings.get('electron'):
|
||||||
app.version = self.env_settings['electron']['version']
|
app.version = env_settings['electron']['version']
|
||||||
app.latest_version = app.version
|
app.latest_version = app.version
|
||||||
|
|
||||||
app.status = PackageStatus.LOADING_DATA
|
app.status = PackageStatus.LOADING_DATA
|
||||||
@@ -888,9 +896,9 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
output.update(read_config())
|
output.update(read_config())
|
||||||
|
|
||||||
def list_suggestions(self, limit: int, filter_installed: bool) -> List[PackageSuggestion]:
|
def list_suggestions(self, limit: int, filter_installed: bool) -> List[PackageSuggestion]:
|
||||||
local_config = {}
|
web_config = {}
|
||||||
|
|
||||||
thread_config = Thread(target=self._fill_config_async, args=(local_config,))
|
thread_config = Thread(target=self._fill_config_async, args=(web_config,))
|
||||||
thread_config.start()
|
thread_config.start()
|
||||||
|
|
||||||
if self.suggestions:
|
if self.suggestions:
|
||||||
@@ -914,7 +922,7 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
else:
|
else:
|
||||||
installed = None
|
installed = None
|
||||||
|
|
||||||
res = []
|
env_settings, res = None, []
|
||||||
|
|
||||||
for s in suggestion_list:
|
for s in suggestion_list:
|
||||||
if limit <= 0 or len(res) < limit:
|
if limit <= 0 or len(res) < limit:
|
||||||
@@ -924,24 +932,24 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
if surl in installed:
|
if surl in installed:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
res.append(self._map_suggestion(s))
|
if env_settings is None: # reading settings if not already loaded
|
||||||
|
thread_config.join()
|
||||||
|
env_settings = self.env_updater.read_settings(web_config=web_config)
|
||||||
|
|
||||||
|
res.append(self._map_suggestion(s, env_settings))
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
if res:
|
if res:
|
||||||
if not self.env_settings and self.env_thread:
|
if env_settings:
|
||||||
self.env_thread.join()
|
|
||||||
self.env_thread = None # cleaning memory
|
|
||||||
|
|
||||||
if self.env_settings:
|
|
||||||
for s in res:
|
for s in res:
|
||||||
s.package.version = self.env_settings['electron']['version']
|
s.package.version = env_settings['electron']['version']
|
||||||
s.package.latest_version = s.package.version
|
s.package.latest_version = s.package.version
|
||||||
|
|
||||||
thread_config.join()
|
thread_config.join()
|
||||||
if local_config and local_config['environment']['electron']['version']:
|
if web_config and web_config['environment']['electron']['version']:
|
||||||
for s in res:
|
for s in res:
|
||||||
s.package.version = str(local_config['environment']['electron']['version'])
|
s.package.version = str(web_config['environment']['electron']['version'])
|
||||||
s.package.latest_version = s.package.version
|
s.package.latest_version = s.package.version
|
||||||
|
|
||||||
return res
|
return res
|
||||||
@@ -973,11 +981,11 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
def get_settings(self, screen_width: int, screen_height: int) -> ViewComponent:
|
def get_settings(self, screen_width: int, screen_height: int) -> ViewComponent:
|
||||||
config = read_config()
|
web_config = read_config()
|
||||||
max_width = floor(screen_width * 0.15)
|
max_width = floor(screen_width * 0.15)
|
||||||
|
|
||||||
input_electron = TextInputComponent(label=self.i18n['web.settings.electron.version.label'],
|
input_electron = TextInputComponent(label=self.i18n['web.settings.electron.version.label'],
|
||||||
value=config['environment']['electron']['version'],
|
value=web_config['environment']['electron']['version'],
|
||||||
tooltip=self.i18n['web.settings.electron.version.tooltip'],
|
tooltip=self.i18n['web.settings.electron.version.tooltip'],
|
||||||
placeholder='{}: 7.1.0'.format(self.i18n['example.short']),
|
placeholder='{}: 7.1.0'.format(self.i18n['example.short']),
|
||||||
max_width=max_width,
|
max_width=max_width,
|
||||||
@@ -990,35 +998,45 @@ class WebApplicationManager(SoftwareManager):
|
|||||||
|
|
||||||
select_nativefier = SingleSelectComponent(label="Nativefier",
|
select_nativefier = SingleSelectComponent(label="Nativefier",
|
||||||
options=native_opts,
|
options=native_opts,
|
||||||
default_option=[o for o in native_opts if o.value == config['environment']['system']][0],
|
default_option=[o for o in native_opts if o.value == web_config['environment']['system']][0],
|
||||||
type_=SelectViewType.COMBO,
|
type_=SelectViewType.COMBO,
|
||||||
tooltip=self.i18n['web.settings.nativefier.tip'],
|
tooltip=self.i18n['web.settings.nativefier.tip'],
|
||||||
max_width=max_width,
|
max_width=max_width,
|
||||||
id_='nativefier')
|
id_='nativefier')
|
||||||
|
|
||||||
form_env = FormComponent(label=self.i18n['web.settings.nativefier.env'].capitalize(), components=[input_electron, select_nativefier])
|
env_settings_exp = TextInputComponent(label=self.i18n['web.settings.cache_exp'],
|
||||||
|
tooltip=self.i18n['web.settings.cache_exp.tip'],
|
||||||
|
capitalize_label=False,
|
||||||
|
value=int(web_config['environment']['cache_exp']) if isinstance(web_config['environment']['cache_exp'], int) else '',
|
||||||
|
only_int=True,
|
||||||
|
max_width=max_width,
|
||||||
|
id_='web_cache_exp')
|
||||||
|
|
||||||
|
form_env = FormComponent(label=self.i18n['web.settings.nativefier.env'].capitalize(),
|
||||||
|
components=[input_electron, select_nativefier, env_settings_exp])
|
||||||
|
|
||||||
return PanelComponent([form_env])
|
return PanelComponent([form_env])
|
||||||
|
|
||||||
def save_settings(self, component: PanelComponent) -> Tuple[bool, Optional[List[str]]]:
|
def save_settings(self, component: PanelComponent) -> Tuple[bool, Optional[List[str]]]:
|
||||||
config = read_config()
|
web_config = read_config()
|
||||||
|
|
||||||
form_env = component.components[0]
|
form_env = component.components[0]
|
||||||
|
|
||||||
config['environment']['electron']['version'] = str(form_env.get_component('electron_version').get_value()).strip()
|
web_config['environment']['electron']['version'] = str(form_env.get_component('electron_version').get_value()).strip()
|
||||||
|
|
||||||
if len(config['environment']['electron']['version']) == 0:
|
if len(web_config['environment']['electron']['version']) == 0:
|
||||||
config['environment']['electron']['version'] = None
|
web_config['environment']['electron']['version'] = None
|
||||||
|
|
||||||
system_nativefier = form_env.get_component('nativefier').get_selected()
|
system_nativefier = form_env.get_component('nativefier').get_selected()
|
||||||
|
|
||||||
if system_nativefier and not nativefier.is_available():
|
if system_nativefier and not nativefier.is_available():
|
||||||
return False, [self.i18n['web.settings.env.nativefier.system.not_installed'].format('Nativefier')]
|
return False, [self.i18n['web.settings.env.nativefier.system.not_installed'].format('Nativefier')]
|
||||||
|
|
||||||
config['environment']['system'] = system_nativefier
|
web_config['environment']['system'] = system_nativefier
|
||||||
|
web_config['environment']['cache_exp'] = form_env.get_component('web_cache_exp').get_int_value()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
save_config(config, CONFIG_FILE)
|
save_config(web_config, CONFIG_FILE)
|
||||||
return True, None
|
return True, None
|
||||||
except:
|
except:
|
||||||
return False, [traceback.format_exc()]
|
return False, [traceback.format_exc()]
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
import tarfile
|
import tarfile
|
||||||
import traceback
|
import traceback
|
||||||
|
from datetime import datetime, timedelta
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from typing import Dict, List, Optional
|
from typing import Dict, List, Optional
|
||||||
@@ -20,7 +21,8 @@ from bauh.commons.html import bold
|
|||||||
from bauh.commons.system import SimpleProcess, ProcessHandler
|
from bauh.commons.system import SimpleProcess, ProcessHandler
|
||||||
from bauh.gems.web import ENV_PATH, NODE_DIR_PATH, NODE_BIN_PATH, NODE_MODULES_PATH, NATIVEFIER_BIN_PATH, \
|
from bauh.gems.web import ENV_PATH, NODE_DIR_PATH, NODE_BIN_PATH, NODE_MODULES_PATH, NATIVEFIER_BIN_PATH, \
|
||||||
ELECTRON_PATH, ELECTRON_DOWNLOAD_URL, ELECTRON_SHA256_URL, URL_ENVIRONMENT_SETTINGS, NPM_BIN_PATH, NODE_PATHS, \
|
ELECTRON_PATH, ELECTRON_DOWNLOAD_URL, ELECTRON_SHA256_URL, URL_ENVIRONMENT_SETTINGS, NPM_BIN_PATH, NODE_PATHS, \
|
||||||
nativefier, URL_NATIVEFIER, get_icon_path, ELECTRON_WIDEVINE_URL, ELECTRON_WIDEVINE_SHA256_URL
|
nativefier, URL_NATIVEFIER, ELECTRON_WIDEVINE_URL, ELECTRON_WIDEVINE_SHA256_URL, \
|
||||||
|
ENVIRONMENT_SETTINGS_CACHED_FILE, ENVIRONMENT_SETTINGS_TS_FILE, get_icon_path
|
||||||
from bauh.gems.web.model import WebApplication
|
from bauh.gems.web.model import WebApplication
|
||||||
from bauh.view.util.translation import I18n
|
from bauh.view.util.translation import I18n
|
||||||
|
|
||||||
@@ -44,6 +46,7 @@ class EnvironmentUpdater:
|
|||||||
self.file_downloader = file_downloader
|
self.file_downloader = file_downloader
|
||||||
self.i18n = i18n
|
self.i18n = i18n
|
||||||
self.http_client = http_client
|
self.http_client = http_client
|
||||||
|
self.task_read_settings_id = 'web_read_settings'
|
||||||
|
|
||||||
def _download_and_install(self, version: str, version_url: str, watcher: ProcessWatcher) -> bool:
|
def _download_and_install(self, version: str, version_url: str, watcher: ProcessWatcher) -> bool:
|
||||||
self.logger.info("Downloading NodeJS {}: {}".format(version, version_url))
|
self.logger.info("Downloading NodeJS {}: {}".format(version, version_url))
|
||||||
@@ -266,31 +269,103 @@ class EnvironmentUpdater:
|
|||||||
|
|
||||||
def _finish_task_download_settings(self, task_man: TaskManager):
|
def _finish_task_download_settings(self, task_man: TaskManager):
|
||||||
if task_man:
|
if task_man:
|
||||||
task_man.update_progress('web_down_sets', 100, None)
|
task_man.update_progress(self.task_read_settings_id, 100, None)
|
||||||
task_man.finish_task('web_down_sets')
|
task_man.finish_task(self.task_read_settings_id)
|
||||||
|
|
||||||
def read_settings(self, task_man: TaskManager = None) -> Optional[dict]:
|
def should_download_settings(self, web_config: dict) -> bool:
|
||||||
try:
|
try:
|
||||||
if task_man:
|
settings_exp = int(web_config['environment']['cache_exp'])
|
||||||
task_man.register_task('web_down_sets', self.i18n['web.task.download_settings'], get_icon_path())
|
except ValueError:
|
||||||
task_man.update_progress('web_down_sets', 10, None)
|
self.logger.error("Could not parse settings property 'environment.cache_exp': {}".format(web_config['environment']['cache_exp']))
|
||||||
|
return True
|
||||||
|
|
||||||
|
if settings_exp <= 0:
|
||||||
|
self.logger.info("No expiration time configured for the environment settings cache file.")
|
||||||
|
return True
|
||||||
|
|
||||||
|
self.logger.info("Checking cached environment settings file")
|
||||||
|
|
||||||
|
if not os.path.exists(ENVIRONMENT_SETTINGS_CACHED_FILE):
|
||||||
|
self.logger.warning("Environment settings file not cached.")
|
||||||
|
return True
|
||||||
|
|
||||||
|
if not os.path.exists(ENVIRONMENT_SETTINGS_TS_FILE):
|
||||||
|
self.logger.warning("Environment settings file has no timestamp associated with it.")
|
||||||
|
return True
|
||||||
|
|
||||||
|
with open(ENVIRONMENT_SETTINGS_TS_FILE) as f:
|
||||||
|
env_ts_str = f.read()
|
||||||
|
|
||||||
|
try:
|
||||||
|
env_timestamp = datetime.fromtimestamp(float(env_ts_str))
|
||||||
|
except:
|
||||||
|
self.logger.error("Could not parse environment settings file timestamp: {}".format(env_ts_str))
|
||||||
|
return True
|
||||||
|
|
||||||
|
return env_timestamp + timedelta(minutes=settings_exp) <= datetime.utcnow()
|
||||||
|
|
||||||
|
def read_cached_settings(self, web_config: dict) -> Optional[dict]:
|
||||||
|
if not self.should_download_settings(web_config):
|
||||||
|
with open(ENVIRONMENT_SETTINGS_CACHED_FILE) as f:
|
||||||
|
cached_settings_str = f.read()
|
||||||
|
|
||||||
|
try:
|
||||||
|
return yaml.safe_load(cached_settings_str)
|
||||||
|
except yaml.YAMLError:
|
||||||
|
self.logger.error('Could not parse the cache environment settings file: {}'.format(cached_settings_str))
|
||||||
|
|
||||||
|
def register_task_read_settings(self, taskman: TaskManager):
|
||||||
|
taskman.register_task(self.task_read_settings_id, self.i18n['web.task.download_settings'], get_icon_path())
|
||||||
|
|
||||||
|
def read_settings(self, web_config: dict, cache: bool = True, taskman: Optional[TaskManager] = None) -> Optional[dict]:
|
||||||
|
cached_settings = self.read_cached_settings(web_config) if cache else None
|
||||||
|
|
||||||
|
if cached_settings:
|
||||||
|
return cached_settings
|
||||||
|
|
||||||
|
try:
|
||||||
|
if taskman:
|
||||||
|
taskman.update_progress(self.task_read_settings_id, 10, None)
|
||||||
|
|
||||||
|
self.logger.info("Downloading environment settings")
|
||||||
res = self.http_client.get(URL_ENVIRONMENT_SETTINGS)
|
res = self.http_client.get(URL_ENVIRONMENT_SETTINGS)
|
||||||
|
|
||||||
if not res:
|
if not res:
|
||||||
self.logger.warning('Could not retrieve the environments settings from the cloud')
|
self.logger.warning('Could not retrieve the environments settings from the cloud')
|
||||||
self._finish_task_download_settings(task_man)
|
self._finish_task_download_settings(taskman)
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._finish_task_download_settings(task_man)
|
settings = yaml.safe_load(res.content)
|
||||||
return yaml.safe_load(res.content)
|
|
||||||
except yaml.YAMLError:
|
except yaml.YAMLError:
|
||||||
self.logger.error('Could not parse environment settings: {}'.format(res.text))
|
self.logger.error('Could not parse environment settings: {}'.format(res.text))
|
||||||
self._finish_task_download_settings(task_man)
|
self._finish_task_download_settings(taskman)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self.logger.info("Caching environment settings to disk")
|
||||||
|
cache_dir = os.path.dirname(ENVIRONMENT_SETTINGS_CACHED_FILE)
|
||||||
|
|
||||||
|
try:
|
||||||
|
Path(cache_dir).mkdir(parents=True, exist_ok=True)
|
||||||
|
except OSError:
|
||||||
|
self.logger.error("Could not create Web cache directory: {}".format(cache_dir))
|
||||||
|
self.logger.info('Finished')
|
||||||
|
self._finish_task_download_settings(taskman)
|
||||||
|
return
|
||||||
|
|
||||||
|
cache_timestamp = datetime.utcnow().timestamp()
|
||||||
|
with open(ENVIRONMENT_SETTINGS_CACHED_FILE, 'w+') as f:
|
||||||
|
f.write(yaml.safe_dump(settings))
|
||||||
|
|
||||||
|
with open(ENVIRONMENT_SETTINGS_TS_FILE, 'w+') as f:
|
||||||
|
f.write(str(cache_timestamp))
|
||||||
|
|
||||||
|
self._finish_task_download_settings(taskman)
|
||||||
|
self.logger.info("Finished")
|
||||||
|
return settings
|
||||||
|
|
||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
self._finish_task_download_settings(task_man)
|
self._finish_task_download_settings(taskman)
|
||||||
return
|
return
|
||||||
|
|
||||||
def _check_and_fill_electron(self, pkg: WebApplication, env: dict, local_config: dict, x86_x64: bool, widevine: bool, output: List[EnvironmentComponent]):
|
def _check_and_fill_electron(self, pkg: WebApplication, env: dict, local_config: dict, x86_x64: bool, widevine: bool, output: List[EnvironmentComponent]):
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ web.install.substatus.call_nativefier=Running {}
|
|||||||
web.install.substatus.checking_fixes=Checking if there are published fixes
|
web.install.substatus.checking_fixes=Checking if there are published fixes
|
||||||
web.install.substatus.options=Waiting for the installation options
|
web.install.substatus.options=Waiting for the installation options
|
||||||
web.install.substatus.shortcut=Generating a menu shortcut
|
web.install.substatus.shortcut=Generating a menu shortcut
|
||||||
|
web.settings.cache_exp=Environment settings expiration
|
||||||
|
web.settings.cache_exp.tip=It defines the period (in minutes) in which the stored environment settings are considered valid. Use 0 so that they are always updated.
|
||||||
web.settings.electron.version.label=Electron version
|
web.settings.electron.version.label=Electron version
|
||||||
web.settings.electron.version.tooltip=Defines an alternative Electron version to render the new installed apps
|
web.settings.electron.version.tooltip=Defines an alternative Electron version to render the new installed apps
|
||||||
web.settings.env.nativefier.system.not_installed={} seems not to be installed on your system
|
web.settings.env.nativefier.system.not_installed={} seems not to be installed on your system
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ web.install.substatus.call_nativefier=Running {}
|
|||||||
web.install.substatus.checking_fixes=Checking if there are published fixes
|
web.install.substatus.checking_fixes=Checking if there are published fixes
|
||||||
web.install.substatus.options=Waiting for the installation options
|
web.install.substatus.options=Waiting for the installation options
|
||||||
web.install.substatus.shortcut=Generating a menu shortcut
|
web.install.substatus.shortcut=Generating a menu shortcut
|
||||||
|
web.settings.cache_exp=Environment settings expiration
|
||||||
|
web.settings.cache_exp.tip=It defines the period (in minutes) in which the stored environment settings are considered valid. Use 0 so that they are always updated.
|
||||||
web.settings.electron.version.label=Electron version
|
web.settings.electron.version.label=Electron version
|
||||||
web.settings.electron.version.tooltip=Defines an alternative Electron version to render the new installed apps
|
web.settings.electron.version.tooltip=Defines an alternative Electron version to render the new installed apps
|
||||||
web.settings.env.nativefier.system.not_installed={} seems not to be installed on your system
|
web.settings.env.nativefier.system.not_installed={} seems not to be installed on your system
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ web.install.substatus.call_nativefier=Ejecutando {}
|
|||||||
web.install.substatus.checking_fixes=Verificando si hay correcciones publicadas
|
web.install.substatus.checking_fixes=Verificando si hay correcciones publicadas
|
||||||
web.install.substatus.options=Esperando las opciones de instalación
|
web.install.substatus.options=Esperando las opciones de instalación
|
||||||
web.install.substatus.shortcut=Generando un atajo de menú
|
web.install.substatus.shortcut=Generando un atajo de menú
|
||||||
|
web.settings.cache_exp=Expiración de configuraciones de ambiente
|
||||||
|
web.settings.cache_exp.tip=Define el período (en minutos) en el que las configuraciones del ambiente almacenadas se consideran válidas. Utilice 0 para que estén siempre actualizadas.
|
||||||
web.settings.electron.version.label=Versión del Electron
|
web.settings.electron.version.label=Versión del Electron
|
||||||
web.settings.electron.version.tooltip=Define una versión alternativa del Electron para renderizar las nuevas aplicaciones instaladas
|
web.settings.electron.version.tooltip=Define una versión alternativa del Electron para renderizar las nuevas aplicaciones instaladas
|
||||||
web.settings.env.nativefier.system.not_installed={} parece no estar instalado en su sistema
|
web.settings.env.nativefier.system.not_installed={} parece no estar instalado en su sistema
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ web.install.substatus.call_nativefier=Lancement {}
|
|||||||
web.install.substatus.checking_fixes=Verification de nouveaux correctifs disponibles
|
web.install.substatus.checking_fixes=Verification de nouveaux correctifs disponibles
|
||||||
web.install.substatus.options=En attente des options d'installation
|
web.install.substatus.options=En attente des options d'installation
|
||||||
web.install.substatus.shortcut=Génération d'un raccourci menu
|
web.install.substatus.shortcut=Génération d'un raccourci menu
|
||||||
|
web.settings.cache_exp=Environment settings expiration
|
||||||
|
web.settings.cache_exp.tip=It defines the period (in minutes) in which the stored environment settings are considered valid. Use 0 so that they are always updated.
|
||||||
web.settings.electron.version.label=Version d'Electron
|
web.settings.electron.version.label=Version d'Electron
|
||||||
web.settings.electron.version.tooltip=Definit une version alternativde d'Electron pour le rendu des dernières apps installées
|
web.settings.electron.version.tooltip=Definit une version alternativde d'Electron pour le rendu des dernières apps installées
|
||||||
web.settings.env.nativefier.system.not_installed={} n'a pas l'air d'être installé sur votre système
|
web.settings.env.nativefier.system.not_installed={} n'a pas l'air d'être installé sur votre système
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ web.install.substatus.call_nativefier=Running {}
|
|||||||
web.install.substatus.checking_fixes=Checking if there are published fixes
|
web.install.substatus.checking_fixes=Checking if there are published fixes
|
||||||
web.install.substatus.options=Waiting for the installation options
|
web.install.substatus.options=Waiting for the installation options
|
||||||
web.install.substatus.shortcut=Generating a menu shortcut
|
web.install.substatus.shortcut=Generating a menu shortcut
|
||||||
|
web.settings.cache_exp=Environment settings expiration
|
||||||
|
web.settings.cache_exp.tip=It defines the period (in minutes) in which the stored environment settings are considered valid. Use 0 so that they are always updated.
|
||||||
web.settings.electron.version.label=Electron version
|
web.settings.electron.version.label=Electron version
|
||||||
web.settings.electron.version.tooltip=Defines an alternative Electron version to render the new installed apps
|
web.settings.electron.version.tooltip=Defines an alternative Electron version to render the new installed apps
|
||||||
web.settings.env.nativefier.system.not_installed={} seems not to be installed on your system
|
web.settings.env.nativefier.system.not_installed={} seems not to be installed on your system
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ web.install.substatus.call_nativefier=Executando {}
|
|||||||
web.install.substatus.checking_fixes=Verificando se há correções publicadas
|
web.install.substatus.checking_fixes=Verificando se há correções publicadas
|
||||||
web.install.substatus.options=Aguardando as opções de instalação
|
web.install.substatus.options=Aguardando as opções de instalação
|
||||||
web.install.substatus.shortcut=Criando um atalho no menu
|
web.install.substatus.shortcut=Criando um atalho no menu
|
||||||
|
web.settings.cache_exp=Expiração das configurações de ambiente
|
||||||
|
web.settings.cache_exp.tip=Define o período (em minutos) em que as configurações do ambiente de instalação armazenadas são consideradas válidas. Utilize 0 para que elas sejam sempre atualizadas.
|
||||||
web.settings.electron.version.label=Versão do Electron
|
web.settings.electron.version.label=Versão do Electron
|
||||||
web.settings.electron.version.tooltip=Define uma versão alternativa do Electron para renderizar os novos aplicativos instalados
|
web.settings.electron.version.tooltip=Define uma versão alternativa do Electron para renderizar os novos aplicativos instalados
|
||||||
web.settings.env.nativefier.system.not_installed={} não parece estar instalado no seu sistema
|
web.settings.env.nativefier.system.not_installed={} não parece estar instalado no seu sistema
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ web.install.substatus.call_nativefier=Работает {}
|
|||||||
web.install.substatus.checking_fixes=Проверка опубликованных исправлений
|
web.install.substatus.checking_fixes=Проверка опубликованных исправлений
|
||||||
web.install.substatus.options=Ожидание опций установки
|
web.install.substatus.options=Ожидание опций установки
|
||||||
web.install.substatus.shortcut=Создается ярлык в меню
|
web.install.substatus.shortcut=Создается ярлык в меню
|
||||||
|
web.settings.cache_exp=Environment settings expiration
|
||||||
|
web.settings.cache_exp.tip=It defines the period (in minutes) in which the stored environment settings are considered valid. Use 0 so that they are always updated.
|
||||||
web.settings.electron.version.label=версия Electron
|
web.settings.electron.version.label=версия Electron
|
||||||
web.settings.electron.version.tooltip=Указывает альтернативный вариант Electron для визуализации устанавливаемых приложений
|
web.settings.electron.version.tooltip=Указывает альтернативный вариант Electron для визуализации устанавливаемых приложений
|
||||||
web.settings.env.nativefier.system.not_installed={} не установлен в Вашей системе
|
web.settings.env.nativefier.system.not_installed={} не установлен в Вашей системе
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ web.install.substatus.call_nativefier={} çalışıyor
|
|||||||
web.install.substatus.checking_fixes=Yayınlanmış düzeltmeler olup olmadığını kontrol et
|
web.install.substatus.checking_fixes=Yayınlanmış düzeltmeler olup olmadığını kontrol et
|
||||||
web.install.substatus.options=Kurulum seçenekleri bekleniyor
|
web.install.substatus.options=Kurulum seçenekleri bekleniyor
|
||||||
web.install.substatus.shortcut=Bir menü kısayolu oluşturuluyor
|
web.install.substatus.shortcut=Bir menü kısayolu oluşturuluyor
|
||||||
|
web.settings.cache_exp=Environment settings expiration
|
||||||
|
web.settings.cache_exp.tip=It defines the period (in minutes) in which the stored environment settings are considered valid. Use 0 so that they are always updated.
|
||||||
web.settings.electron.version.label=Electron sürümü
|
web.settings.electron.version.label=Electron sürümü
|
||||||
web.settings.electron.version.tooltip=Yeni yüklenen uygulamaları oluşturmak için alternatif bir Elektron sürümü tanımlar
|
web.settings.electron.version.tooltip=Yeni yüklenen uygulamaları oluşturmak için alternatif bir Elektron sürümü tanımlar
|
||||||
web.settings.env.nativefier.system.not_installed={} sisteminize kurulu değil gibi görünüyor
|
web.settings.env.nativefier.system.not_installed={} sisteminize kurulu değil gibi görünüyor
|
||||||
|
|||||||
@@ -19,16 +19,25 @@ class SuggestionsDownloader:
|
|||||||
self.logger = logger
|
self.logger = logger
|
||||||
self.taskman = taskman
|
self.taskman = taskman
|
||||||
self.i18n = i18n
|
self.i18n = i18n
|
||||||
|
self.task_id = 'web_sugs'
|
||||||
|
self._task_registered = False
|
||||||
|
self._task_finished = False
|
||||||
|
|
||||||
def _finish_task(self):
|
def _finish_task(self):
|
||||||
if self.taskman:
|
if self.taskman:
|
||||||
self.taskman.update_progress('web_sugs', 100, None)
|
self.taskman.update_progress(self.task_id, 100, None)
|
||||||
self.taskman.finish_task('web_sugs')
|
self.taskman.finish_task(self.task_id)
|
||||||
|
self._task_finished = True
|
||||||
|
self.logger.info("Finished")
|
||||||
|
|
||||||
|
def register_task(self):
|
||||||
|
if self.taskman and not self._task_registered and not self._task_finished:
|
||||||
|
self.taskman.register_task(self.task_id, self.i18n['web.task.suggestions'], get_icon_path())
|
||||||
|
self._task_registered = True
|
||||||
|
|
||||||
def download(self) -> dict:
|
def download(self) -> dict:
|
||||||
if self.taskman:
|
if self.taskman:
|
||||||
self.taskman.register_task('web_sugs', self.i18n['web.task.suggestions'], get_icon_path())
|
self.taskman.update_progress(self.task_id, 10, None)
|
||||||
self.taskman.update_progress('web_sugs', 10, None)
|
|
||||||
|
|
||||||
self.logger.info("Reading suggestions from {}".format(URL_SUGGESTIONS))
|
self.logger.info("Reading suggestions from {}".format(URL_SUGGESTIONS))
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user