Ignore:
Timestamp:
Jun 13, 2018, 1:42:39 PM (14 months ago)
Author:
Juanma
Message:

fix wrong update

Location:
lliurex-store/trunk/fuentes
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • lliurex-store/trunk/fuentes/debian/changelog

    r7383 r7432  
     1lliurex-store (0.5.4.6) xenial; urgency=medium
     2
     3  * Fix wrong update
     4
     5 -- Juanma Navarro Mañez <juanma1980@gmail.com>  Wed, 13 Jun 2018 13:41:28 +0200
     6
    17lliurex-store (0.5.4.5) xenial; urgency=high
    28
  • lliurex-store/trunk/fuentes/lliurex-store-gui/usr/share/lliurex-store/lliurex-store-gui/DetailsBox.py

    r7096 r7432  
    515515       
    516516        def open_clicked(self,widget):
    517                 if self.core.main_window.current_pkg["bundle"]=='snap':
    518                         snap=self.core.main_window.current_pkg["name"]
     517                if self.core.main_window.current_pkg["name"].endswith('.snap'):
     518                        snap=self.core.main_window.current_pkg["name"].replace('.snap','')
    519519                        if os.path.exists("/snap/bin/%s"%snap):
    520520                                os.system("/snap/bin/%s"%snap)
    521                 elif self.core.main_window.current_pkg["bundle"]=='appimage':
    522                         appimg=self.core.main_window.current_pkg["package"]
    523                         if os.path.exists(os.getenv("HOME")+"/.lliurex-store/appimg/%s"%appimg):
    524                                 os.system(os.getenv("HOME")+"/.lliurex-store/appimg/%s"%appimg)
     521                elif self.core.main_window.current_pkg["name"].endswith('.appimage'):
     522                        appimg=self.core.main_window.current_pkg["name"].lower()
     523                        if os.path.exists(os.getenv("HOME")+"/.local/bin/%s"%appimg):
     524                                os.system(os.getenv("HOME")+"/.local/bin/%s"%appimg)
     525                elif 'Zomando' in self.core.main_window.current_pkg["categories"]:
     526                        zmd=self.core.main_window.current_pkg["id"]+".zmd"
     527                        if os.path.exists("/usr/share/zero-center/zmds/%s"%zmd):
     528                                os.system("pe /usr/share/zero-center/zmds/%s"%zmd)
    525529                else:
    526530                        desktop=self.core.main_window.current_pkg["id"]
  • lliurex-store/trunk/fuentes/lliurex-store-gui/usr/share/lliurex-store/lliurex-store-gui/ResourcesManager.py

    r7092 r7432  
    55import time
    66import json
    7 
     7import re
    88import gi
    99gi.require_version('Gtk', '3.0')
     
    4343                if os.path.isfile(icon):
    4444                        return(icon)
     45
     46                if icon.startswith("http"):
     47                        cache_dir=os.getenv("HOME")+"/.cache/lliurex-store/icons"
     48                        icon_name=icon.split("/")[-1]
     49                        if not os.path.exists(cache_dir):
     50                                os.makedirs(cache_dir)
     51                        if os.path.isfile(cache_dir+"/"+icon_name):
     52                                return(cache_dir+"/"+icon_name)
     53                        icon_file=cache_dir+"/"+icon_name
     54                        url=icon
     55                        try:
     56                                req=urllib2.Request(url,headers=HEADER)
     57                                res=urllib2.urlopen(req)
     58                                x=open(icon_file,"wb")
     59                                x.write(res.read())
     60                                x.close()
     61                        except Exception as e:
     62                                icon_file=''
     63                        finally:
     64                                return(icon_file)
     65       
    4566               
    4667                component=pkg_info["component"]
     
    5576                        for dist in ["xenial-updates","xenial-security","xenial"]:
    5677                                # "64x64/" is included in pkg_info["icon"]
    57                                 if "64x64/" not in icon:
     78#                               if "64x64/" not in icon:
     79                                if not re.match("[0-9]*x[0-9]*\/",icon):
    5880                                        icon="64x64/" + icon
    5981                                        if debian_name+"_"+debian_name not in icon:
    6082                                                icon=icon.replace(debian_name,debian_name+"_"+debian_name)
     83                                                if not icon.endswith(".png"):
     84                                                        icon=icon+'.png'
    6185                                        if "pyromaths" in icon:
    6286                                                icon="64x64/pyromaths_pyromaths.png"
     
    6488                                ret_icon=self.icons_path+"%s/%s"%(component,icon)
    6589                                if os.path.exists(ret_icon):
    66                                        
    6790                                        return ret_icon
     91                                else:
     92                                        ret_icon=ret_icon.replace("64x64","128x128")
     93                                        if os.path.exists(ret_icon):
     94                                                return ret_icon
     95                                        icon="64x64/" + pkg_info['icon']
     96                                ret_icon=self.icons_path+"%s/%s"%(component,icon)
     97                                if os.path.exists(ret_icon):
     98                                        return ret_icon
     99                                else:
     100                                #Last attempt
     101                                        pkg_id=pkg_info['id'].split('.')[-2]
     102                                        icon="64x64/%s_%s.png"%(debian_name,pkg_id)
     103                                ret_icon=self.icons_path+"%s/%s"%(component,icon)
     104                                if os.path.exists(ret_icon):
     105                                        return ret_icon
     106                                else:
     107                                #Unaccurate icon search...
     108                                        for icon_file in os.listdir(self.icons_path+"/"+component+"/64x64/"):
     109                                                if re.search("^.*"+pkg_info['icon']+".*\.png",icon_file):
     110                                                        ret_icon=self.icons_path+"%s/64x64/%s"%(component,icon_file)
     111                                                        return ret_icon
     112                                                               
    68113
    69114                ret_icon=self.package_icon
  • lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/appImageManager.py

    r7143 r7432  
    11#The name of the main class must match the file name in lowercase
     2import re
    23import urllib
    34from urllib.request import Request
     
    67import json
    78import os
    8 from subprocess import call
    99import sys
    1010import threading
    11 from bs4 import BeautifulSoup
     11import queue
     12import time
    1213import random
    13 import time
    1414import gi
    1515from gi.repository import Gio
    1616gi.require_version('AppStreamGlib', '1.0')
    1717from gi.repository import AppStreamGlib as appstream
     18from bs4 import BeautifulSoup
     19#from subprocess import call
    1820
    1921class appimagemanager:
    2022        def __init__(self):
    21                 self.dbg=False
     23                self.dbg=True
    2224                self.progress=0
    2325                self.partial_progress=0
     
    2628                self.result['data']={}
    2729                self.result['status']={}
    28                 self.conf_dir=os.getenv("HOME")+"/.cache/lliurex-store"
    29                 self.bundles_dir=self.conf_dir+"/bundles"
     30                self.cache_dir=os.getenv("HOME")+"/.cache/lliurex-store"
     31                self.icons_dir=self.cache_dir+"/icons"
     32                self.bundles_dir=self.cache_dir+"/xmls/appimage"
    3033                self.bundle_types=['appimg']
    31                 self.appimage_dir=os.getenv("HOME")+"/.local/bin/"
     34#               self.appimage_dir=os.getenv("HOME")+"/.lliurex-store/appimg"
     35                self.appimage_dir=os.getenv("HOME")+"/.local/bin"
    3236                #To get the description of an app we must go to a specific url defined in url_info.
    3337                #$(appname) we'll be replaced with the appname so the url matches the right one.
    3438                #If other site has other url naming convention it'll be mandatory to define it with the appropiate replacements
    35                 self.repos={'probono':{'url':'https://dl.bintray.com/probono/AppImages', 'url_info':'https://bintray.com/probono/AppImages/$(appname)'}}
    36                 #Appimges not stored in a repo must be listed here, providing the download url and the info url (if there's any)
     39                self.repos={'appimagehub':{'type':'json','url':'https://appimage.github.io/feed.json','url_info':''}}
     40                #Appimges not stored in a repo must be listed in this file, providing the download url and the info url (if there's any)
    3741                self.external_appimages="/usr/share/lliurex-store/files/external_appimages.json"
     42                self.locale=['ca_ES@valencia','ca@valencia','qcv','ca','ca_ES','es_ES','es','en_US','en_GB','en','C']
    3843                self.disabled=False
    39                 self.count=0
     44                self.icon_cache_enabled=True
     45                self.image_cache_enabled=True
     46                self.apps_for_store=queue.Queue()
    4047        #def __init__
    4148
     
    6168                else:
    6269                        self.store=appstream.Store()
     70                self.appimage_store=appstream.Store()
    6371                self.progress=0
    6472                self.result['status']={'status':-1,'msg':''}
    65                 self.result['data']=''
     73                self.result['data']=[]
     74                self.threads=[]
    6675                dataList=[]
    6776                if self.disabled:
     
    7180                        self._chk_installDir()
    7281                        if action=='load':
    73                                 self.result['data']=self._load_appimage_store(self.store)
     82                                self._load_appimage_store()
     83#                               self.result['data']=self._load_appimage_store()
     84                                #wait till threads end (if any)
     85                                self._debug("Ending threads...")
     86#                               for app in self.apps_for_store:
     87                                for th in threading.enumerate():
     88                                        if th.is_alive():
     89                                                try:
     90                                                        th.join(5)
     91                                                except:
     92                                                        pass
     93                                while not self.apps_for_store.empty():
     94                                        app=self.apps_for_store.get()
     95                                        self.store.add_app(app)
     96                                self.result['data']=self.store
    7497                        else:
    7598                                for app_info in applist:
     
    81104                                        if action=='pkginfo':
    82105                                                dataList.append(self._get_info(app_info))
    83                                         self.progress+=int(self.partial_progress/len(applist))
     106                                        self.progress+=int(self.partial_progress/len(applist))-1
    84107                                self.result['data']=list(dataList)
    85108                self.progress=100
     
    118141                        self._set_status(4)
    119142                else:
    120                                 #                       appimage_url=self.repository_url+'/'+app_info['package']
    121                         appimage_url=app_info['homepage']+'/'+app_info['package']
     143#                       appimage_url=app_info['installerUrl']+'/'+app_info['package']
     144                        appimage_url=app_info['channel_releases']['appimage'][0]
    122145                        self._debug("Downloading "+appimage_url)
    123146                        dest_path=self.appimage_dir+'/'+app_info['package']
     
    163186        #def _remove_appimage
    164187
    165         def _get_info(self,app_info):
    166                 app_info['state']='available'
    167                 if os.path.isfile(self.appimage_dir+'/'+app_info['package']):
    168                         app_info['state']='installed'
    169                 #Get size
    170                 appimage_url=app_info['homepage']+'/'+app_info['package']
    171                 dest_path=self.appimage_dir+'/'+app_info['package']
    172                 if appimage_url:
    173                         try:
    174                                 with urllib.request.urlopen(appimage_url) as response:
    175                                         app_info['size']=(response.info()['Content-Length'])
    176                         except:
    177                                 app_info['size']=0
    178                 self._set_status(0)
    179                 self.partial_progress=100
    180                 return(app_info)
    181         #def _get_info
    182 
    183         def _load_appimage_store(self,store):
    184                 self._download_bundles_catalogue()
     188        def _load_appimage_store(self,store=None):
     189                self._get_bundles_catalogue()
    185190                if os.path.exists(self.bundles_dir):
    186191                        for bundle_type in self.bundle_types:
     
    207212        #def _generic_file_load
    208213
    209         def _download_bundles_catalogue(self):
    210                 CURSOR_UP='\033[F'
    211                 ERASE_LINE='\033[K'
    212                 content=''
     214        def _get_bundles_catalogue(self):
    213215                applist=[]
    214                 progress_bar="#"
    215                 self.descriptions_dict={}
     216                appdict={}
    216217                all_apps=[]
    217218                outdir=self.bundles_dir+'/appimg/'
    218219                #Load repos
    219220                for repo_name,repo_info in self.repos.items():
    220                         if self._chk_bundle_dir(outdir):
    221                                 self._debug("Fetching repo %s"%repo_info['url'])
    222 ##                                      print (("Fetching %s catalogue: "+progress_bar)%repo_type,end="\r")
    223 ##                                      progress_bar=progress_bar+"#"
    224 ##                                      print (("Fetching %s catalogue: "+progress_bar)%repo_type,end="\r")
    225                                 applist=self._generate_applist(self._fetch_repo(repo_info['url']),repo_name)
    226 ##                                      progress_bar=progress_bar+"##"
    227 ##                                      print (("Fetching %s catalogue: "+progress_bar)%repo_type,end="\r")
    228                                 self._debug("Processing info...")
    229                                 self._th_generate_xml_catalog(applist,outdir,repo_info['url_info'],repo_info['url'],repo_name,progress_bar)
    230                                 self._debug("Fetched repo "+repo_info['url'])
    231                                 all_apps.extend(applist)
    232                         else:
     221                        if not os.path.isdir(self.bundles_dir):
     222                                try:
     223                                        os.makedirs(self.bundles_dir)
     224                                except:
    233225                                        self._debug("appImage catalogue could not be fetched: Permission denied")
     226                        self._debug("Fetching repo %s"%repo_info['url'])
     227                        if repo_info['type']=='json':
     228                                applist=self._process_appimage_json(self._fetch_repo(repo_info['url']),repo_name)
     229
     230                        self._debug("Fetched repo "+repo_info['url'])
     231                        self._th_generate_xml_catalog(applist,outdir,repo_info['url_info'],repo_info['url'],repo_name)
     232                        all_apps.extend(applist)
    234233                #Load external apps
    235234                for app_name,app_info in self._get_external_appimages().items():
    236                         if self._chk_bundle_dir(outdir):
    237                                 appimage=app_info['url'].split('/')[-1]
    238                                 appimage_url='/'.join(app_info['url'].split('/')[0:-1])
     235                        if os.path.isdir(self.bundles_dir):
     236                                appinfo=self._init_appinfo()
     237                                appinfo['name']=app_info['url'].split('/')[-1]
     238                                appinfo['package']=app_info['url'].split('/')[-1]
     239                                appinfo['homepage']='/'.join(app_info['url'].split('/')[0:-1])
    239240                                self._debug("Fetching external appimage %s"%app_info['url'])
    240                                 applist=[appimage]
    241                                 self._debug("Processing info...")
    242                                 self._th_generate_xml_catalog(applist,outdir,app_info['url_info'],appimage_url,app_name,progress_bar)
     241                                appinfo['bundle']='appimage'
     242                                applist=[appinfo]
     243                                self._th_generate_xml_catalog(applist,outdir,app_info['url_info'],app_info['url'],app_name)
    243244                                self._debug("Fetched appimage "+app_info['url'])
    244245                                all_apps.extend(applist)
    245246                        else:
    246247                                self._debug("External appImage could not be fetched: Permission denied")
    247 
    248 
    249 ##              print (("Removing old entries..."))
    250                 self._clean_bundle_catalogue(all_apps,outdir)
     248                self._debug("Removing old entries...")
     249#               self._clean_bundle_catalogue(all_apps,outdir)
    251250                return(True)
    252         #def _download_bundles_catalogue
    253 
     251        #def _get_bundles_catalogue
     252       
     253        def _fetch_repo(self,repo):
     254                req=Request(repo, headers={'User-Agent':'Mozilla/5.0'})
     255                with urllib.request.urlopen(req) as f:
     256                        content=(f.read().decode('utf-8'))
     257               
     258                return(content)
     259        #def _fetch_repo
     260       
    254261        def _get_external_appimages(self):
    255262                external_appimages={}
     
    262269                self._debug(external_appimages)
    263270                return external_appimages
    264 
     271        #def _get_external_appimages
     272       
     273        def _process_appimage_json(self,data,repo_name):
     274                applist=[]
     275                json_data=json.loads(data)
     276                if 'items' in json_data.keys():
     277                        for appimage in json_data['items']:
     278                                appinfo=self._th_process_appimage(appimage)
     279                                if appinfo:
     280                                        applist.append(appinfo)
     281                return (applist)
     282        #_process_appimage_json
     283
     284        def _th_process_appimage(self,appimage):
     285                appinfo=None
     286                releases=[]
     287                if 'links' in appimage.keys():
     288                        if appimage['links']:
     289                                appinfo=self.load_json_appinfo(appimage)
     290#Deprecated. appImage releases will be load on the info stage
     291#                       releases=self._get_releases_from_json(appimage)
     292#                       if releases:
     293#                               appinfo['releases']=releases
     294#                               for release in releases:
     295#                                       #Release has the direct download url
     296#                                       tmp_release=release.split('/')
     297#                                       tmp_appinfo=appinfo.copy()
     298#                                       rel_number=tmp_release[-2]
     299#                                       rel_name=tmp_release[-1].lower().replace('.appimage','')
     300#                                       self._debug("Release: %s"%release)
     301#                                       tmp_appinfo['name']=rel_name
     302#                                       tmp_appinfo['package']=tmp_release[-1]
     303#                                       tmp_appinfo['homepage']='/'.join(tmp_release[0:-1])
     304#                                       self.queue.put(tmp_appinfo)
     305                return(appinfo)
     306        #def _th_process_appimage
     307
     308        def load_json_appinfo(self,appimage):
     309                appinfo=self._init_appinfo()
     310                appinfo['name']=appimage['name']
     311                appinfo['package']=appimage['name']
     312                if 'license' in appimage.keys():
     313                        appinfo['license']=appimage['license']
     314                appinfo['summary']=''
     315                if 'description' in appimage.keys():
     316                        appinfo['description']=appimage['description']
     317                if 'categories' in appimage.keys():
     318                        appinfo['categories']=appimage['categories']
     319                if 'icon' in appimage.keys():
     320                        appinfo['icon']=appimage['icon']
     321                if 'icons' in appimage.keys():
     322                        self._debug("Loading icon %s"%appimage['icons'])
     323                        if appimage['icons']:
     324                                self._debug("Loading icon %s"%appimage['icons'][0])
     325                                appinfo['icon']=appimage['icons'][0]
     326                if 'screenshots' in appimage.keys():
     327                        appinfo['thumbnails']=appimage['screenshots']
     328                if 'links' in appimage.keys():
     329                        if appimage['links']:
     330                                for link in appimage['links']:
     331                                        if 'url' in link.keys() and link['type']=='Download':
     332                                                appinfo['installerUrl']=link['url']
     333                if 'authors' in appimage.keys():
     334                        if appimage['authors']:
     335                                for author in appimage['authors']:
     336                                        if 'url' in author.keys():
     337                                                self._debug("Author: %s"%author['url'])
     338                                                appinfo['homepage']=author['url']
     339                else:
     340                        appinfo['homepage']='/'.join(appinfo['installerUrl'].split('/')[0:-1])
     341                appinfo['bundle']=['appimage']
     342                return appinfo
     343        #def load_json_appinfo
     344
     345        def _th_generate_xml_catalog(self,applist,outdir,info_url,repo,repo_name):
     346                maxconnections = 2
     347                threads=[]
     348                semaphore = threading.BoundedSemaphore(value=maxconnections)
     349                random_applist = list(applist)
     350                random.shuffle(random_applist)
     351                for app in applist:
     352                        th=threading.Thread(target=self._th_write_xml, args = (app,outdir,info_url,repo,repo_name,semaphore))
     353                        threads.append(th)
     354                        th.start()
     355        #def _th_generate_xml_catalog
     356
     357        def     _th_write_xml(self,appinfo,outdir,info_url,repo,repo_name,semaphore):
     358                semaphore.acquire()
     359                self._add_appimage(appinfo)
     360                semaphore.release()
     361        #def _th_write_xml
     362
     363#       def _add_appimage(self,appinfo,repo_info):
     364        def _add_appimage(self,appinfo):
     365                #Search in local store for the app
     366                sw_new=False
     367                app=appstream.App()
     368                app_orig=self.store.get_app_by_pkgname(appinfo['package'].lower())
     369                if not app_orig:
     370                        app_orig=self.store.get_app_by_id(appinfo['package'].lower()+".desktop")
     371                if app_orig:
     372                        self._debug("Extending app %s"%appinfo['package'])
     373                        app=self._copy_app_from_appstream(app_orig,app)
     374                else:
     375                        self._debug("Generating new %s"%appinfo['package'])
     376                app.set_id("appimagehub.%s"%appinfo['name'].lower()+'.appimage')
     377                app.set_id_kind=appstream.IdKind.DESKTOP
     378                sw_new=True
     379
     380                icon=appstream.Icon()
     381                screenshot=appstream.Screenshot()
     382                app.set_name("C",appinfo['name']+".appimage")
     383                app.add_pkgname(appinfo['package'].lower()+".appimage")
     384                if appinfo['license']:
     385                        app.set_project_license(appinfo['license'])
     386                bundle=appstream.Bundle()
     387                bundle.set_kind(bundle.kind_from_string('APPIMAGE'))
     388                bundle.set_id(appinfo['package']+'.appimage')
     389#               if app_orig:
     390#                       app_orig.add_bundle(bundle)
     391                app.add_bundle(bundle)
     392                app.add_keyword("C","appimage")
     393                app.add_category("appimage")
     394                app.add_url(appstream.UrlKind.UNKNOWN,appinfo['installerUrl'])
     395                app.add_url(appstream.UrlKind.HOMEPAGE,appinfo['homepage'])
     396                if sw_new:
     397                        app.add_keyword("C",appinfo['package'])
     398                        app.set_name("C",appinfo['name']+".appimage")
     399                        description="This is an AppImage bundle of app %s. It hasn't been tested by our developers and comes from a 3rd party dev team. Please use it carefully.\n%s"%(appinfo['name'],appinfo['description'])
     400                        summary=' '.join(list(description.split(' ')[:8]))
     401                        if len(description.split(' '))>8:
     402                                summary+="... "
     403                        app.set_description("C",description)
     404                        app.set_comment("C",summary)
     405                        for category in appinfo['categories']:
     406                                app.add_category(category)
     407                if appinfo['icon']:
     408                        if self.icon_cache_enabled:
     409                                icon.set_kind(appstream.IconKind.LOCAL)
     410                                icon.set_name(self._download_file(appinfo['icon'],appinfo['name'],self.icons_dir))
     411                        else:
     412                                icon.set_kind(appstream.IconKind.REMOTE)
     413                                icon.set_name(pkg.get_icon())
     414                                icon.set_url(pkg.get_icon())
     415                        app.add_icon(icon)
     416                if appinfo['thumbnails']:
     417                        img=appstream.Image()
     418                        if not appinfo['thumbnails'][0].startswith('http'):
     419                                        appinfo['screenshot']=appinfo['thumbnails'][0]
     420                                        appinfo['screenshot']="https://appimage.github.io/database/%s"%appinfo['screenshot']
     421                        img.set_kind(appstream.ImageKind.SOURCE)
     422                        img.set_url(appinfo['screenshot'])
     423                        screenshot.add_image(img)
     424                        app.add_screenshot(screenshot)
     425                #Adds the app to the store
     426#               self._debug("Adding %s"%appinfo['package'])
     427                self.apps_for_store.put(app)
     428                if not os.path.isfile(self.bundles_dir+'/'+app.get_id_filename()):
     429                        gioFile=Gio.File.new_for_path('%s/%s.xml'%(self.bundles_dir,app.get_id_filename()))
     430                        app.to_file(gioFile)
     431        #def _add_appimage
     432
     433        def _copy_app_from_appstream(self,app_orig,app):
     434                app.set_id("appimage."+app_orig.get_id())
     435                for category in app_orig.get_categories():
     436                        app.add_category(category)
     437                for screenshot in app_orig.get_screenshots():
     438                        app.add_screenshot(screenshot)
     439                for icon in app_orig.get_icons():
     440                        app.add_icon(icon)
     441                for localeItem in self.locale:
     442                        if app_orig.get_name(localeItem):
     443                                app.set_name(localeItem,app_orig.get_name(localeItem)+".appimage")
     444                        if app_orig.get_description(localeItem):
     445                                app.set_description(localeItem,app_orig.get_description(localeItem))
     446                        if app_orig.get_comment(localeItem):
     447                                app.set_comment(localeItem,app_orig.get_comment(localeItem))
     448                app.set_origin(app_orig.get_origin())
     449                return app
     450
     451        def _clean_bundle_catalogue(self,applist,outdir):
     452                xml_files_list=[]
     453                applist=[item.lower() for item in applist]
     454                for xml_file in os.listdir(outdir):
     455                        if xml_file.endswith('appdata.xml'):
     456                                xml_files_list.append(xml_file.lower().replace('appdata.xml','appimage'))
     457       
     458                if xml_files_list:
     459                        xml_discard_list=list(set(xml_files_list).difference(applist))
     460                        for discarded_file in xml_discard_list:
     461                                os.remove(outdir+'/'+discarded_file.replace('appimage','appdata.xml'))
     462        #def _clean_bunlde_catalogue
     463
     464        def _download_file(self,url,app_name,dest_dir):
     465#               target_file=self.icons_folder+'/'+app_name+".png"
     466                target_file=dest_dir+'/'+app_name+".png"
     467                if not url.startswith('http'):
     468                        url="https://appimage.github.io/database/%s"%url
     469                if not os.path.isfile(target_file):
     470#                       shutil.copy("/usr/share/icons/hicolor/128x128/apps/lliurex-store.png",target_file)
     471#                       if not os.fork():
     472                        if not os.path.isfile(target_file):
     473                                self._debug("Downloading %s to %s"%(url,target_file))
     474                                try:
     475                                        with urllib.request.urlopen(url) as response, open(target_file, 'wb') as out_file:
     476                                                bf=16*1024
     477                                                acumbf=0
     478                                                file_size=int(response.info()['Content-Length'])
     479                                                while True:
     480                                                        if acumbf>=file_size:
     481                                                            break
     482                                                        shutil.copyfileobj(response, out_file,bf)
     483                                                        acumbf=acumbf+bf
     484                                        st = os.stat(target_file)
     485                                except Exception as e:
     486                                        self._debug("Unable to download %s"%url)
     487                                        self._debug("Reason: %s"%e)
     488                                        target_file=''
     489#                               os._exit(0)
     490                return(target_file)
     491        #def _download_file
     492       
    265493        def _chk_bundle_dir(self,outdir):
    266494                msg_status=True
     
    273501                return(os.access(outdir,os.W_OK|os.R_OK|os.X_OK|os.F_OK))
    274502        #def _chk_bundle_dir
    275 
    276         def _fetch_repo(self,repo):
    277                 req=Request(repo, headers={'User-Agent':'Mozilla/5.0'})
    278                 with urllib.request.urlopen(req) as f:
    279                         content=(f.read().decode('utf-8'))
    280                
    281                 return(content)
    282         #def _fetch_repo
    283 
    284         def _generate_applist(self,content,repo_name):
    285                 garbage_list=[]
    286                 applist=[]
    287                 #webscrapping for probono repo
    288                 if repo_name=='probono':
    289                         garbage_list=content.split(' ')
    290                         for garbage_line in garbage_list:
    291                                 if garbage_line.endswith('AppImage"'):
    292                                         app=garbage_line.replace('href=":','')
    293                                         applist.append(app.replace('"',''))
    294                 #Example of a webscrapping from another site
    295 #               if repo_name='other_repo_name':
    296 #                       for garbage_line in garbage_list:
    297 #                                       if garbage_line.startswith('file="'):
    298 #                                               if 'appimage' in garbage_line:
    299 #                                                       app=garbage_line.replace('file="','')
    300 #                                                       app=app.replace('\n','')
    301 #                                                       self._debug("Add %s"%app)
    302 #                                                       applist.append(app.replace('"',''))
    303 
    304                 return(applist)
    305         #def _generate_applist
    306 
    307         def _th_generate_xml_catalog(self,applist,outdir,info_url,repo,repo_name,progress_bar=''):
    308                 CURSOR_UP='\033[F'
    309                 ERASE_LINE='\033[K'
    310                 maxconnections = 10
    311                 semaphore = threading.BoundedSemaphore(value=maxconnections)
    312                 random_applist = list(applist)
    313                 random.shuffle(random_applist)
    314                 len_applist=len(random_applist)
    315                 inc=30/len_applist
    316 #               print (CURSOR_UP)
    317                 for app in random_applist:
    318                         th=threading.Thread(target=self._th_write_xml, args = (app,outdir,info_url,repo,repo_name,semaphore,inc))
    319                         th.start()
    320 #               os.system('setterm -cursor off')
    321 #               while threading.active_count()>2: #Discard both main and own threads
    322 #                       for i in range(len(progress_bar),int(self.progress)):
    323 #                               progress_bar='#'+progress_bar
    324 #                       print (CURSOR_UP)
    325 #                       print (("Fetching %s catalogue: "+progress_bar)%repo_type,end="\r")
    326 #               os.system('setterm -cursor on')
    327         #def _th_generate_xml_catalog
    328 
    329         def _th_write_xml(self,app,outdir,info_url,repo,repo_name,semaphore,inc):
    330                 semaphore.acquire()
    331                 lock=threading.Lock()
    332                 name_splitted=app.split('-')
    333                 name=name_splitted[0]
    334                 version=name_splitted[1]
    335                 arch=name_splitted[2]
    336                 filename=outdir+app.lower().replace('appimage',"appdata.xml")
    337                 self._debug("checking if we need to download "+filename)
    338                 if not os.path.isfile(filename):
    339                         self._write_xml_file(filename,app,name,version,info_url,repo,repo_name,lock)
    340                 with lock:
    341                         self.progress=self.progress+inc
    342                 semaphore.release()
    343         #def _th_write_xml
    344 
    345         def _write_xml_file(self,filename,app,name,version,info_url,repo,repo_name,lock):
    346                         self._debug("Generating "+app+" xml")
    347                         f=open(filename,'w')
    348                         f.write('<?xml version="1.0" encoding="UTF-8"?>'+"\n")
    349                         f.write("<components version=\"0.10\">\n")
    350                         f.write("<component  type=\"desktop-application\">\n")
    351                         f.write("  <id>"+app.lower()+"</id>\n")
    352                         f.write("  <pkgname>"+app+"</pkgname>\n")
    353                         f.write("  <name>"+name+"</name>\n")
    354                         f.write("  <metadata_license>CC0-1.0</metadata_license>\n")
    355                         f.write("  <provides><binary>"+app+"</binary></provides>\n")
    356                         f.write("  <releases>\n")
    357                         f.write("  <release version=\""+version+"\" timestamp=\"1408573857\"></release>\n")
    358                         f.write("  </releases>\n")
    359                         f.write("  <launchable type=\"desktop-id\">"+name+".desktop</launchable>\n")
    360                         with lock:
    361                                 try:
    362                                         if name in self.descriptions_dict.keys():
    363                                                 description=self.descriptions_dict[name]
     503       
     504        def _init_appinfo(self):
     505                appInfo={'appstream_id':'',\
     506                'id':'',\
     507                'name':'',\
     508                'version':'',\
     509                'channel_releases':{},\
     510                'component':'',\
     511                'package':'',\
     512                'license':'',\
     513                'summary':'',\
     514                'description':'',\
     515                'categories':[],\
     516                'icon':'',\
     517                'screenshot':'',\
     518                'thumbnails':[],\
     519                'video':'',\
     520                'homepage':'',\
     521                'installerUrl':'',\
     522                'state':'',\
     523                'depends':'',\
     524                'kudos':'',\
     525                'suggests':'',\
     526                'extraInfo':'',\
     527                'size':'',\
     528                'bundle':'',\
     529                'updatable':'',\
     530                }
     531                return(appInfo)
     532        #def _init_appinfo
     533       
     534        def _get_info(self,app_info):
     535                if app_info['installerUrl']:
     536                        app_info['channel_releases']={'appimage':[]}
     537                        app_info['channel_releases']['appimage']=self._get_releases(app_info)
     538                app_info['state']='available'
     539                if os.path.isfile(self.appimage_dir+'/'+app_info['package']):
     540                        app_info['state']='installed'
     541                #Get size
     542                if 'appimage' in app_info['channel_releases'].keys():
     543                        if app_info['channel_releases']['appimage'][0]:
     544                                appimage_url=app_info['channel_releases']['appimage'][0]
     545                                dest_path=self.appimage_dir+'/'+app_info['package']
     546                                if appimage_url:
     547                                        try:
     548                                                with urllib.request.urlopen(appimage_url) as response:
     549                                                        app_info['size']=(response.info()['Content-Length'])
     550                                        except:
     551                                                app_info['size']=0
     552                        else:
     553                                app_info['size']=0
     554                        #Version (unaccurate aprox)
     555                        app_info['version']=app_info['channel_releases']['appimage'][0].split('/')[-2]
     556#                       try:
     557#                               app_info['version']="%s.%s"%(version.split('.')[1],version.split('.')[2])
     558#                       except:
     559#                               app_info['version']="%s"%version.split('_')[-1]
     560
     561                self._set_status(0)
     562                self.partial_progress=100
     563                return(app_info)
     564        #def _get_info
     565
     566        def _get_releases(self,app_info):
     567                releases=[]
     568                releases_page=''
     569                self._debug("Info url: %s"%app_info['installerUrl'])
     570                url_source=""
     571                try:
     572                        if 'github' in app_info['installerUrl']:
     573                                releases_page="https://github.com"
     574                        if 'gitlab' in app_info['installerUrl']:
     575                                releases_page="https://gitlab.com"
     576                        if 'opensuse' in app_info['installerUrl'].lower():
     577                                releases_page=""
     578                                url_source="opensuse"
     579#                               app_info['installerUrl']=app_info['installerUrl']+"/download"
     580
     581                        with urllib.request.urlopen(app_info['installerUrl']) as f:
     582                                content=(f.read().decode('utf-8'))
     583                                soup=BeautifulSoup(content,"html.parser")
     584                                package_a=soup.findAll('a', attrs={ "href" : re.compile(r'.*\.[aA]pp[iI]mage$')})
     585
     586                                for package_data in package_a:
     587                                        if url_source=="opensuse":
     588                                                package_name=package_data.findAll('a', attrs={"class" : "mirrorbrain-btn"})
    364589                                        else:
    365                                                 description=self._get_description(name,info_url,repo_name)
    366                                                 self.descriptions_dict.update({name:description})
    367                                 except:
    368                                         description=''
    369                         summary=' '.join(list(description.split(' ')[:8]))
    370                         description="This is an AppImage bundle of app "+name+". It hasn't been tested by our developers and comes from a 3rd party dev team. Please use it carefully.\n"+description
    371                         if not summary:
    372                                 summary=' '.join(list(description.split(' ')[:8]))
    373                         f.write("  <description><p></p><p>"+description+"</p></description>\n")
    374                         f.write("  <summary>"+summary+"...</summary>\n")
    375                         f.write('  <url type="homepage">'+repo+'</url>\n')
    376                         f.write("  <bundle type=\"appimage\">"+app+"</bundle>\n")
    377                         f.write("  <keywords>\n")
    378                         f.write("       <keyword>"+name+"</keyword>\n")
    379                         f.write("       <keyword>appimage</keyword>\n")
    380                         f.write("  </keywords>\n")
    381                         f.write("  <categories>\n")
    382                         f.write("       <category>AppImage</category>\n")
    383 #                       f.write("       <category>GTK</category>\n")
    384                         f.write("  </categories>\n")
    385                         f.write("<icon type=\"cached\">"+name+"_"+name+".png</icon>\n")
    386                         f.write("</component>\n")
    387                         f.write("</components>\n")
    388                         f.close()
    389         #def _write_xml_file
    390 
    391         def _get_description(self,app_name,info_url,repo_name):
    392                 desc=''
    393                 if '$(appname)' in info_url:
    394                         info_url=info_url.replace('$(appname)',app_name)
    395                 if info_url:
    396                         self._debug("Getting description from repo/app %s - %s "%(repo_name,info_url))
    397                         try:
    398                                 with urllib.request.urlopen(info_url) as f:
    399                                         if repo_name=='probono':
    400                                                 content=(f.read().decode('utf-8'))
    401                                                 soup=BeautifulSoup(content,"html.parser")
    402                                                 description_div=soup.findAll('div', attrs={ "class" : "description-text"})
    403                                 if len(description_div)>0:
    404                                         desc=description_div[0].text
    405                                         desc=desc.replace(':','.')
    406                                         desc=desc.replace('&','&amp;')
    407                         except Exception as e:
    408                                 print("Can't get description from "+info_url)
    409                                 print(str(e))
    410                                 pass
    411                 return(desc)
    412         #def _get_description
    413 
    414         def _clean_bundle_catalogue(self,applist,outdir):
    415                 xml_files_list=[]
    416                 applist=[item.lower() for item in applist]
    417                 for xml_file in os.listdir(outdir):
    418                         if xml_file.endswith('appdata.xml'):
    419                                 xml_files_list.append(xml_file.lower().replace('appdata.xml','appimage'))
    420        
    421                 if xml_files_list:
    422                         xml_discard_list=list(set(xml_files_list).difference(applist))
    423                         for discarded_file in xml_discard_list:
    424                                 os.remove(outdir+'/'+discarded_file.replace('appimage','appdata.xml'))
    425         #def _clean_bunlde_catalogue
    426 
     590                                                package_name=package_data.findAll('strong', attrs={ "class" : "pl-1"})
     591                                        package_link=package_data['href']
     592                                        if releases_page or url_source:
     593                                                package_link=releases_page+package_link
     594                                                releases.append(package_link)
     595                                                self._debug("Link: %s"%package_link)
     596                except Exception as e:
     597                        print(e)
     598                return releases
     599        #def _get_releases
     600       
  • lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/debManager.py

    r7080 r7432  
    66        def __init__(self):
    77                self.installer=''
    8                 self.dbg=False
     8                self.dbg=True
    99                self.result=[]
    1010                self.progress=0
  • lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/example.py

    r6645 r7432  
    88                self.progress=0
    99                #This dict defines wich package_type relies on what action
    10                 #actions are defined in storeManager.
     10                #actions could be defined in storeManager or per-plugin
    1111                #Non contempled actions must declare its related functions on storeManager (threads dict) and define relationships with other actions in relatedActions.
    12                 #action=example
    13                 #package='*' (in this case all package_types. It could be "deb", "zmd" or whatever package type)
     12                #package='*' (in this case action 'example' is related to all package_types. It could be "deb", "zmd" or whatever package type)
    1413                self.plugin_actions={'example':'*'}
    15                 #This switch enables cli_mode for the plugin, just in case some function difers from the gui mode
     14                #This switch enables cli_mode for the plugin, just in case some function difers from the gui mode (take a look at snapManager)
    1615                self.cli_mode=False
    1716                #This one controls if the plugin is enabled or not
     
    1918                # - storeManager having a parameter with name=package_type (simply add it to the arg list passed when invoking storeManager)
    2019                # - Internal failure controls (see zmdManager for an example)
     20                #If there'll be no parameter for enable/disable then the plugin manages it's own state and self.disabled must be None
    2121                #This example plugin is disabled by default
    2222                self.disabled=True
  • lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/infoManager.py

    r7143 r7432  
    33class infomanager:
    44        def __init__(self):
    5                 self.dbg=False
     5                self.dbg=True
    66                self.plugin_actions={'get_info':'*'}
    77                self.result={}
     
    6060                        appInfo=self._init_appInfo()
    6161#                       self._debug("Gathering package info for "+app.get_id())
    62                         appInfo['appstream_id']=app
     62#Earlier versions stored the appstream_id as the memory dir of the metadata
     63#Changes in python3.6 and pickle module forces us to disable this feature...
     64#                       appInfo['appstream_id']=app
    6365                        if app.get_id():
    6466                                appInfo['id']=app.get_id()
     
    7577                        if app.get_pkgname_default():
    7678                                appInfo['package']=app.get_pkgname_default()
     79                        if len(app.get_pkgnames())>1:
     80                                appInfo['packages']=app.get_pkgnames()
    7781                        if app.get_project_license():
    7882                                appInfo['license']=app.get_project_license()
     
    9498                                appInfo['categories']=app.get_categories()
    9599                        if app.get_icon_default():
    96                                 appInfo['icon']=app.get_icon_default().get_name()
     100                                if app.get_icon_default().get_filename():
     101                                        appInfo['icon']=app.get_icon_default().get_filename()
     102                                else:
     103                                        appInfo['icon']=app.get_icon_default().get_name()
    97104                                if appInfo['icon']==None:
    98105                                        icons=app.get_icons()
     
    103110                                        else:
    104111                                                appInfo['icon']=''
    105                                
     112                        if appInfo['icon']==None:       
     113                                appInfo['icon']=''
    106114                        if app.get_screenshots():       
    107115                                thumbnails_list=[]
     
    134142                                appInfo["screenshots"]=screenshots_list
    135143                        #The values are the values of appstream.UrlKind. 1=HOMEPAGE, 0=UNKNOWN
     144#                       self._debug(app.get_url_item(0))
    136145                        if app.get_url_item(1):
    137146                                appInfo['homepage']=app.get_url_item(1).strip()
     
    153162                                if 'embed' not in appInfo['video']:
    154163                                        appInfo['video']=appInfo['video'].replace('watch?v=','embed/')
    155                         #F***g appstream returns unknown for all the possible kinds
     164                        #This appstream version returns unknown for all the possible kinds
    156165#                       if app.get_bundle_default():
    157166#                               appInfo['bundle']=app.get_bundle_default().get_kind()
    158                         #Fix F***g appstream returns unknown for all the possible kinds
     167                        #This appstream version returns unknown for all the possible kinds
    159168                        #ID must contain bundle type as last field
    160169                        for bundle in app.get_bundles():
    161170                                if bundle.get_kind()==0:
    162171                                        kind=bundle.get_id().split('.')[-1]
    163                                         appInfo['bundle']=kind.lower()
     172                                        appInfo['bundle'].append(kind.lower())
    164173                                        if kind.lower=='sh':
    165174                                                appInfo['installerUrl']=bundle.get_id()
     
    192201                'extraInfo':'',\
    193202                'size':'',\
    194                 'bundle':'',\
     203                'bundle':[],\
    195204                'updatable':'',\
     205                'component':'',\
     206                'channel_releases':{}
    196207                }
    197208                return(appInfo)
  • lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/loadStore.py

    r7080 r7432  
    2222                self.progress=0
    2323                self.error=0
    24                 self.zmd_store_dir='/var/lib/lliurexstore/zmds'
     24#               self.zmd_store_dir='/var/lib/lliurexstore/zmds' #DEPRECATED
    2525                self.result={}
    2626                self.result['data']={}
     
    7171                                print ("Failed to load"+str(flag))
    7272                                pass
    73                 store=self.load_zmds_catalog(store)
     73                #Zomandos are now available from appstream
     74#               store=self.load_zmds_catalog(store)
    7475                store=self._sanitize_store(store)
    7576                self.store=store
     
    7778        #def load_store
    7879
    79         def load_zmds_catalog(self,store):
     80        def load_zmds_catalog(self,store): #DEPRECATED
    8081                if os.path.exists(self.zmd_store_dir):
    8182                        store=self._generic_file_load(self.zmd_store_dir,store)
     
    142143                                        self._debug("Mergin app %s as is in LliureX"%app.get_id())
    143144                                        lliurex_apps[app.get_id_filename()].subsume_full(app,appstream.AppSubsumeFlags.BOTH_WAYS)
    144                                         store.remove_app(app)
     145#                                       store.add_app(lliurex_apps[app.get_id_filename()])
    145146                        #Remove apps whitout pkgname
    146147                        if not app.get_pkgnames():
  • lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/searchManager.py

    r7143 r7432  
    77        def __init__(self):
    88                self.locale=locale.getlocale()[0]
    9                 self.dbg=False
     9                self.dbg=True
    1010                self.store=''
    1111                self.plugin_actions={'search':'*','list':'*','list_sections':'*','info':'*'}
     
    6666                        if (action=='search' or action=='info'):
    6767                                self._search_app(tokens,exact_match_for_search)
     68                else:
     69                        self._debug("Search needs a store")
    6870                self.progress=100
    6971                return(self.result)
     
    8385                        app=self._app_exists(tokens[0])
    8486                if app:
    85                         applist.append(app)
    86                         self._debug("App direct match found: "+app.get_id())
     87                        if type(app)==type([]):
     88                                applist.extend(app)
     89                        else:
     90                                applist.append(app)
     91#                       self._debug("App direct match found: "+app.get_id())
    8792                if not exact_match:
    8893                        applist.extend(self._get_apps_by_match(tokens,applist))
     
    171176        def _app_exists(self,app_name):
    172177                self._debug("Trying direct match for "+app_name)
     178                #id_matches defines how to search for an app
     179                # %s -> app_name; zero-lliurex-%s -> app_name with zero-lliurex- prefix and so on...
     180                id_matches=['%s','zero-lliurex-%s','%s.desktop']
    173181                app=None
     182                for id_string in id_matches:
     183                                #                       app=self.store.get_app_by_id_ignore_prefix(id_string%app_name)
     184                        app=self.store.get_apps_by_id(id_string%app_name)
     185                        if app:
     186                                break
     187
     188
    174189                #1.- Try exact match
    175                 app=self.store.get_app_by_id(app_name)
    176                 if not app:
    177                 #2.- Try exact match with zero-lliurex- for the zomandos
    178                         app=self.store.get_app_by_id("zero-lliurex-"+app_name)
    179                 if not app:
    180                 #3.- Try exact match with .desktop
    181                         app=self.store.get_app_by_id(app_name+".desktop")
     190#               app=self.store.get_apps_by_id(app_name)
     191#               if not app:
     192#               #2.- Try exact match with zero-lliurex- for the zomandos
     193#                       app=self.store.get_app_by_id("zero-lliurex-"+app_name)
     194#               if not app:
     195#               #3.- Try exact match with .desktop
     196#                       app=self.store.get_apps_by_id(app_name+".desktop")
    182197                if not app:
    183198                #4.- Try exact match by pkgname
    184199                        app=self.store.get_app_by_pkgname(app_name)
     200#               if not app:
     201#                       app=self.store.get_app_by_id_ignore_prefix(app_name)
    185202                self._debug("App found %s"%app)
    186203                return(app)
    187204
    188205        def _get_apps_by_match(self,tokens,applist=[]):
    189                 #Add items witch match >= self.precision
     206                #Add items with match >= self.precision
    190207                self._debug("Searching app by fuzzy match")
    191208                if not applist:
  • lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/snapManager.py

    r7143 r7432  
    1010from gi.repository import AppStreamGlib as appstream
    1111import time
     12import html
    1213#Needed for async find method, perhaps only on xenial
    1314wrap=Gio.SimpleAsyncResult()
     
    1516       
    1617        def __init__(self):
    17                 self.dbg=False
     18                self.dbg=True
    1819                self.progress=0
    1920                self.partial_progress=0
    2021                self.plugin_actions={'install':'snap','remove':'snap','pkginfo':'snap','load':'snap'}
    2122                self.cache_dir=os.getenv("HOME")+"/.cache/lliurex-store"
     23                self.cache_xmls=self.cache_dir+'/xmls/snap'
     24                self.cache_last_update=self.cache_xmls+'/.snap.lu'
    2225                self.icons_folder=self.cache_dir+"/icons"
    2326                self.images_folder=self.cache_dir+"/images"
     
    7376                        self.result['data']=self.store
    7477                else:
     78                        self._check_dirs()
    7579                        self.snap_client=Snapd.Client()
    7680                        self.snap_client.connect_sync(None)
     
    108112        #def _callback
    109113
     114        def _check_dirs(self):
     115                if not os.path.isdir(self.cache_xmls):
     116                        os.makedirs(self.cache_xmls)
     117
    110118        def _load_snap_store(self,store):
    111119                pkgs=[]
     120                #Look if cache is up-to-date
     121                if os.path.isfile(self.cache_last_update):
     122                        epoch_time=time.time()
     123                        fcache=open(self.cache_last_update,'r')
     124                        fcache_update=fcache.read()
     125                        if not fcache_update:
     126                                fcache_update=0
     127                        if int(epoch_time)-int(fcache_update)<86400:
     128                                if not os.listdir(os.path.dirname(self.cache_xmls)):
     129                                        self._debug("Loading snap from cache")
     130                                        store=self._load_from_cache(store)
     131                                        return store
     132
     133                fcache=open(self.cache_last_update,'w')
     134                fcache.write(str(int(time.time())))
    112135                if self.cli_mode:
    113136                        pkgs=self._search_snap("*")
     
    116139                self._set_status(1)
    117140                for pkg in pkgs:
    118                         store.add_app(self._generate_appstream_app(pkg))
     141                        app=self.store.get_app_by_pkgname(pkg.get_name())
     142                        if not app:
     143                                self._debug("Searching for %s"%pkg.get_name())
     144                                app=self.store.get_app_by_id(pkg.get_name().lower()+".desktop")
     145                        if app:
     146                                bundle=appstream.Bundle()
     147                                bundle.set_kind(bundle.kind_from_string('SNAP'))
     148                                bundle.set_id(pkg.get_name()+'.snap')
     149                                app.add_bundle(bundle)
     150                                app.add_category("Snap")
     151                                store.add_app(self._generate_appstream_app_from_snap(pkg))
     152                        else:
     153                                store.add_app(self._generate_appstream_app_from_snap(pkg))
    119154                return(store)
    120155
    121         def _generate_appstream_app(self,pkg):
     156        def _load_from_cache(self,store):
     157                for target_file in os.listdir(self.cache_xmls):
     158                        if target_file.endswith('.xml'):
     159                                store_file=Gio.File.new_for_path(self.cache_xmls+'/'+target_file)
     160                                self._debug("Adding file %s/%s"%(self.cache_xmls,target_file))
     161                                try:
     162                                        store.from_file(store_file,None,None)
     163                                except Exception as e:
     164                                        self._debug("Couldn't add file %s to store"%target_file)
     165                                        self._debug("Reason: %s"%e)
     166                return store   
     167
     168        def _generate_appstream_app_from_snap(self,pkg):
    122169                bundle=appstream.Bundle()
    123170                app=appstream.App()
    124171                icon=appstream.Icon()
    125172                screenshot=appstream.Screenshot()
    126                 #F*****g appstream have kinds undefined but kind_from_string works... wtf?
    127173#               bundle.set_kind(appstream.BundleKind.SNAP)
    128174                bundle.set_kind(bundle.kind_from_string('SNAP'))
    129175                bundle.set_id(pkg.get_name()+'.snap')
    130176                app.add_bundle(bundle)
    131                 app.set_name("C",pkg.get_name())
     177                app.set_name("C",pkg.get_name()+'.snap')
    132178                app.add_pkgname(pkg.get_name()+'.snap')
    133179                app.add_category("Snap")
     
    135181                release.set_version(pkg.get_version())
    136182                app.add_release(release)
    137                 sw_id=False
    138                 for snap_app in pkg.get_apps():
    139                         if snap_app.get_desktop_file():
    140                                 app.set_id("%s"%snap_app.get_desktop_file())
    141                                 sw_id=True
    142                                 break
    143                 if sw_id==False:
    144                         app.set_id("%s_%s.desktop"%(pkg.get_name(),pkg.get_name()))
    145 #               app.set_id(pkg.get_name()+'.snap')
     183                app.set_id("io.snapcraft.%s"%pkg.get_name()+'.snap')
    146184                app.set_id_kind=appstream.IdKind.DESKTOP
    147                 description=("This is an Snap bundle of app %s. It hasn't been tested by our developers and comes from a 3rd party dev team. Please use it carefully."%pkg.get_name())
    148                 app.set_description("C",description+'<br>'+pkg.get_description())
    149                 app.set_comment("C",pkg.get_summary())
     185                app.set_metadata_license("CC0-1.0")
     186                description="This is an Snap bundle. It hasn't been tested by our developers and comes from a 3rd party dev team. Please use it carefully."
     187                pkg_description=pkg.get_description()
     188                pkg_description=html.escape(pkg_description,quote=True)
     189                pkg_description=pkg_description.replace("<","&gt;")
     190                app.set_description("C","<p>%s</p><p>%s</p>"%(description,pkg_description))
     191                app.set_comment("C",pkg.get_summary().rstrip('.'))
     192
    150193                app.add_keyword("C",pkg.get_name())
    151194                for word in pkg.get_summary().split(' '):
    152                         app.add_keyword("C",word)
     195                        if len(word)>3:
     196                                app.add_keyword("C",word)
    153197
    154198                if pkg.get_icon():
     
    159203                                icon.set_kind(appstream.IconKind.REMOTE)
    160204                                icon.set_name(pkg.get_icon())
     205                                icon.set_url(pkg.get_icon())
    161206                        app.add_icon(icon)
    162207
     
    167212                        for snap_screen in pkg.get_screenshots():
    168213                                img=appstream.Image()
    169 #                               img.load_filename(self._download_file(snap_screen.get_url(),pkg.get_name(),self.images_folder))
    170214                                img.set_kind(appstream.ImageKind.SOURCE)
    171215                                img.set_url(snap_screen.get_url())
     
    173217                        screenshot.add_image(img)
    174218                        app.add_screenshot(screenshot)
     219
     220                if not os.path.isfile(self.cache_xmls+'/'+app.get_id_filename()):
     221                        xml_path='%s/%s.xml'%(self.cache_xmls,app.get_id_filename())
     222                        gioFile=Gio.File.new_for_path(xml_path)
     223                        app.to_file(gioFile)
     224                        #Fix some things in app_file...
     225                        xml_file=open(xml_path,'r')
     226                        xml_data=xml_file.readlines()
     227                        xml_file.close()
     228                        count=0
     229                        xml_data[0]=xml_data[0]+"<components>\n"
     230                        xml_data[-1]=xml_data[-1]+"\n"+"</components>"
     231                        xml_file=open(xml_path,'w')
     232                        xml_file.writelines(xml_data)
     233                        xml_file.close()
    175234                return(app)
    176235
     
    189248                while 'Snapd' not in str(type(wrap)):
    190249                        time.sleep(0.1)
     250#               snaps,curr=self.snap_client.find_finish(wrap)
    191251                snaps=self.snap_client.find_finish(wrap)
    192252                if type(snaps)!=type([]):
     
    205265                pkgs=None
    206266                try:
    207                         pkgs=self.snap_client.find_sync(Snapd.FindFlags.MATCH_NAME,tokens,None,None)
     267                                #                       pkgs,curr=self.snap_client.find_sync(Snapd.FindFlags.MATCH_NAME,tokens,None)
     268                        pkgs=self.snap_client.find_sync(Snapd.FindFlags.MATCH_NAME,tokens,None)
    208269                except Exception as e:
    209                         print(e)
     270                        print("ERR: %s"%e)
    210271                        self._set_status(1)
    211272                stable_pkgs=[]
     
    241302                                        self._debug("Unable to download %s"%url)
    242303                                        self._debug("Reason: %s"%e)
     304                                        target_file=''
    243305#                               os._exit(0)
    244306                return(target_file)
     
    252314                pkg=None
    253315                try:
    254                         pkg=self.snap_client.list_one_sync(app_info['name'])
     316                        pkg=self.snap_client.list_one_sync(app_info['package'].replace('.snap',''))
    255317                        app_info['state']='installed'
    256318                        pkgs=[pkg]
     
    258320                        app_info['state']='available'
    259321                        if self.cli_mode:
    260                                 pkgs=self._search_snap(app_info['name'])
    261                         else:
    262                                 pkgs=self._search_snap_async(app_info['name'])
     322                                pkgs=self._search_snap(app_info['package'].replace('.snap',''))
     323                        else:
     324                                pkgs=self._search_snap_async(app_info['package'].replace('.snap',''))
    263325                        self._debug("Getting extended info for %s %s"%(app_info['name'],pkgs))
    264326                if type(pkgs)==type([]):
     
    283345                else:
    284346                        try:
    285                                 self.snap_client.install_sync(app_info['name'],
     347                                self.snap_client.install_sync(app_info['name'].replace('.snap',''),
    286348                        None, # channel
    287349                        self._callback, (None,),
     
    302364                else:
    303365                        try:
    304                                 self.snap_client.remove_sync(app_info['name'],
     366                                self.snap_client.remove_sync(app_info['name'].replace('.snap',''),
    305367                       self._callback, (None,),
    306368                                                None) # cancellable
  • lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/zmdManager.py

    r7169 r7432  
    2020                if hasattr(sys,'last_value') or not (os.path.exists(self.zmd_folder)):
    2121                        #If there's an error at this point it only could be an importError caused by xmlrpc
     22                        print("ERROR!!!!")
    2223                        self.disabled=True
    2324                self.plugin_actions={'install':'zmd','pkginfo':'zmd','remove':'zmd'}
     
    6667                        except:
    6768                                self.disabled=True
     69                                print("ERROR2!!!!")
    6870                                self._set_status(10)
    6971                self.progress=100
  • lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/storeManager.py

    r7170 r7432  
    1717class StoreManager():
    1818        def __init__(self,*args,**kwargs):
    19                 self.dbg=False
    2019                if 'dbg' in kwargs.keys():
    2120                        self.dbg=kwargs['dbg']
     21                self.dbg=True
    2222                self._propagate_dbg=False
    2323                self.store=None
     24                self.stores={}
    2425                self.related_actions={
    2526                                        'load':['load'],
     
    7980                                                        continue
    8081                                                if target_class.disabled==None:
    81                                                         self._debug("Plugin %s will manage its state"%plugin_name)
    82                                                 #Time to check if plugin is disabled or enabled by parm
    83                                                 #Values for the plugins_registered dict must be the same as the parm name that enables the plugin
     82                                                        self._debug("Plugin %s will set its status"%plugin_name)
    8483                                                else:
     84                                                        #Time to check if plugin is disabled or enabled by parm
     85                                                        #Values for the plugins_registered dict must be the same as the parm name that enables the plugin
    8586                                                        for key,value in class_actions.items():
    8687                                                                val=value
     
    264265                self._debug("Joining action: %s"%action)
    265266                try:
     267                        print("T: %s"%self.running_threads[action])
    266268                        self.running_threads[action].join()
    267269                except Exception as e:
     
    394396        def _load_Store(self):
    395397                action='load'
     398                #Load appstream metada first
     399                package_type='*'
     400                load_function=self._execute_class_method(action,package_type,launchedby=None)
     401                self.store=load_function.execute_action(action=action,store=self.store)['data']
     402                #Once appstream is loaded load the appstream plugins for other package types (snap, appimage...)
    396403                for package_type in self.plugins_registered[action]:
    397                         load_function=self._execute_class_method(action,package_type,launchedby=None)
    398                         self.store=load_function.execute_action(action=action,store=self.store)['data']
     404                        if package_type!='*':
     405                                load_function=self._execute_class_method(action,package_type,launchedby=None)
     406                                self.store=load_function.execute_action(action=action,store=self.store)['data']
    399407        #def _load_Store
    400408
     
    420428        #  - Dict with the related info
    421429        ####
    422         def _get_Extended_App_Info(self,info_applist,launchedby=None,fullsearch=True):
     430        def _get_Extended_App_Info(self,info_applist,launchedby=None,fullsearch=True,channel=''):
    423431                #Check if there's any plugin for the distinct type of packages
    424432                action='pkginfo'
     
    427435                result['data']=[]
    428436                result['status']={'status':0,'msg':''}
     437                processed=[]
    429438                for app_info in info_applist:
    430                         package_type=self._check_package_type(app_info)
    431                         if package_type in types_dict:
    432                                 types_dict[package_type].append(app_info)
     439                        if channel:
     440                                types_dict[channel]=[app_info]
    433441                        else:
    434                                 types_dict[package_type]=[app_info]
     442                                available_channels=self._check_package_type(app_info)
     443                                for package_type in available_channels:
     444                                        if app_info['component']!='':
     445                                                if app_info['id'] in processed:
     446                                                        self._debug("App %s processed"%app_info['id'])
     447                                                        continue
     448
     449                                        if package_type in types_dict:
     450                                                types_dict[package_type].append(app_info)
     451                                        else:
     452                                                types_dict[package_type]=[app_info]
     453                                        processed.append(app_info['id'])
    435454                for package_type in types_dict:
    436455                        self._debug("Checking plugin for %s %s"%(action,package_type))
    437456                        if package_type in self.plugins_registered[action]:
    438                                 #Only search full info if it's required
     457                                #Only seach full info if it's required
    439458                                if (fullsearch==False and package_type=='deb'):
    440459                                        result['data'].extend(types_dict[package_type])
     
    476495        def _search_Store(self,*args,**kwargs):
    477496                search_item=args[0]
     497                return_msg=False
    478498                action='search'
    479499                if 'action' in kwargs.keys():
     
    500520                if (launchedby=='search'):
    501521                                exact_match=False
     522                target_channel=''
     523                if '=' in search_item:
     524                        target_channel=search_item.split('=')[-1]
     525                        search_item=search_item.split('=')[0]
    502526                for package_type in self.plugins_registered[action]:
     527                        self._debug("Searching package type %s"%package_type)
    503528                        search_function=self._execute_class_method(action,'*',launchedby=launchedby)
    504529                        result.update(search_function.execute_action(self.store,action,search_item,exact_match,max_results))
     
    513538                        self._debug("Add result for %s"%subordinate_action)
    514539                        self.result[subordinate_action]=result
    515                         #2.- Get rest of metadata (slower)
    516                         subordinate_action='pkginfo'
    517                         result=self._get_Extended_App_Info(result['data'],launchedby,fullsearch)
    518                         if launchedby:
    519                                 realAction=launchedby
    520                                 self._debug("Assigned results of %s to %s"%(action,realAction))
    521                         if (result['status']['status']==0) or (result['status']['status']==9):
    522                                 return_msg=True
    523                                 if fullsearch:
    524                                         result['status']['status']=0
    525                         else:
    526                                 return_msg=False
     540                        if fullsearch:
     541                                #2.- Get rest of metadata (slower)
     542                                subordinate_action='pkginfo'
     543                                self._debug("Target channel: %s"%target_channel)
     544                                result=self._get_Extended_App_Info(result['data'],launchedby,fullsearch,target_channel)
     545                                if launchedby:
     546                                        realAction=launchedby
     547                                        self._debug("Assigned results of %s to %s"%(action,realAction))
     548                                if (result['status']['status']==0) or (result['status']['status']==9):
     549                                        return_msg=True
     550                                        if fullsearch:
     551                                                result['status']['status']=0
     552                                else:
     553                                        return_msg=False
    527554                else:
    528555                        return_msg=False
     
    563590                                        types_dict={}
    564591                                        break
    565                                
    566                                 package_type=self._check_package_type(app_info)
    567                                 if package_type in types_dict:
    568                                         types_dict[package_type].append(app_info)
    569                                 else:
    570                                         types_dict[package_type]=[app_info]
     592                                processed=[]
     593                                available_channels=self._check_package_type(app_info)
     594                                for package_type in available_channels:
     595                                        if app_info['component']!='':
     596                                                if app_info['id'] in processed:
     597                                                        self._debug("App %s processed"%app_info['id'])
     598                                                        continue
     599
     600                                        if package_type in types_dict:
     601                                                types_dict[package_type].append(app_info)
     602                                        else:
     603                                                types_dict[package_type]=[app_info]
     604                                        processed.append(app_info['id'])
    571605
    572606                        for package_type in types_dict:
     
    591625                                        result=install_function.execute_action(action,types_dict[package_type])
    592626                                        self.result[action]=result
    593                                         if result['status']['status']==0:
     627                                        #Deprecated. Earlier versions stored the "app" object so here the app could get marked as installed/removed without neeed of import or query anything
     628                                        #Python>=3.6 don't let us to store the app object in a queue (needed for the GUI) so this code becames deprecated.
     629#                                       if result['status']['status']==0:
    594630                                                #Mark the apps as installed or available
    595                                                 for app in types_dict[package_type]:
    596                                                         if action=='install':
    597                                                                 app['appstream_id'].set_state(1)
    598                                                                 self._debug("App state changed to installed")
    599                                                         else:
    600                                                                 app['appstream_id'].set_state(2)
    601                                                                 self._debug("App state changed to available")
     631#                                               for app in types_dict[package_type]:
     632#                                                       if action=='install':
     633#                                                               app['appstream_id'].set_state(1)
     634#                                                               self._debug("App state changed to installed")
     635#                                                       else:
     636#                                                               app['appstream_id'].set_state(2)
     637#                                                               self._debug("App state changed to available")
    602638                                        return_msg=True
    603639                self._log("Result %s: %s"%(action,self.result[action]))
     
    616652                #Zomandos must have the subcategory "Zomando"
    617653                self._debug("Checking package type for app "+app_info['name'])
    618                 if "Zomando" in app_info['categories']:
    619                         return_msg="zmd"
    620                 else:
     654                return_msg=[]
     655                if app_info['bundle']:
     656                        return_msg.extend(app_info['bundle'])
     657                else:
     658                        if "Zomando" in app_info['categories']:
     659                                return_msg.append("zmd")
     660                        if 'component' in app_info.keys():
     661                                if app_info['component']!='':
     662                                        return_msg.append('deb')
    621663                #Standalone installers must have an installerUrl field loaded from a bundle type=script description
    622                         if app_info['bundle']!='':
    623                                 return_msg=app_info['bundle']
    624                         elif app_info['installerUrl']!='':
    625                                 return_msg="sh"
    626                         else:
    627                                 return_msg="deb"
     664                        if app_info['installerUrl']!='':
     665                                return_msg.append("sh")
    628666                return(return_msg)
    629667        #def _check_package_type
Note: See TracChangeset for help on using the changeset viewer.