[feature][tray] displaying a notification when there is a new bauh release

This commit is contained in:
Vinícius Moreira
2020-04-20 15:05:52 -03:00
parent 81acfa7934
commit d5049c8466
18 changed files with 111 additions and 57 deletions

View File

@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [0.9.1] 2020 ## [0.9.1] 2020
### Features
- Tray
- displaying a notification when there is a new bauh release
### Improvements ### Improvements
- Internet availability checking code - Internet availability checking code
- Arch - Arch

View File

@@ -1,12 +1,10 @@
import os import re
import re import re
import time import time
import traceback import traceback
from pathlib import Path
from threading import Thread from threading import Thread
from typing import List, Set, Type, Tuple, Dict from typing import List, Set, Type, Tuple, Dict
from bauh import __app_name__, __version__
from bauh.api.abstract.controller import SoftwareManager, SearchResult, ApplicationContext, UpgradeRequirements, \ from bauh.api.abstract.controller import SoftwareManager, SearchResult, ApplicationContext, UpgradeRequirements, \
UpgradeRequirement UpgradeRequirement
from bauh.api.abstract.disk import DiskCacheLoader from bauh.api.abstract.disk import DiskCacheLoader
@@ -14,11 +12,10 @@ from bauh.api.abstract.handler import ProcessWatcher, TaskManager
from bauh.api.abstract.model import SoftwarePackage, PackageUpdate, PackageHistory, PackageSuggestion, \ from bauh.api.abstract.model import SoftwarePackage, PackageUpdate, PackageHistory, PackageSuggestion, \
CustomSoftwareAction CustomSoftwareAction
from bauh.api.abstract.view import ViewComponent, TabGroupComponent from bauh.api.abstract.view import ViewComponent, TabGroupComponent
from bauh.api.constants import CACHE_PATH
from bauh.api.exception import NoInternetException from bauh.api.exception import NoInternetException
from bauh.commons import internet from bauh.commons import internet
from bauh.commons.html import bold, link
from bauh.view.core.settings import GenericSettingsManager from bauh.view.core.settings import GenericSettingsManager
from bauh.view.core.update import check_for_update
RE_IS_URL = re.compile(r'^https?://.+') RE_IS_URL = re.compile(r'^https?://.+')
@@ -330,50 +327,13 @@ class GenericSoftwareManager(SoftwareManager):
return updates return updates
def _check_for_updates(self) -> str:
self.logger.info("Checking for updates")
try:
releases = self.http_client.get_json('https://api.github.com/repos/vinifmor/bauh/releases')
if releases:
latest = None
for r in releases:
if not r['draft']:
latest = r
break
if latest and latest.get('tag_name'):
notifications_dir = '{}/updates'.format(CACHE_PATH)
release_file = '{}/{}'.format(notifications_dir, latest['tag_name'])
if os.path.exists(release_file):
self.logger.info("Release {} already notified".format(latest['tag_name']))
elif latest['tag_name'] > __version__:
try:
Path(notifications_dir).mkdir(parents=True, exist_ok=True)
with open(release_file, 'w+') as f:
f.write('')
except:
self.logger.error("An error occurred while trying to create the update notification file: {}".format(release_file))
return self.i18n['warning.update_available'].format(bold(__app_name__), bold(latest['tag_name']), link(latest.get('html_url', '?')))
else:
self.logger.info("No updates available")
else:
self.logger.warning("No official release found")
else:
self.logger.warning("No releases returned from the GitHub API")
except:
self.logger.error("An error occurred while trying to retrieve the current releases")
def list_warnings(self, internet_available: bool = None) -> List[str]: def list_warnings(self, internet_available: bool = None) -> List[str]:
warnings = [] warnings = []
int_available = internet.is_available() int_available = internet.is_available()
if int_available: if int_available:
updates_msg = self._check_for_updates() updates_msg = check_for_update(self.logger, self.http_client, self.i18n)
if updates_msg: if updates_msg:
warnings.append(updates_msg) warnings.append(updates_msg)

57
bauh/view/core/update.py Normal file
View File

@@ -0,0 +1,57 @@
import logging
import os
from pathlib import Path
from bauh import __app_name__, __version__
from bauh.api.constants import CACHE_PATH
from bauh.api.http import HttpClient
from bauh.commons.html import bold, link
from bauh.view.util.translation import I18n
def check_for_update(logger: logging.Logger, http_client: HttpClient, i18n: I18n, tray: bool = False) -> str:
"""
:param logger:
:param http_client:
:param i18n:
:param file_prefix: notification file prefix
:return: bauh update warning string or 'None' if no update is available
"""
logger.info("Checking for updates")
try:
releases = http_client.get_json('https://api.github.com/repos/vinifmor/bauh/releases')
if releases:
latest = None
for r in releases:
if not r['draft']:
latest = r
break
if latest and latest.get('tag_name'):
notifications_dir = '{}/updates'.format(CACHE_PATH)
release_file = '{}/{}{}'.format(notifications_dir, '' if not tray else 'tray_', latest['tag_name'])
if os.path.exists(release_file):
logger.info("Release {} already notified".format(latest['tag_name']))
elif latest['tag_name'] > __version__:
try:
Path(notifications_dir).mkdir(parents=True, exist_ok=True)
with open(release_file, 'w+') as f:
f.write('')
except:
logger.error("An error occurred while trying to create the update notification file: {}".format(release_file))
if tray:
return i18n['tray.warning.update_available'].format(__app_name__, latest['tag_name'])
else:
return i18n['warning.update_available'].format(bold(__app_name__), bold(latest['tag_name']), link(latest.get('html_url', '?')))
else:
logger.info("No updates available")
else:
logger.warning("No official release found")
else:
logger.warning("No releases returned from the GitHub API")
except:
logger.error("An error occurred while trying to retrieve the current releases")

View File

@@ -15,12 +15,15 @@ from PyQt5.QtWidgets import QSystemTrayIcon, QMenu
from bauh import __app_name__, ROOT_DIR from bauh import __app_name__, ROOT_DIR
from bauh.api.abstract.model import PackageUpdate from bauh.api.abstract.model import PackageUpdate
from bauh.api.http import HttpClient
from bauh.commons.system import run_cmd from bauh.commons.system import run_cmd
from bauh.context import generate_i18n from bauh.context import generate_i18n
from bauh.view.core.tray_client import TRAY_CHECK_FILE from bauh.view.core.tray_client import TRAY_CHECK_FILE
from bauh.view.core.update import check_for_update
from bauh.view.qt.about import AboutDialog from bauh.view.qt.about import AboutDialog
from bauh.view.qt.view_utils import load_resource_icon from bauh.view.qt.view_utils import load_resource_icon
from bauh.view.util import util, resource from bauh.view.util import util, resource
from bauh.view.util.translation import I18n
CLI_PATH = '{}/bin/bauh-cli'.format(sys.exec_prefix) CLI_PATH = '{}/bin/bauh-cli'.format(sys.exec_prefix)
@@ -78,6 +81,25 @@ class UpdateCheck(QThread):
self._notify_updates() self._notify_updates()
class AppUpdateCheck(Thread):
def __init__(self, http_client: HttpClient, logger: logging.Logger, i18n: I18n, interval: int = 300):
super(AppUpdateCheck, self).__init__(daemon=True)
self.interval = interval
self.http_client = http_client
self.logger = logger
self.i18n = i18n
def run(self):
while True:
update_msg = check_for_update(http_client=self.http_client, logger=self.logger, i18n=self.i18n, tray=True)
if update_msg:
util.notify_user(msg=update_msg)
time.sleep(self.interval)
class TrayIcon(QSystemTrayIcon): class TrayIcon(QSystemTrayIcon):
def __init__(self, config: dict, screen_size: QSize, logger: logging.Logger, manage_process: Popen = None, settings_process: Popen = None): def __init__(self, config: dict, screen_size: QSize, logger: logging.Logger, manage_process: Popen = None, settings_process: Popen = None):
@@ -87,6 +109,7 @@ class TrayIcon(QSystemTrayIcon):
self.manage_process = manage_process self.manage_process = manage_process
self.settings_process = settings_process self.settings_process = settings_process
self.logger = logger self.logger = logger
self.http_client = HttpClient(logger=logger)
if config['ui']['tray']['default_icon']: if config['ui']['tray']['default_icon']:
self.icon_default = QIcon(config['ui']['tray']['default_icon']) self.icon_default = QIcon(config['ui']['tray']['default_icon'])
@@ -135,6 +158,9 @@ class TrayIcon(QSystemTrayIcon):
self.recheck_thread.signal.connect(self.notify_updates) self.recheck_thread.signal.connect(self.notify_updates)
self.recheck_thread.start() self.recheck_thread.start()
self.update_thread = AppUpdateCheck(http_client=self.http_client, logger=self.logger, i18n=self.i18n)
self.update_thread.start()
self.last_updates = set() self.last_updates = set()
self.update_notification = bool(config['system']['notifications']) self.update_notification = bool(config['system']['notifications'])
self.lock_notify = Lock() self.lock_notify = Lock()

View File

@@ -371,7 +371,7 @@ version.unknown=no informat
version.updated=actualitzada version.updated=actualitzada
view.components.file_chooser.placeholder=Feu clic aquí per seleccionar view.components.file_chooser.placeholder=Feu clic aquí per seleccionar
warning=avís warning=avís
warning.update_available=There is a new {} update available ({}). Checkout the news at {}. warning.update_available=There is a new {} version available ({}). Checkout the news at {}.
welcome=us donem la benvinguda welcome=us donem la benvinguda
window_manage.input_search.placeholder=Cerca window_manage.input_search.placeholder=Cerca
window_manage.input_search.tooltip=Escriviu i premeu Intro per a cercar aplicacions window_manage.input_search.tooltip=Escriviu i premeu Intro per a cercar aplicacions

View File

@@ -370,7 +370,7 @@ version.unknown=unbekannt
version.updated=geupdated version.updated=geupdated
view.components.file_chooser.placeholder=Auswählen view.components.file_chooser.placeholder=Auswählen
warning=Warnung warning=Warnung
warning.update_available=There is a new {} update available ({}). Checkout the news at {}. warning.update_available=There is a new {} version available ({}). Checkout the news at {}.
welcome=Willkommen welcome=Willkommen
window_manage.input_search.placeholder=Suchbegriff window_manage.input_search.placeholder=Suchbegriff
window_manage.input_search.tooltip=Suchbegriff eingeben und Enter drücken, um zu suchen window_manage.input_search.tooltip=Suchbegriff eingeben und Enter drücken, um zu suchen

View File

@@ -371,7 +371,7 @@ version=version
view.components.file_chooser.placeholder=Click here to select view.components.file_chooser.placeholder=Click here to select
warning=warning warning=warning
welcome=welcome welcome=welcome
warning.update_available=There is a new {} update available ({}). Checkout the news at {}. warning.update_available=There is a new {} version available ({}). Checkout the news at {}.
window_manage.input_search.placeholder=Search window_manage.input_search.placeholder=Search
window_manage.input_search.tooltip=Type and press ENTER to search for applications window_manage.input_search.tooltip=Type and press ENTER to search for applications
yes=yes yes=yes

View File

@@ -371,7 +371,7 @@ version.unknown=versión no informada
version.updated=actualizada version.updated=actualizada
view.components.file_chooser.placeholder=Pulse aquí para seleccionar view.components.file_chooser.placeholder=Pulse aquí para seleccionar
warning=aviso warning=aviso
warning.update_available=Hay una nueva actualización de {} disponible ({}). Vea las novedades en {}. warning.update_available=Hay una nueva versión de {} disponible ({}). Vea las novedades en {}.
welcome=bienvenido welcome=bienvenido
window_manage.input_search.placeholder=Buscar window_manage.input_search.placeholder=Buscar
window_manage.input_search.tooltip=Escriba y oprima Intro para buscar aplicaciones window_manage.input_search.tooltip=Escriba y oprima Intro para buscar aplicaciones

View File

@@ -373,7 +373,7 @@ version.unknown=non informato
version.updated=aggiornata version.updated=aggiornata
view.components.file_chooser.placeholder=Fai clic qui per selezionare view.components.file_chooser.placeholder=Fai clic qui per selezionare
warning=Avviso warning=Avviso
warning.update_available=There is a new {} update available ({}). Checkout the news at {}. warning.update_available=There is a new {} version available ({}). Checkout the news at {}.
welcome=benvenuto welcome=benvenuto
window_manage.input_search.placeholder=Cerca window_manage.input_search.placeholder=Cerca
window_manage.input_search.tooltip=Digitare e premere INVIO per cercare applicazioni window_manage.input_search.tooltip=Digitare e premere INVIO per cercare applicazioni

View File

@@ -370,7 +370,7 @@ version.updated=atualizada
version=versão version=versão
view.components.file_chooser.placeholder=Clique aqui para selecionar view.components.file_chooser.placeholder=Clique aqui para selecionar
warning=aviso warning=aviso
warning.update_available=Há uma nova atualização do {} disponível ({}). Confira as novidades em {} warning.update_available=Há uma nova versão do {} disponível ({}). Confira as novidades em {}
welcome=bem vindo welcome=bem vindo
window_manage.input_search.placeholder=Buscar window_manage.input_search.placeholder=Buscar
window_manage.input_search.tooltip=Digite e pressione ENTER para buscar aplicativos window_manage.input_search.tooltip=Digite e pressione ENTER para buscar aplicativos

View File

@@ -370,7 +370,7 @@ version.unknown=не сообщать
version.updated=Обновленная version.updated=Обновленная
view.components.file_chooser.placeholder=Нажмите здесь, чтобы выбрать view.components.file_chooser.placeholder=Нажмите здесь, чтобы выбрать
warning=Предупреждение warning=Предупреждение
warning.update_available=There is a new {} update available ({}). Checkout the news at {}. warning.update_available=There is a new {} version available ({}). Checkout the news at {}.
welcome=Добро пожаловать! welcome=Добро пожаловать!
window_manage.input_search.placeholder=Поиск window_manage.input_search.placeholder=Поиск
window_manage.input_search.tooltip=Введите и нажмите ENTER для поиска приложений window_manage.input_search.tooltip=Введите и нажмите ENTER для поиска приложений

View File

@@ -4,4 +4,5 @@ tray.action.about=Quant a
tray.action.refreshing=Refrescant tray.action.refreshing=Refrescant
tray.settings=configuració tray.settings=configuració
notification.update={} actualització disponible notification.update={} actualització disponible
notification.updates={} actualitzacions disponibles notification.updates={} actualitzacions disponibles
tray.warning.update_available=New {} version available ({})

View File

@@ -4,4 +4,5 @@ tray.action.about=Über
tray.action.refreshing=Aktualisieren tray.action.refreshing=Aktualisieren
tray.settings=Einstellungen tray.settings=Einstellungen
notification.update={} Update verfügbar notification.update={} Update verfügbar
notification.updates={} Updates verfügbar notification.updates={} Updates verfügbar
tray.warning.update_available=New {} version available ({})

View File

@@ -4,4 +4,5 @@ tray.action.about=About
tray.action.refreshing=Refreshing tray.action.refreshing=Refreshing
tray.settings=Settings tray.settings=Settings
notification.update={} available update notification.update={} available update
notification.updates={} available updates notification.updates={} available updates
tray.warning.update_available=New {} version available ({})

View File

@@ -4,4 +4,5 @@ tray.action.about=Acerca de
tray.action.refreshing=Recargando tray.action.refreshing=Recargando
tray.settings=configuraciones tray.settings=configuraciones
notification.update={} actualización disponible notification.update={} actualización disponible
notification.updates={} actualizaciones disponibles notification.updates={} actualizaciones disponibles
tray.warning.update_available=Nueva versión de {} disponible ({})

View File

@@ -4,4 +4,5 @@ tray.action.about=Informazioni su
tray.action.refreshing=Refreshing tray.action.refreshing=Refreshing
tray.settings=impostazioni tray.settings=impostazioni
notification.update={} aggiornamento disponibile notification.update={} aggiornamento disponibile
notification.updates={} aggiornamenti disponibile notification.updates={} aggiornamenti disponibile
tray.warning.update_available=New {} version available ({})

View File

@@ -4,4 +4,5 @@ tray.action.about=Sobre
tray.action.refreshing=Recarregando tray.action.refreshing=Recarregando
tray.settings=Configurações tray.settings=Configurações
notification.update={} atualização disponível notification.update={} atualização disponível
notification.updates={} atualizações disponíveis notification.updates={} atualizações disponíveis
tray.warning.update_available=Nova versão do {} disponível ({})

View File

@@ -4,4 +4,5 @@ tray.action.about=О программе
tray.action.refreshing=Обновляется tray.action.refreshing=Обновляется
tray.settings=Настройки tray.settings=Настройки
notification.update={} обновления доступно notification.update={} обновления доступно
notification.updates={} обновлений доступно notification.updates={} обновлений доступно
tray.warning.update_available=New {} version available ({})