source: lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/appImageManager.py @ 7120

Last change on this file since 7120 was 7120, checked in by Juanma, 2 years ago

WIP on bundles/releases

File size: 21.9 KB
Line 
1#The name of the main class must match the file name in lowercase
2import re
3import urllib
4from urllib.request import Request
5from urllib.request import urlretrieve
6import shutil
7import json
8import os
9import sys
10import threading
11import queue
12import time
13import random
14import gi
15from gi.repository import Gio
16gi.require_version('AppStreamGlib', '1.0')
17from gi.repository import AppStreamGlib as appstream
18from bs4 import BeautifulSoup
19#from subprocess import call
20
21class appimagemanager:
22        def __init__(self):
23                self.dbg=True
24                self.progress=0
25                self.partial_progress=0
26                self.plugin_actions={'install':'appimage','remove':'appimage','pkginfo':'appimage','load':'appimage'}
27                self.result={}
28                self.result['data']={}
29                self.result['status']={}
30                self.conf_dir=os.getenv("HOME")+"/.cache/lliurex-store"
31                self.icons_dir=self.conf_dir+"/icons"
32                self.bundles_dir=self.conf_dir+"/bundles"
33                self.bundle_types=['appimg']
34                self.appimage_dir=os.getenv("HOME")+"/.lliurex-store/appimg"
35                #To get the description of an app we must go to a specific url defined in url_info.
36                #$(appname) we'll be replaced with the appname so the url matches the right one.
37                #If other site has other url naming convention it'll be mandatory to define it with the appropiate replacements
38                self.repos={'appimagehub':{'type':'json','url':'https://appimage.github.io/feed.json','url_info':''}}
39                #Appimges not stored in a repo must be listed in this file, providing the download url and the info url (if there's any)
40                self.external_appimages="/usr/share/lliurex-store/files/external_appimages.json"
41                #Queue pool
42                self.queue=queue.Queue()
43                self.disabled=False
44        #def __init__
45
46        def set_debug(self,dbg=True):
47                self.dbg=dbg
48                self._debug ("Debug enabled")
49        #def set_debug
50
51        def _debug(self,msg=''):
52                if self.dbg:
53                        print ('DEBUG appimage: %s'%msg)
54        #def debug
55
56        def register(self):
57                return(self.plugin_actions)
58
59        def enable(self,state=False):
60                self.disable=state
61
62        def execute_action(self,action,applist=None,store=None):
63                if store:
64                        self.store=store
65                else:
66                        self.store=appstream.Store()
67                self.progress=0
68                self.result['status']={'status':-1,'msg':''}
69                self.result['data']=''
70                dataList=[]
71                if self.disabled:
72                        self._set_status(9)
73                        self.result['data']=self.store
74                else:
75                        self._chk_installDir()
76                        if action=='load':
77                                self.result['data']=self._load_appimage_store(self.store)
78                        else:
79                                for app_info in applist:
80                                        self.partial_progress=0
81                                        if action=='install':
82                                                dataList.append(self._install_appimage(app_info))
83                                        if action=='remove':
84                                                dataList.append(self._remove_appimage(app_info))
85                                        if action=='pkginfo':
86                                                dataList.append(self._get_info(app_info))
87                                        self.progress+=int(self.partial_progress/len(applist))
88                                self.result['data']=list(dataList)
89                self.progress=100
90                return(self.result)
91
92        def _set_status(self,status,msg=''):
93                self.result['status']={'status':status,'msg':msg}
94        #def _set_status
95
96        def _callback(self,partial_size=0,total_size=0):
97                limit=99
98                if partial_size!=0 and total_size!=0:
99                        inc=round(partial_size/total_size,2)*100
100                        self.progress=inc
101                else:
102                        inc=1
103                        margin=limit-self.progress
104                        inc=round(margin/limit,3)
105                        self.progress=(self.progress+inc)
106                if (self.progress>limit):
107                        self.progress=limit
108
109        def _chk_installDir(self):
110                msg_status=True
111                if not os.path.isdir(self.appimage_dir):
112                        try:
113                                os.makedirs(self.appimage_dir)
114                        except:
115                                msg_status=False
116                return msg_status                               
117
118        def _install_appimage(self,app_info):
119                app_info=self._get_info(app_info)
120                self._debug("Installing %s"%app_info)
121                if app_info['state']=='installed':
122                        self._set_status(4)
123                else:
124                                #                       appimage_url=self.repository_url+'/'+app_info['package']
125                        appimage_url=app_info['homepage']+'/'+app_info['package']
126                        self._debug("Downloading "+appimage_url)
127                        dest_path=self.appimage_dir+'/'+app_info['package']
128                        if appimage_url:
129                                try:
130                                        req=Request(appimage_url, headers={'User-Agent':'Mozilla/5.0'})
131                                        with urllib.request.urlopen(req) as response, open(dest_path, 'wb') as out_file:
132                                                bf=16*1024
133                                                acumbf=0
134#                                               print("Response: %s"%response.info())
135                                                app_size=int(response.info()['Content-Length'])
136#                                               print("APP SIZE: %s"%app_size)
137                                                while True:
138                                                        if acumbf>=app_size:
139                                                            break
140                                                        shutil.copyfileobj(response, out_file,bf)
141                                                        acumbf=acumbf+bf
142                                                        self._callback(acumbf,app_size)
143                                        st = os.stat(dest_path)
144                                        os.chmod(dest_path, st.st_mode | 0o111)
145                                        self._set_status(0)
146                                except Exception as e:
147                                        print(e)
148                                        self._set_status(5)
149                        else:
150                                self._set_status(12)
151                return app_info
152        #def _install_appimage
153
154        def _remove_appimage(self,app_info):
155                self._debug("Removing "+app_info['package'])
156                if os.path.isfile(self.appimage_dir+'/'+app_info['package']):
157                        try:
158                                call([self.appimage_dir+"/"+app_info['package'], "--remove-appimage-desktop-integration"])
159                        except:
160                                pass
161                        try:
162                                os.remove(self.appimage_dir+"/"+app_info['package'])
163                                self._set_status(0)
164                        except:
165                                self._set_status(6)
166                return(app_info)
167        #def _remove_appimage
168
169        def _get_info(self,app_info):
170                app_info['state']='available'
171                if os.path.isfile(self.appimage_dir+'/'+app_info['package']):
172                        app_info['state']='installed'
173                #Get size
174                appimage_url=app_info['homepage']+'/'+app_info['package']
175                dest_path=self.appimage_dir+'/'+app_info['package']
176                if appimage_url:
177                        try:
178                                with urllib.request.urlopen(appimage_url) as response:
179                                        app_info['size']=(response.info()['Content-Length'])
180                        except:
181                                app_info['size']=0
182                self._set_status(0)
183                self.partial_progress=100
184                return(app_info)
185        #def _get_info
186
187        def _load_appimage_store(self,store):
188                self._get_bundles_catalogue()
189                if os.path.exists(self.bundles_dir):
190                        for bundle_type in self.bundle_types:
191                                self._debug("Loading %s catalog"%bundle_type)
192                                store=self._generic_file_load(self.bundles_dir+'/'+bundle_type,store)
193                return(store)
194        #def load_bundles_catalog(self)
195       
196        def _generic_file_load(self,target_path,store):
197                icon_path='/usr/share/icons/hicolor/128x128'
198                if not os.path.isdir(target_path):
199                        os.makedirs(target_path)
200                files=os.listdir(target_path)
201                for target_file in os.listdir(target_path):
202                        if target_file.endswith('appdata.xml'):
203                                store_path=Gio.File.new_for_path(target_path+'/'+target_file)
204                                self._debug("Adding file "+target_path+'/'+target_file)
205                                try:
206                                        store.from_file(store_path,icon_path,None)
207                                except Exception as e:
208                                        self._debug("Couldn't add file "+target_file+" to store")
209                                        self._debug("Reason: "+str(e))
210                return(store)
211        #def _generic_file_load
212
213        def _get_bundles_catalogue(self):
214                applist=[]
215                appdict={}
216                all_apps=[]
217                outdir=self.bundles_dir+'/appimg/'
218                #Load repos
219                for repo_name,repo_info in self.repos.items():
220                        if not os.path.isdir(self.bundles_dir):
221                                try:
222                                        os.makedirs(self.bundles_dir)
223                                except:
224                                        self._debug("appImage catalogue could not be fetched: Permission denied")
225                        self._debug("Fetching repo %s"%repo_info['url'])
226                        if repo_info['type']=='json':
227                                applist=self._process_appimage_json(self._fetch_repo(repo_info['url']),repo_name)
228
229                        self._debug("Fetched repo "+repo_info['url'])
230                        self._th_generate_xml_catalog(applist,outdir,repo_info['url_info'],repo_info['url'],repo_name)
231                        all_apps.extend(applist)
232                #Load external apps
233                for app_name,app_info in self._get_external_appimages().items():
234                        if os.path.isdir(self.bundles_dir):
235                                appinfo=self._init_appinfo()
236                                appinfo['name']=app_info['url'].split('/')[-1]
237                                appinfo['package']=app_info['url'].split('/')[-1]
238                                appinfo['homepage']='/'.join(app_info['url'].split('/')[0:-1])
239                                self._debug("Fetching external appimage %s"%app_info['url'])
240                                appinfo['bundle']='appimage'
241                                applist=[appinfo]
242                                self._th_generate_xml_catalog(applist,outdir,app_info['url_info'],app_info['url'],app_name)
243                                self._debug("Fetched appimage "+app_info['url'])
244                                all_apps.extend(applist)
245                        else:
246                                self._debug("External appImage could not be fetched: Permission denied")
247                self._debug("Removing old entries...")
248#               self._clean_bundle_catalogue(all_apps,outdir)
249                return(True)
250        #def _get_bundles_catalogue
251       
252        def _fetch_repo(self,repo):
253                req=Request(repo, headers={'User-Agent':'Mozilla/5.0'})
254                with urllib.request.urlopen(req) as f:
255                        content=(f.read().decode('utf-8'))
256               
257                return(content)
258        #def _fetch_repo
259       
260        def _get_external_appimages(self):
261                external_appimages={}
262                if os.path.isfile(self.external_appimages):
263                        try:
264                                with open(self.external_appimages) as appimages:
265                                        external_appimages=json.load(appimages)
266                        except:
267                                self._debug("Can't load %s"%self.external_appimages)
268                self._debug(external_appimages)
269                return external_appimages
270        #def _get_external_appimages
271       
272        def _process_appimage_json(self,data,repo_name):
273                maxconnections = 10
274                semaphore = threading.BoundedSemaphore(value=maxconnections)
275                applist=[]
276                json_data=json.loads(data)
277                if 'items' in json_data.keys():
278                        for appimage in json_data['items']:
279                                appinfo=self._th_process_appimage(appimage,semaphore)
280                                if appinfo:
281                                        applist.append(appinfo)
282                                        #                               th=threading.Thread(target=self._th_process_appimage, args = (appimage,semaphore))
283#                               th.start()
284
285#               while threading.active_count()>1:
286#                       print("%s"%threading.active_count())
287#                       time.sleep(0.1)
288
289#               while not self.queue.empty():
290#                       applist.append(self.queue.get())
291#                       self._debug("Added %s"%applist[-1])
292                self._debug("JSON: %s"%applist)
293                return (applist)
294        #_process_appimage_json
295
296        def _th_process_appimage(self,appimage,semaphore):
297                appinfo=None
298#               semaphore.acquire()
299#               lock=threading.Lock()
300                releases=[]
301                if 'links' in appimage.keys():
302                        if appimage['links']:
303                                appinfo=self.load_json_appinfo(appimage)
304#Deprecated. appImage releases will be load on the info stage
305#                       releases=self._get_releases_from_json(appimage)
306#                       if releases:
307#                               appinfo['releases']=releases
308#                               for release in releases:
309#                                       #Release has the direct download url
310#                                       tmp_release=release.split('/')
311#                                       tmp_appinfo=appinfo.copy()
312#                                       rel_number=tmp_release[-2]
313#                                       rel_name=tmp_release[-1].lower().replace('.appimage','')
314#                                       self._debug("Release: %s"%release)
315#                                       tmp_appinfo['name']=rel_name
316#                                       tmp_appinfo['package']=tmp_release[-1]
317#                                       tmp_appinfo['homepage']='/'.join(tmp_release[0:-1])
318#                                       self.queue.put(tmp_appinfo)
319#Threading disabled
320#                               self.queue.put(appinfo)
321                return(appinfo)
322        #def _th_process_appimage
323
324        def load_json_appinfo(self,appimage):
325                appinfo=self._init_appinfo()
326                appinfo['name']=appimage['name']
327                appinfo['package']=appimage['name']
328                if 'license' in appimage.keys():
329                        appinfo['license']=appimage['license']
330                appinfo['summary']=''
331                if 'description' in appimage.keys():
332                        appinfo['description']=appimage['description']
333                if 'categories' in appimage.keys():
334                        appinfo['categories']=appimage['categories']
335                if 'icon' in appimage.keys():
336                        appinfo['icon']=appimage['icon']
337                if 'screenshots' in appimage.keys():
338                        appinfo['thumbnails']=appimage['screenshots']
339                if 'links' in appimage.keys():
340                        if appimage['links']:
341                                for link in appimage['links']:
342                                        if 'url' in link.keys() and link['type']=='Download':
343                                                appinfo['homepage']=link['url']
344                elif 'authors' in appimage.keys():
345                        if appimage['authors']:
346                                for author in appimage['authors']:
347                                        if 'url' in author.keys():
348                                                appinfo['homepage']=author['url']
349                appinfo['bundle']='appimage'
350                return appinfo
351        #def load_json_appinfo
352
353        def _get_releases_from_json(self,appimage):
354                releases=[]
355                if appimage['links']:
356                        for link in appimage['links']:
357                                if 'type' in link.keys():
358                                        if link['type']=='Download':
359                                                self._debug("Info url: %s"%link['url'])
360                                                try:
361                                                        sw_git=False
362                                                        with urllib.request.urlopen(link['url']) as f:
363                                                                if 'github' in link['url']:
364                                                                        sw_git=True
365                                                                content=(f.read().decode('utf-8'))
366                                                                soup=BeautifulSoup(content,"html.parser")
367                                                                package_a=soup.findAll('a', attrs={ "href" : re.compile(r'.*[aA]pp[iI]mage$')})
368                                                                for package_data in package_a:
369                                                                        package_name=package_data.findAll('strong', attrs={ "class" : "pl-1"})
370                                                                        package_link=package_data['href']
371                                                                        if sw_git:
372                                                                                package_link="https://github.com"+package_link
373                                                                                releases.append(package_link)
374                                                                                self._debug("Link: %s"%package_link)
375                                                except Exception as e:
376                                                        print(e)
377                return releases
378        #def _get_releases_from_json
379
380        def _th_generate_xml_catalog(self,applist,outdir,info_url,repo,repo_name):
381                maxconnections = 10
382                semaphore = threading.BoundedSemaphore(value=maxconnections)
383                random_applist = list(applist)
384                random.shuffle(random_applist)
385                for app in applist:
386                        th=threading.Thread(target=self._th_write_xml, args = (app,outdir,info_url,repo,repo_name,semaphore))
387                        th.start()
388        #def _th_generate_xml_catalog
389
390        def _th_write_xml(self,appinfo,outdir,info_url,repo,repo_name,semaphore):
391                semaphore.acquire()
392                lock=threading.Lock()
393                self._debug("Populating %s"%appinfo)
394                package=appinfo['name'].lower().replace(".appimage","")
395                if len(package)>40:
396                        tmp_package=package.split('-')
397                        tam=0
398                        pos=1
399                        index=0
400                        banned=['linux32','linux64','i386','x86_64','ia32','amd64']
401                        for tmp_name in tmp_package:
402                                if (tam<len(tmp_name) and pos<index) and tmp_name not in banned:
403                                        tam=len(tmp_name)
404                                        pos=index
405                                index+=1
406                        print("Removed: %s"%tmp_package[pos])
407                        tmp_package[pos]=''
408                        package='-'.join(tmp_package)
409                        package=package.replace("--","-")
410                        package=package.replace("-.",".")
411
412#               filename=outdir+package.lower().replace('appimage',"appdata")+".xml"
413#               self._debug("checking if we need to download "+filename)
414#               if not os.path.isfile(filename):
415                repo_info={'info_url':info_url,'repo':repo,repo_name:'repo_name'}
416                self._write_xml_file(appinfo,repo_info,lock)
417                semaphore.release()
418        #def _th_write_xml
419
420        def _write_xml_file(self,appinfo,repo_info,lock):
421                #Search in local store for the app
422                app=self.store.get_app_by_pkgname(appinfo['package'].lower())
423                sw_new=False
424                if not app:
425                        app=appstream.App()
426                        sw_new=True
427                bundle=appstream.Bundle()
428                icon=appstream.Icon()
429                screenshot=appstream.Screenshot()
430                #F*****g appstream have kinds undefined but kind_from_string works... wtf?
431#               bundle.set_kind(appstream.BundleKind.SNAP)
432                bundle.set_kind(bundle.kind_from_string('APPIMAGE'))
433                bundle.set_id(appinfo['package']+'.appimage')
434                app.add_bundle(bundle)
435                app.add_category("AppImage")
436                if sw_new:
437                        app.set_name("C",appinfo['name'])
438#               app.add_pkgname(pkg.get_name()+'.snap')
439                        app.add_pkgname(appinfo['package'])
440#               release=appstream.Release()
441#               release.set_version(pkg.get_version())
442#               app.add_release(release)
443                        app.set_id("appimagehub.%s"%appinfo['name']+'.appimage')
444#               app.set_id(pkg.get_name()+'.snap')
445                        app.set_id_kind=appstream.IdKind.DESKTOP
446                        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'])
447                        summary=' '.join(list(description.split(' ')[:8]))
448                        if len(description.split(' '))>8:
449                                summary+="... "
450                        app.set_description("C",description)
451                        app.set_comment("C",summary)
452                        self.store.add_app(app)
453
454#               app.add_keyword("C",pkg.get_name())
455#               for word in pkg.get_summary().split(' '):
456#                       app.add_keyword("C",word)
457
458#               if pkg.get_icon():
459#                       if self.icon_cache_enabled:
460#                               icon.set_kind(appstream.IconKind.LOCAL)
461#                               icon.set_name(self._download_file(pkg.get_icon(),pkg.get_name(),self.icons_folder))
462#                       else:
463#                               icon.set_kind(appstream.IconKind.REMOTE)
464#                               icon.set_name(pkg.get_icon())
465#                       app.add_icon(icon)
466
467#               if pkg.get_license():
468#                       app.set_project_license(pkg.get_license())
469
470#               if pkg.get_screenshots():
471#                       for snap_screen in pkg.get_screenshots():
472#                               img=appstream.Image()
473##                              img.load_filename(self._download_file(snap_screen.get_url(),pkg.get_name(),self.images_folder))
474#                               img.set_kind(appstream.ImageKind.SOURCE)
475#                               img.set_url(snap_screen.get_url())
476#                               break
477#                       screenshot.add_image(img)
478#                       app.add_screenshot(screenshot)
479                return(app)
480#                       name=appinfo['name'].lower().replace(".appimage","")
481#                       self._debug("Generating %s xml"%appinfo['package'])
482#                       f=open(filename,'w')
483#                       f.write('<?xml version="1.0" encoding="UTF-8"?>'+"\n")
484#                       f.write("<components version=\"0.10\">\n")
485#                       f.write("<component  type=\"desktop-application\">\n")
486#                       f.write("  <id>%s</id>\n"%appinfo['package'].lower())
487#                       f.write("  <pkgname>%s</pkgname>\n"%appinfo['package'])
488#                       f.write("  <name>%s</name>\n"%name)
489#                       f.write("  <metadata_license>CC0-1.0</metadata_license>\n")
490#                       f.write("  <provides><binary>%s</binary></provides>\n"%appinfo['package'])
491#                       if 'releases' in appinfo.keys():
492#                               f.write("  <releases>\n")
493#                               for release in appinfo['releases']:
494#                                       tmp_release=release.split('/')
495#                                       rel_number='/'.join(tmp_release[-2:])
496#                                       f.write("    <release version=\"%s\" urgency=\"medium\">"%rel_number)
497#                                       f.write("</release>\n")
498#                               f.write("  </releases>\n")
499#                       f.write("  <launchable type=\"desktop-id\">%s.desktop</launchable>\n"%name)
500#                       if appinfo['description']=='':
501#                               with lock:
502#                                       try:
503#                                               if appinfo['name'] in self.descriptions_dict.keys():
504#                                                       (description,icon)=self.descriptions_dict[appinfo['name']]
505#                                               else:
506#                                                       (description,icon)=self._get_description_icon(appinfo['name'],repo_info)
507#                                                       self.descriptions_dict.update({appinfo['name']:[description,icon]})
508#                                       except:
509#                                               description=''
510#                                               icon=''
511#                       else:
512#                               description=appinfo['description']
513#                       summary=' '.join(list(description.split(' ')[:8]))
514#                       if len(description.split(' '))>8:
515#                               summary+="... "
516#                       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"%(name,description)
517#                       if summary=='':
518#                               summary=' '.join(list(description.split(' ')[:8]))
519#                       f.write("  <description><p></p><p>%s</p></description>\n"%description)
520#                       f.write("  <summary>%s</summary>\n"%summary)
521##                      f.write("  <icon type=\"local\">%s</icon>\n"%appinfo['icon'])
522#                       f.write("<icon type=\"cached\">"+name+"_"+name+".png</icon>\n")
523#                       f.write("  <url type=\"homepage\">%s</url>\n"%appinfo['homepage'])
524#                       f.write("  <bundle type=\"appimage\">%s</bundle>\n"%appinfo['name'])
525#                       f.write("  <keywords>\n")
526#                       keywords=name.split("-")
527#                       banned_keywords=["linux","x86_64","i386","ia32","amd64"]
528#                       for keyword in keywords:
529#                               #Better than isalpha method for this purpose
530#                               if keyword.isidentifier() and keyword not in banned_keywords:
531#                                       f.write("       <keyword>%s</keyword>\n"%keyword)
532#                       f.write("       <keyword>appimage</keyword>\n")
533#                       f.write("  </keywords>\n")
534#                       f.write("  <categories>\n")
535#                       f.write("       <category>AppImage</category>\n")
536#                       if 'categories' in appinfo.keys():
537#                               for category in appinfo['categories']:
538#                                       f.write("       <category>%s</category>\n"%category)
539#                       f.write("  </categories>\n")
540#                       f.write("</component>\n")
541#                       f.write("</components>\n")
542#                       f.close()
543        #def _write_xml_file
544
545        def _get_description_icon(self,app_name,info_url,repo_name):
546                desc=''
547                icon=''
548                if info_url:
549                        if '$(appname)' in info_url:
550                                info_url=info_url.replace('$(appname)',app_name)
551                        self._debug("Getting description from repo/app %s - %s "%(repo_name,info_url))
552                        try:
553                                with urllib.request.urlopen(info_url) as f:
554                                        if repo_name=='probono':
555                                                content=(f.read().decode('utf-8'))
556                                                soup=BeautifulSoup(content,"html.parser")
557                                                description_div=soup.findAll('div', attrs={ "class" : "description-text"})
558                                                icon_div=soup.findAll('div', attrs={ "class" : "avatar-icon avatar-large description-icon "})
559                                if len(description_div)>0:
560                                        desc=description_div[0].text
561                                        desc=desc.replace(':','.')
562                                        desc=desc.replace('&','&amp;')
563                                if len(icon_div)>0:
564                                        icon_str=str(icon_div[0])
565                                        icon=icon_str.split(' ')[9]
566                                        icon=icon.lstrip('url(')
567                                        if icon.startswith('http'):
568                                                icon=icon.rstrip(');"></div>')
569                                                icon=self._download_file(icon,app_name)
570                                        print("Icon: %s"%icon)
571                        except Exception as e:
572                                print("Can't get description from "+info_url)
573                                print(str(e))
574                                pass
575                return([desc,icon])
576        #def _get_description
577
578        def _clean_bundle_catalogue(self,applist,outdir):
579                xml_files_list=[]
580                applist=[item.lower() for item in applist]
581                for xml_file in os.listdir(outdir):
582                        if xml_file.endswith('appdata.xml'):
583                                xml_files_list.append(xml_file.lower().replace('appdata.xml','appimage'))
584       
585                if xml_files_list:
586                        xml_discard_list=list(set(xml_files_list).difference(applist))
587                        for discarded_file in xml_discard_list:
588                                os.remove(outdir+'/'+discarded_file.replace('appimage','appdata.xml'))
589        #def _clean_bunlde_catalogue
590
591        def _download_file(self,url,app_name):
592#               target_file=self.icons_folder+'/'+app_name+".png"
593                target_file=self.icons_dir+'/'+app_name+".png"
594                if not os.path.isfile(target_file):
595#                       shutil.copy("/usr/share/icons/hicolor/128x128/apps/lliurex-store.png",target_file)
596#                       if not os.fork():
597                        if not os.path.isfile(target_file):
598                                self._debug("Downloading %s to %s"%(url,target_file))
599                                try:
600                                        with urllib.request.urlopen(url) as response, open(target_file, 'wb') as out_file:
601                                                bf=16*1024
602                                                acumbf=0
603                                                file_size=int(response.info()['Content-Length'])
604                                                while True:
605                                                        if acumbf>=file_size:
606                                                            break
607                                                        shutil.copyfileobj(response, out_file,bf)
608                                                        acumbf=acumbf+bf
609                                        st = os.stat(target_file)
610                                except Exception as e:
611                                        self._debug("Unable to download %s"%url)
612                                        self._debug("Reason: %s"%e)
613                                        target_file=url
614#                               os._exit(0)
615                return(target_file)
616        #def _download_file
617       
618        def _chk_bundle_dir(self,outdir):
619                msg_status=True
620                if not os.path.isdir(outdir):
621                        try:
622                                os.makedirs(outdir)
623                        except Exception as e:
624                                msg_status=False
625                                print(e)
626                return(os.access(outdir,os.W_OK|os.R_OK|os.X_OK|os.F_OK))
627        #def _chk_bundle_dir
628       
629        def _init_appinfo(self):
630                appInfo={'appstream_id':'',\
631                'id':'',\
632                'name':'',\
633                'version':'',\
634                'releases':[],\
635                'package':'',\
636                'license':'',\
637                'summary':'',\
638                'description':'',\
639                'categories':[],\
640                'icon':'',\
641                'screenshot':'',\
642                'thumbnails':[],\
643                'video':'',\
644                'homepage':'',\
645                'installerUrl':'',\
646                'state':'',\
647                'depends':'',\
648                'kudos':'',\
649                'suggests':'',\
650                'extraInfo':'',\
651                'size':'',\
652                'bundle':'',\
653                'updatable':'',\
654                }
655                return(appInfo)
656        #def _init_appinfo
Note: See TracBrowser for help on using the repository browser.