[web] feature: new custom action button to install apps

This commit is contained in:
Vinicius Moreira
2021-12-15 13:40:20 -03:00
parent cbc52b68ee
commit 8576a1f169
11 changed files with 117 additions and 37 deletions

View File

@@ -56,6 +56,9 @@ class HttpClient:
elif isinstance(e, requests.exceptions.TooManyRedirects):
self.logger.warning(f"Too many redirects for GET -> {url}")
raise e
elif e.__class__ in (requests.exceptions.MissingSchema, requests.exceptions.InvalidSchema):
self.logger.warning(f"The URL '{url}' has an invalid schema")
raise e
self.logger.error("Could not retrieve data from '{}'".format(url))
traceback.print_exc()

View File

@@ -14,7 +14,7 @@ from typing import List, Type, Set, Tuple, Optional, Dict
import requests
import yaml
from colorama import Fore
from requests import exceptions, Response
from requests import Response
from bauh.api.abstract.context import ApplicationContext
from bauh.api.abstract.controller import SoftwareManager, SearchResult, UpgradeRequirements, TransactionResult, \
@@ -74,13 +74,22 @@ class WebApplicationManager(SoftwareManager):
self.suggestions = {}
self.configman = WebConfigManager()
self.idxman = SearchIndexManager(logger=context.logger)
self.custom_actions = [CustomSoftwareAction(i18n_label_key='web.custom_action.clean_env',
i18n_status_key='web.custom_action.clean_env.status',
manager=self,
manager_method='clean_environment',
icon_path=resource.get_path('img/web.svg', ROOT_DIR),
requires_root=False,
refresh=False)]
self.custom_actions = [
CustomSoftwareAction(i18n_label_key='web.custom_action.install_app',
i18n_status_key='web.custom_action.install_app.status',
manager=self,
manager_method='install_app',
icon_path=resource.get_path('img/web.svg', ROOT_DIR),
requires_root=False,
refresh=True),
CustomSoftwareAction(i18n_label_key='web.custom_action.clean_env',
i18n_status_key='web.custom_action.clean_env.status',
manager=self,
manager_method='clean_environment',
icon_path=resource.get_path('img/web.svg', ROOT_DIR),
requires_root=False,
refresh=False)
]
def _get_lang_header(self) -> str:
try:
@@ -222,7 +231,7 @@ class WebApplicationManager(SoftwareManager):
def _strip_url_protocol(self, url: str) -> str:
return RE_PROTOCOL_STRIP.split(url)[1].strip().lower()
def serialize_to_disk(self, pkg: SoftwarePackage, icon_bytes: bytes, only_icon: bool):
def serialize_to_disk(self, pkg: SoftwarePackage, icon_bytes: Optional[bytes], only_icon: bool):
super(WebApplicationManager, self).serialize_to_disk(pkg=pkg, icon_bytes=None, only_icon=False)
def _request_url(self, url: str) -> Optional[Response]:
@@ -230,8 +239,8 @@ class WebApplicationManager(SoftwareManager):
try:
return self.http_client.get(url, headers=headers, ignore_ssl=True, single_call=True, session=False, allow_redirects=True)
except (exceptions.ConnectionError, requests.exceptions.TooManyRedirects) as e:
self.logger.warning(f"Could not GET {url}. Exception: {e.__class__.__name__}")
except Exception as e:
self.logger.warning(f"Could not GET '{url}'. Exception: {e.__class__.__name__}")
def _map_url(self, url: str) -> Tuple["BeautifulSoup", requests.Response]:
url_res = self._request_url(url)
@@ -473,10 +482,10 @@ class WebApplicationManager(SoftwareManager):
def get_history(self, pkg: SoftwarePackage) -> PackageHistory:
pass
def _ask_install_options(self, app: WebApplication, watcher: ProcessWatcher) -> Tuple[bool, List[str]]:
def _ask_install_options(self, app: WebApplication, watcher: ProcessWatcher, pre_validated: bool) -> Tuple[bool, List[str]]:
watcher.change_substatus(self.i18n['web.install.substatus.options'])
inp_url = TextInputComponent(label=self.i18n['address'], value=app.url, read_only=True)
inp_url = TextInputComponent(label=self.i18n['address'], value=app.url, read_only=pre_validated)
inp_name = TextInputComponent(label=self.i18n['name'], value=app.name)
inp_desc = TextInputComponent(label=self.i18n['description'], value=app.description)
@@ -513,11 +522,15 @@ class WebApplicationManager(SoftwareManager):
icon_op_ded = InputOption(id_='icon_ded', label=self.i18n['web.install.option.wicon.deducted.label'], value=0,
tooltip=self.i18n['web.install.option.wicon.deducted.tip'].format('Nativefier'))
icon_op_disp = InputOption(id_='icon_disp', label=self.i18n['web.install.option.wicon.displayed.label'],
value=1, tooltip=self.i18n['web.install.option.wicon.displayed.tip'])
if pre_validated:
icon_op_disp = InputOption(id_='icon_disp', label=self.i18n['web.install.option.wicon.displayed.label'],
value=1, tooltip=self.i18n['web.install.option.wicon.displayed.tip'])
else:
icon_op_disp = None
inp_icon = SingleSelectComponent(type_=SelectViewType.COMBO,
options=[icon_op_disp, icon_op_ded],
options=[op for op in (icon_op_ded, icon_op_disp) if op],
default_option=icon_op_disp if app.icon_url and app.save_icon else icon_op_ded,
label=self.i18n['web.install.option.wicon.label'])
@@ -544,13 +557,24 @@ class WebApplicationManager(SoftwareManager):
check_options = MultipleSelectComponent(options=adv_opts, default_options=def_adv_opts, label=self.i18n['web.install.options.advanced'].capitalize())
res = watcher.request_confirmation(title=self.i18n['web.install.options_dialog.title'],
body=None,
components=[form_1, check_options],
confirmation_label=self.i18n['continue'].capitalize(),
deny_label=self.i18n['cancel'].capitalize())
install_ = watcher.request_confirmation(title=self.i18n['web.install.options_dialog.title'],
body=None,
components=[form_1, check_options],
confirmation_label=self.i18n['continue'].capitalize(),
deny_label=self.i18n['cancel'].capitalize())
if install_:
if not pre_validated:
typed_url = inp_url.get_value().strip()
if not typed_url or not self._request_url(typed_url):
watcher.show_message(title=self.i18n['error'].capitalize(),
type_=MessageType.ERROR,
body=self.i18n['web.custom_action.install_app.invalid_url'].format(url=bold(f'"{inp_url.get_value()}"')))
return False, []
else:
app.url = typed_url
if res:
selected = []
if check_options.values:
@@ -579,9 +603,9 @@ class WebApplicationManager(SoftwareManager):
app.set_custom_icon(icon_chooser.file_path)
selected.append('--icon={}'.format(icon_chooser.file_path))
app.save_icon = inp_icon.value == icon_op_disp
app.save_icon = inp_icon.value == icon_op_disp if icon_op_disp else False
return res, selected
return True, selected
return False, []
@@ -649,13 +673,9 @@ class WebApplicationManager(SoftwareManager):
pkg.name))
traceback.print_exc()
def install(self, pkg: WebApplication, root_password: str, disk_loader: DiskCacheLoader, watcher: ProcessWatcher) -> TransactionResult:
continue_install, install_options = self._ask_install_options(pkg, watcher)
def _install(self, pkg: WebApplication, install_options: List[str], watcher: ProcessWatcher) -> TransactionResult:
widevine_support = '--widevine' in install_options
if not continue_install:
return TransactionResult(success=False, installed=[], removed=[])
watcher.change_substatus(self.i18n['web.env.checking'])
handler = ProcessHandler(watcher)
@@ -664,7 +684,8 @@ class WebApplicationManager(SoftwareManager):
if web_config['environment']['system'] and not nativefier.is_available():
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)
return TransactionResult(success=False, installed=[], removed=[])
@@ -677,8 +698,9 @@ class WebApplicationManager(SoftwareManager):
if comps_to_update and not self._ask_update_permission(comps_to_update, watcher):
return TransactionResult(success=False, installed=[], removed=[])
if not self.env_updater.update(components=comps_to_update, handler=handler):
watcher.show_message(title=self.i18n['error'], body=self.i18n['web.env.error'].format(bold(pkg.name)), type_=MessageType.ERROR)
if not self.env_updater.update(components=comps_to_update, handler=handler):
watcher.show_message(title=self.i18n['error'], body=self.i18n['web.env.error'].format(bold(pkg.name)),
type_=MessageType.ERROR)
return TransactionResult(success=False, installed=[], removed=[])
Path(INSTALLED_PATH).mkdir(parents=True, exist_ok=True)
@@ -737,11 +759,13 @@ class WebApplicationManager(SoftwareManager):
if hasattr(pkg, prop):
try:
setattr(pkg, prop, val)
self.logger.info(f"Using custom installation property '{prop}' ({val if val else '<null>'}) for '{url_domain}' "
f"(Electron: {electron_version})")
self.logger.info(
f"Using custom installation property '{prop}' ({val if val else '<null>'}) for '{url_domain}' "
f"(Electron: {electron_version})")
except:
self.logger.error(f"Could not set the custom installation property '{prop}' ({val if val else '<null>'}) "
f"for '{url_domain}' (Electron: {electron_version})")
self.logger.error(
f"Could not set the custom installation property '{prop}' ({val if val else '<null>'}) "
f"for '{url_domain}' (Electron: {electron_version})")
watcher.change_substatus(self.i18n['web.install.substatus.call_nativefier'].format(bold('nativefier')))
@@ -754,7 +778,8 @@ class WebApplicationManager(SoftwareManager):
if not installed:
msg = '{}.{}.'.format(self.i18n['wen.install.error'].format(bold(pkg.name)),
self.i18n['web.install.nativefier.error.unknown'].format(bold(self.i18n['details'].capitalize())))
self.i18n['web.install.nativefier.error.unknown'].format(
bold(self.i18n['details'].capitalize())))
watcher.show_message(title=self.i18n['error'], body=msg, type_=MessageType.ERROR)
return TransactionResult(success=False, installed=[], removed=[])
@@ -825,6 +850,27 @@ class WebApplicationManager(SoftwareManager):
return TransactionResult(success=True, installed=[pkg], removed=[])
def install(self, pkg: WebApplication, root_password: str, disk_loader: DiskCacheLoader, watcher: ProcessWatcher) -> TransactionResult:
continue_install, install_options = self._ask_install_options(pkg, watcher, pre_validated=True)
if not continue_install:
return TransactionResult(success=False, installed=[], removed=[])
return self._install(pkg, install_options, watcher)
def install_app(self, root_password: str, watcher: ProcessWatcher) -> bool:
pkg = WebApplication()
continue_install, install_options = self._ask_install_options(pkg, watcher, pre_validated=False)
if not continue_install:
return False
if self._install(pkg, install_options, watcher).success:
self.serialize_to_disk(pkg, icon_bytes=None, only_icon=False)
return True
return False
def _gen_desktop_entry_content(self, pkg: WebApplication) -> str:
return """
[Desktop Entry]

View File

@@ -4,6 +4,9 @@ web.custom_action.clean_env.failed=An error occurred during the installation env
web.custom_action.clean_env.status=Cleaning the installation environment
web.custom_action.clean_env.success=Installation environment cleaned
web.custom_action.clean_env=Clean installation environment
web.custom_action.install_app=Install Web application
web.custom_action.install_app.invalid_url=The address {url} could not be found. It is not possible to finish the installation.
web.custom_action.install_app.status=Installing Web application
web.env.checking=Checking the Web installation environment
web.env.error=It seems there are issues with the Web installation environment. It wil not be possible to install {}.
web.environment.install=Installing {}

View File

@@ -4,6 +4,9 @@ web.custom_action.clean_env.failed=An error occurred during the installation env
web.custom_action.clean_env.status=Cleaning the installation environment
web.custom_action.clean_env.success=Installation environment cleaned
web.custom_action.clean_env=Clean installation environment
web.custom_action.install_app=Install Web application
web.custom_action.install_app.invalid_url=The address {url} could not be found. It is not possible to finish the installation.
web.custom_action.install_app.status=Installing Web application
web.env.checking=Checking the Web installation environment
web.env.error=It seems there are issues with the Web installation environment. It wil not be possible to install {}.
web.environment.install=Installing {}

View File

@@ -4,6 +4,9 @@ web.custom_action.clean_env.failed=Se produjo un error durante la limpieza del a
web.custom_action.clean_env.status=Limpiando el ambiente de instalación
web.custom_action.clean_env.success=Ambiente de instalación limpio
web.custom_action.clean_env=Limpiar ambiente de instalación
web.custom_action.install_app=Instalar aplicación Web
web.custom_action.install_app.invalid_url=No se pudo encontrar la dirección {url}. No es posible finalizar la instalación.
web.custom_action.install_app.status=Instalando aplicación Web
web.env.checking=Verificando el ambiente de instalación web
web.env.error=Parece que hay problemas con el ambiente de instalación web. No será posible instalar {}.
web.environment.install=Instalando {}

View File

@@ -4,6 +4,9 @@ web.custom_action.clean_env.failed=Une erreur est survenue lors du nettoyage de
web.custom_action.clean_env.status=Nettoyage de l'environnement d'installation
web.custom_action.clean_env.success=Environnement d'installation nettoyé
web.custom_action.clean_env=Nettoyage de l'environnement d'installation Web.
web.custom_action.install_app=Install Web application
web.custom_action.install_app.invalid_url=The address {url} could not be found. It is not possible to finish the installation.
web.custom_action.install_app.status=Installing Web application
web.env.checking=Verification de l'environnement d'installation Web.
web.env.error=Il y a des problèmes avec l'environnement d'installation Web. {} ne pourra pas être installé.
web.environment.install=Intallation de {}

View File

@@ -4,6 +4,9 @@ web.custom_action.clean_env.failed=An error occurred during the installation env
web.custom_action.clean_env.status=Cleaning the installation environment
web.custom_action.clean_env.success=Installation environment cleaned
web.custom_action.clean_env=Clean installation environment
web.custom_action.install_app=Install Web application
web.custom_action.install_app.invalid_url=The address {url} could not be found. It is not possible to finish the installation.
web.custom_action.install_app.status=Installing Web application
web.env.checking=Checking the Web installation environment
web.env.error=It seems there are issues with the Web installation environment. It wil not be possible to install {}.
web.environment.install=Installing {}

View File

@@ -4,6 +4,9 @@ web.custom_action.clean_env.failed=Ocorreu um problema durante a limpeza do ambi
web.custom_action.clean_env.status=Limpando ambiente de instalação
web.custom_action.clean_env.success=Ambiente de instalação limpo
web.custom_action.clean_env=Limpar ambiente de instalação
web.custom_action.install_app=Instalar aplicação Web
web.custom_action.install_app.invalid_url=O endereço {url} não foi encontrado. Não é possível finalizar a instalação.
web.custom_action.install_app.status=Instalando aplicação Web
web.env.checking=Verificando o ambiente de instalação Web
web.env.error=Parce que existem problemas com o ambiente de instalação Web. Não será possível instalar {}.
web.environment.nativefier=Instalando {}

View File

@@ -4,6 +4,9 @@ web.custom_action.clean_env=Очистка среды установки
web.custom_action.clean_env.failed=Произошла ошибка при очистке среды установки
web.custom_action.clean_env.status=Среда установки будет очищена
web.custom_action.clean_env.success=Среда установки очищена!
web.custom_action.install_app=Install Web application
web.custom_action.install_app.invalid_url=The address {url} could not be found. It is not possible to finish the installation.
web.custom_action.install_app.status=Installing Web application
web.env.checking=Проверка Веб-среды
web.env.error=Проблемы с Веб-средой. Невозможно установить {}.
web.environment.install=Устанавливается {}

View File

@@ -4,6 +4,9 @@ web.custom_action.clean_env.failed=Kurulum ortamı temizliği sırasında bir ha
web.custom_action.clean_env.status=Kurulum ortamını temizleme
web.custom_action.clean_env.success=Kurulum ortamı temizlendi
web.custom_action.clean_env=Temiz kurulum ortamı
web.custom_action.install_app=Install Web application
web.custom_action.install_app.invalid_url=The address {url} could not be found. It is not possible to finish the installation.
web.custom_action.install_app.status=Installing Web application
web.env.checking=Web kurulum ortamını kontrol et
web.env.error=Görünüşe göre Web kurulum ortamıyla ilgili sorunlar var. {} kurmak mümkün olmayacak.
web.environment.install={} yükleniyor