mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-06 22:54:16 +02:00
snaps: integrating with Ubuntu search API
This commit is contained in:
@@ -4,6 +4,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/).
|
||||
|
||||
## [0.4.1]
|
||||
### Improvements
|
||||
- retrieving some Snaps data (icon, description and confinement) through Ubuntu API instead of Snap Store
|
||||
|
||||
## [0.4.0] - 2019-07-25
|
||||
### Features
|
||||
- supporting snaps
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from fpakman.core.constants import CACHE_PATH
|
||||
|
||||
SNAP_STORE_URL = 'https://snapcraft.io'
|
||||
SNAP_API_URL = 'https://search.apps.ubuntu.com/api/v1'
|
||||
SNAP_CACHE_PATH = '{}/snap/installed'.format(CACHE_PATH)
|
||||
|
||||
@@ -114,7 +114,7 @@ class SnapManager(ApplicationManager):
|
||||
return []
|
||||
|
||||
def install_and_stream(self, app: SnapApplication, root_password: str) -> FpakmanProcess:
|
||||
return FpakmanProcess(subproc=snap.install_and_stream(app.base_data.name, app.install_cmd, root_password))
|
||||
return FpakmanProcess(subproc=snap.install_and_stream(app.base_data.name, app.confinement, root_password))
|
||||
|
||||
def is_enabled(self) -> bool:
|
||||
return snap.is_installed()
|
||||
|
||||
@@ -5,13 +5,13 @@ from fpakman.core.snap.constants import SNAP_CACHE_PATH
|
||||
|
||||
class SnapApplication(Application):
|
||||
|
||||
def __init__(self, base_data: ApplicationData, publisher: str, rev: str, notes: str, app_type: str, install_cmd: str = None):
|
||||
def __init__(self, base_data: ApplicationData, publisher: str, rev: str, notes: str, app_type: str, confinement: str = None):
|
||||
super(SnapApplication, self).__init__(base_data=base_data)
|
||||
self.publisher = publisher
|
||||
self.rev = rev
|
||||
self.notes = notes
|
||||
self.type = app_type
|
||||
self.install_cmd = install_cmd
|
||||
self.confinement = confinement
|
||||
|
||||
def has_history(self):
|
||||
return False
|
||||
@@ -46,7 +46,7 @@ class SnapApplication(Application):
|
||||
def get_data_to_cache(self):
|
||||
return {
|
||||
"icon_url": self.base_data.icon_url,
|
||||
'install_cmd': self.install_cmd,
|
||||
'confinement': self.confinement,
|
||||
'description': self.base_data.description
|
||||
}
|
||||
|
||||
@@ -56,5 +56,5 @@ class SnapApplication(Application):
|
||||
if data.get(base_attr):
|
||||
setattr(self.base_data, base_attr, data[base_attr])
|
||||
|
||||
if data.get('install_cmd'):
|
||||
self.install_cmd = data['install_cmd']
|
||||
if data.get('confinement'):
|
||||
self.confinement = data['confinement']
|
||||
|
||||
@@ -2,11 +2,7 @@ import re
|
||||
import subprocess
|
||||
from typing import List
|
||||
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from fpakman.core import system
|
||||
from fpakman.core.snap.constants import SNAP_STORE_URL
|
||||
|
||||
BASE_CMD = 'snap'
|
||||
|
||||
@@ -120,19 +116,12 @@ def uninstall_and_stream(app_name: str, root_password: str):
|
||||
return system.cmd_as_root([BASE_CMD, 'remove', app_name], root_password)
|
||||
|
||||
|
||||
def install_and_stream(app_name: str, custom_install_cmd: str, root_password: str) -> subprocess.Popen:
|
||||
def install_and_stream(app_name: str, confinement: str, root_password: str) -> subprocess.Popen:
|
||||
|
||||
install_cmd = [BASE_CMD, 'install', app_name] # default
|
||||
|
||||
if custom_install_cmd:
|
||||
install_cmd = custom_install_cmd.split(' ')
|
||||
else: # tries to retrieve the snapstore proper installation command
|
||||
res = requests.get('{}/{}'.format(SNAP_STORE_URL, app_name))
|
||||
|
||||
if res.status_code == 200:
|
||||
soup = BeautifulSoup(res.text, 'html.parser')
|
||||
input_install_cmd = soup.find("input", {"id": "snap-install"})
|
||||
install_cmd = input_install_cmd.get("value").strip().split(' ')
|
||||
if confinement == 'classic':
|
||||
install_cmd.append('--classic')
|
||||
|
||||
return system.cmd_as_root(install_cmd, root_password)
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
from colorama import Fore
|
||||
|
||||
from fpakman.core.controller import ApplicationManager
|
||||
from fpakman.core.model import ApplicationStatus
|
||||
from fpakman.core.snap import snap
|
||||
from fpakman.core.snap.constants import SNAP_STORE_URL
|
||||
from fpakman.core.snap.constants import SNAP_API_URL
|
||||
from fpakman.core.snap.model import SnapApplication
|
||||
from fpakman.core.worker import AsyncDataLoader
|
||||
from fpakman.util.cache import Cache
|
||||
@@ -28,34 +27,39 @@ class SnapAsyncDataLoader(AsyncDataLoader):
|
||||
def run(self):
|
||||
if self.app:
|
||||
self.app.status = ApplicationStatus.LOADING_DATA
|
||||
if not self.app.base_data.description:
|
||||
self.app.base_data.description = snap.get_info(self.app.base_data.name, ('description',)).get('description')
|
||||
|
||||
for _ in range(0, self.attempts):
|
||||
try:
|
||||
res = self.http_session.get('{}/{}'.format(SNAP_STORE_URL, self.app.base_data.name),
|
||||
timeout=self.timeout)
|
||||
res = self.http_session.get('{}/search?q={}'.format(SNAP_API_URL, self.app.base_data.name), timeout=self.timeout)
|
||||
|
||||
if res.status_code == 200 and res.text:
|
||||
soup = BeautifulSoup(res.text, 'html.parser')
|
||||
input_install_cmd = soup.find("input", {"id": "snap-install"})
|
||||
|
||||
try:
|
||||
snap_list = res.json()['_embedded']['clickindex:package']
|
||||
except:
|
||||
self.log_msg('Snap API response responded differently from expected for app: {}'.format(self.app.base_data.name))
|
||||
break
|
||||
|
||||
if not snap_list:
|
||||
break
|
||||
|
||||
snap_data = snap_list[0]
|
||||
|
||||
api_data = {
|
||||
'install_cmd': input_install_cmd.get("value").strip(),
|
||||
'description': self.app.base_data.description
|
||||
'confinement': snap_data.get('confinement'),
|
||||
'description': snap_data.get('description'),
|
||||
'icon_url': snap_data.get('icon_url') if self.download_icons else None
|
||||
}
|
||||
|
||||
img_icon = None
|
||||
|
||||
if self.download_icons:
|
||||
img_icon = soup.find('img', {"class": "p-snap-heading__icon"})
|
||||
|
||||
if img_icon and img_icon.get("src") and 'snapcraft-missing-icon' not in img_icon.get('src'):
|
||||
api_data['icon_url'] = img_icon.get("src")
|
||||
|
||||
self.api_cache.add(self.app.base_data.id, api_data)
|
||||
self.app.install_cmd = api_data['install_cmd']
|
||||
self.app.base_data.icon_url = api_data.get('icon_url')
|
||||
self.app.confinement = api_data['confinement']
|
||||
self.app.base_data.icon_url = api_data['icon_url']
|
||||
|
||||
if not api_data.get('description'):
|
||||
api_data['description'] = snap.get_info(self.app.base_data.name, ('description',)).get('description')
|
||||
|
||||
self.app.base_data.description = api_data['description']
|
||||
|
||||
self.app.status = ApplicationStatus.READY
|
||||
|
||||
if self.app.supports_disk_cache():
|
||||
@@ -65,7 +69,7 @@ class SnapAsyncDataLoader(AsyncDataLoader):
|
||||
else:
|
||||
self.log_msg("Could not retrieve app data for id '{}'. Server response: {}. Body: {}".format(self.app.base_data.id, res.status_code, res.content.decode()), Fore.RED)
|
||||
except:
|
||||
self.log_msg("Could not retrieve app data for id '{}'".format(app.base_data.id), Fore.YELLOW)
|
||||
self.log_msg("Could not retrieve app data for id '{}'".format(self.app.base_data.id), Fore.YELLOW)
|
||||
traceback.print_exc()
|
||||
time.sleep(0.5)
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
pyqt5>=5.12
|
||||
requests>=2.22
|
||||
colorama>=0.4.1
|
||||
beautifulsoup4>=4.7
|
||||
colorama>=0.4.1
|
||||
Reference in New Issue
Block a user