- Timestamp:
- Apr 18, 2018, 2:28:43 PM (3 years ago)
- Location:
- lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/appImageManager.py
r7139 r7143 1 1 #The name of the main class must match the file name in lowercase 2 import re3 2 import urllib 4 3 from urllib.request import Request … … 7 6 import json 8 7 import os 8 from subprocess import call 9 9 import sys 10 10 import threading 11 import queue 11 from bs4 import BeautifulSoup 12 import random 12 13 import time 13 import random14 14 import gi 15 15 from gi.repository import Gio 16 16 gi.require_version('AppStreamGlib', '1.0') 17 17 from gi.repository import AppStreamGlib as appstream 18 from bs4 import BeautifulSoup19 #from subprocess import call20 18 21 19 class appimagemanager: 22 20 def __init__(self): 23 self.dbg= True21 self.dbg=False 24 22 self.progress=0 25 23 self.partial_progress=0 … … 28 26 self.result['data']={} 29 27 self.result['status']={} 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+"/bundles/appimage" 28 self.conf_dir=os.getenv("HOME")+"/.cache/lliurex-store" 29 self.bundles_dir=self.conf_dir+"/bundles" 33 30 self.bundle_types=['appimg'] 34 self.appimage_dir=os.getenv("HOME")+"/.l liurex-store/appimg"31 self.appimage_dir=os.getenv("HOME")+"/.local/bin/" 35 32 #To get the description of an app we must go to a specific url defined in url_info. 36 33 #$(appname) we'll be replaced with the appname so the url matches the right one. 37 34 #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)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) 40 37 self.external_appimages="/usr/share/lliurex-store/files/external_appimages.json" 41 #Queue pool42 self.queue=queue.Queue()43 38 self.disabled=False 39 self.count=0 44 40 #def __init__ 45 41 … … 65 61 else: 66 62 self.store=appstream.Store() 67 self.appimage_store=appstream.Store()68 63 self.progress=0 69 64 self.result['status']={'status':-1,'msg':''} … … 76 71 self._chk_installDir() 77 72 if action=='load': 78 self.result['data']=self._load_appimage_store( )73 self.result['data']=self._load_appimage_store(self.store) 79 74 else: 80 75 for app_info in applist: … … 168 163 #def _remove_appimage 169 164 170 def _load_appimage_store(self,store=None): 171 self._get_bundles_catalogue() 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() 172 185 if os.path.exists(self.bundles_dir): 173 186 for bundle_type in self.bundle_types: … … 194 207 #def _generic_file_load 195 208 196 def _get_bundles_catalogue(self): 209 def _download_bundles_catalogue(self): 210 CURSOR_UP='\033[F' 211 ERASE_LINE='\033[K' 212 content='' 197 213 applist=[] 198 appdict={} 214 progress_bar="#" 215 self.descriptions_dict={} 199 216 all_apps=[] 200 217 outdir=self.bundles_dir+'/appimg/' 201 218 #Load repos 202 219 for repo_name,repo_info in self.repos.items(): 203 if not os.path.isdir(self.bundles_dir): 204 try: 205 os.makedirs(self.bundles_dir) 206 except: 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: 207 233 self._debug("appImage catalogue could not be fetched: Permission denied") 208 self._debug("Fetching repo %s"%repo_info['url'])209 if repo_info['type']=='json':210 applist=self._process_appimage_json(self._fetch_repo(repo_info['url']),repo_name)211 212 self._debug("Fetched repo "+repo_info['url'])213 self._th_generate_xml_catalog(applist,outdir,repo_info['url_info'],repo_info['url'],repo_name)214 all_apps.extend(applist)215 234 #Load external apps 216 235 for app_name,app_info in self._get_external_appimages().items(): 217 if os.path.isdir(self.bundles_dir): 218 appinfo=self._init_appinfo() 219 appinfo['name']=app_info['url'].split('/')[-1] 220 appinfo['package']=app_info['url'].split('/')[-1] 221 appinfo['homepage']='/'.join(app_info['url'].split('/')[0:-1]) 236 if self._chk_bundle_dir(outdir): 237 appimage=app_info['url'].split('/')[-1] 238 appimage_url='/'.join(app_info['url'].split('/')[0:-1]) 222 239 self._debug("Fetching external appimage %s"%app_info['url']) 223 app info['bundle']='appimage'224 applist=[appinfo]225 self._th_generate_xml_catalog(applist,outdir,app_info['url_info'],app _info['url'],app_name)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) 226 243 self._debug("Fetched appimage "+app_info['url']) 227 244 all_apps.extend(applist) 228 245 else: 229 246 self._debug("External appImage could not be fetched: Permission denied") 230 self._debug("Removing old entries...") 231 # self._clean_bundle_catalogue(all_apps,outdir) 247 248 249 ## print (("Removing old entries...")) 250 self._clean_bundle_catalogue(all_apps,outdir) 232 251 return(True) 233 #def _get_bundles_catalogue 234 252 #def _download_bundles_catalogue 253 254 def _get_external_appimages(self): 255 external_appimages={} 256 if os.path.isfile(self.external_appimages): 257 try: 258 with open(self.external_appimages) as appimages: 259 external_appimages=json.load(appimages) 260 except: 261 self._debug("Can't load %s"%self.external_appimages) 262 self._debug(external_appimages) 263 return external_appimages 264 265 def _chk_bundle_dir(self,outdir): 266 msg_status=True 267 if not os.path.isdir(outdir): 268 try: 269 os.makedirs(outdir) 270 except Exception as e: 271 msg_status=False 272 print(e) 273 return(os.access(outdir,os.W_OK|os.R_OK|os.X_OK|os.F_OK)) 274 #def _chk_bundle_dir 275 235 276 def _fetch_repo(self,repo): 236 277 req=Request(repo, headers={'User-Agent':'Mozilla/5.0'}) … … 240 281 return(content) 241 282 #def _fetch_repo 242 243 def _get_external_appimages(self): 244 external_appimages={} 245 if os.path.isfile(self.external_appimages): 246 try: 247 with open(self.external_appimages) as appimages: 248 external_appimages=json.load(appimages) 249 except: 250 self._debug("Can't load %s"%self.external_appimages) 251 self._debug(external_appimages) 252 return external_appimages 253 #def _get_external_appimages 254 255 def _process_appimage_json(self,data,repo_name): 256 maxconnections = 10 257 semaphore = threading.BoundedSemaphore(value=maxconnections) 283 284 def _generate_applist(self,content,repo_name): 285 garbage_list=[] 258 286 applist=[] 259 json_data=json.loads(data) 260 if 'items' in json_data.keys(): 261 for appimage in json_data['items']: 262 appinfo=self._th_process_appimage(appimage,semaphore) 263 if appinfo: 264 applist.append(appinfo) 265 # th=threading.Thread(target=self._th_process_appimage, args = (appimage,semaphore)) 266 # th.start() 267 268 # while threading.active_count()>1: 269 # print("%s"%threading.active_count()) 270 # time.sleep(0.1) 271 272 # while not self.queue.empty(): 273 # applist.append(self.queue.get()) 274 # self._debug("Added %s"%applist[-1]) 275 # self._debug("JSON: %s"%applist) 276 return (applist) 277 #_process_appimage_json 278 279 def _th_process_appimage(self,appimage,semaphore): 280 appinfo=None 281 # semaphore.acquire() 282 # lock=threading.Lock() 283 releases=[] 284 if 'links' in appimage.keys(): 285 if appimage['links']: 286 appinfo=self.load_json_appinfo(appimage) 287 #Deprecated. appImage releases will be load on the info stage 288 # releases=self._get_releases_from_json(appimage) 289 # if releases: 290 # appinfo['releases']=releases 291 # for release in releases: 292 # #Release has the direct download url 293 # tmp_release=release.split('/') 294 # tmp_appinfo=appinfo.copy() 295 # rel_number=tmp_release[-2] 296 # rel_name=tmp_release[-1].lower().replace('.appimage','') 297 # self._debug("Release: %s"%release) 298 # tmp_appinfo['name']=rel_name 299 # tmp_appinfo['package']=tmp_release[-1] 300 # tmp_appinfo['homepage']='/'.join(tmp_release[0:-1]) 301 # self.queue.put(tmp_appinfo) 302 #Threading disabled 303 # self.queue.put(appinfo) 304 return(appinfo) 305 #def _th_process_appimage 306 307 def load_json_appinfo(self,appimage): 308 appinfo=self._init_appinfo() 309 appinfo['name']=appimage['name'] 310 appinfo['package']=appimage['name'] 311 if 'license' in appimage.keys(): 312 appinfo['license']=appimage['license'] 313 appinfo['summary']='' 314 if 'description' in appimage.keys(): 315 appinfo['description']=appimage['description'] 316 if 'categories' in appimage.keys(): 317 appinfo['categories']=appimage['categories'] 318 if 'icon' in appimage.keys(): 319 appinfo['icon']=appimage['icon'] 320 if 'screenshots' in appimage.keys(): 321 appinfo['thumbnails']=appimage['screenshots'] 322 if 'links' in appimage.keys(): 323 if appimage['links']: 324 for link in appimage['links']: 325 if 'url' in link.keys() and link['type']=='Download': 326 appinfo['homepage']=link['url'] 327 elif 'authors' in appimage.keys(): 328 if appimage['authors']: 329 for author in appimage['authors']: 330 if 'url' in author.keys(): 331 appinfo['homepage']=author['url'] 332 appinfo['bundle']=['appimage'] 333 return appinfo 334 #def load_json_appinfo 335 336 def _th_generate_xml_catalog(self,applist,outdir,info_url,repo,repo_name): 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' 337 310 maxconnections = 10 338 311 semaphore = threading.BoundedSemaphore(value=maxconnections) 339 312 random_applist = list(applist) 340 313 random.shuffle(random_applist) 341 for app in applist: 342 th=threading.Thread(target=self._th_write_xml, args = (app,outdir,info_url,repo,repo_name,semaphore)) 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)) 343 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') 344 327 #def _th_generate_xml_catalog 345 328 346 def _th_write_xml(self,app info,outdir,info_url,repo,repo_name,semaphore):329 def _th_write_xml(self,app,outdir,info_url,repo,repo_name,semaphore,inc): 347 330 semaphore.acquire() 348 331 lock=threading.Lock() 349 # self._debug("Populating %s"%appinfo) 350 package=appinfo['name'].lower().replace(".appimage","") 351 if len(package)>40: 352 tmp_package=package.split('-') 353 tam=0 354 pos=1 355 index=0 356 banned=['linux32','linux64','i386','x86_64','ia32','amd64'] 357 for tmp_name in tmp_package: 358 if (tam<len(tmp_name) and pos<index) and tmp_name not in banned: 359 tam=len(tmp_name) 360 pos=index 361 index+=1 362 print("Removed: %s"%tmp_package[pos]) 363 tmp_package[pos]='' 364 package='-'.join(tmp_package) 365 package=package.replace("--","-") 366 package=package.replace("-.",".") 367 368 # filename=outdir+package.lower().replace('appimage',"appdata")+".xml" 369 # self._debug("checking if we need to download "+filename) 370 # if not os.path.isfile(filename): 371 repo_info={'info_url':info_url,'repo':repo,repo_name:'repo_name'} 372 self._add_appimage(appinfo,repo_info,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 373 342 semaphore.release() 374 343 #def _th_write_xml 375 344 376 def _add_appimage(self,appinfo,repo_info,lock): 377 #Search in local store for the app 378 sw_new=False 379 app=self.store.get_app_by_pkgname(appinfo['package'].lower()) 380 if not app: 381 self._debug("Searching for %s"%appinfo['package']) 382 app=self.store.get_app_by_id(appinfo['package'].lower()+".desktop") 383 if not app: 384 self._debug("Generating new %s"%appinfo['package']) 385 app=appstream.App() 386 sw_new=True 387 bundle=appstream.Bundle() 388 icon=appstream.Icon() 389 screenshot=appstream.Screenshot() 390 bundle.set_kind(bundle.kind_from_string('APPIMAGE')) 391 bundle.set_id(appinfo['package']+'.appimage') 392 app.add_bundle(bundle) 393 app.add_keyword("C","appimage") 394 app.add_category("appimage") 395 app.add_pkgname(appinfo['package'].lower()+".appimage") 396 app.add_url(appstream.UrlKind.UNKNOWN,appinfo['homepage']) 397 if sw_new: 398 app.add_keyword("C",appinfo['package']) 399 app.set_name("C",appinfo['name']) 400 app.add_pkgname(appinfo['package'].lower()+".appimage") 401 app.set_id("appimagehub.%s"%appinfo['name'].lower()+'.appimage') 402 app.set_id_kind=appstream.IdKind.DESKTOP 403 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']) 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] 364 else: 365 description=self._get_description(name,info_url,repo_name) 366 self.descriptions_dict.update({name:description}) 367 except: 368 description='' 404 369 summary=' '.join(list(description.split(' ')[:8])) 405 if len(description.split(' '))>8: 406 summary+="... " 407 app.set_description("C",description) 408 app.set_comment("C",summary) 409 for category in appinfo['categories']: 410 app.add_category(category) 411 self.store.add_app(app) 412 gioFile=Gio.File.new_for_path('%s/%s.xml'%(self.bundles_dir,app.get_id_filename())) 413 app.to_file(gioFile) 414 # self.appimage_store.to_file(gioFile,appstream.NodeToXmlFlags.ADD_HEADER) 415 # self.appimage_store.add_app(app) 416 return(app) 417 #def _add_appimage 418 419 def _get_description_icon(self,app_name,info_url,repo_name): 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): 420 392 desc='' 421 icon='' 393 if '$(appname)' in info_url: 394 info_url=info_url.replace('$(appname)',app_name) 422 395 if info_url: 423 if '$(appname)' in info_url:424 info_url=info_url.replace('$(appname)',app_name)425 396 self._debug("Getting description from repo/app %s - %s "%(repo_name,info_url)) 426 397 try: … … 430 401 soup=BeautifulSoup(content,"html.parser") 431 402 description_div=soup.findAll('div', attrs={ "class" : "description-text"}) 432 icon_div=soup.findAll('div', attrs={ "class" : "avatar-icon avatar-large description-icon "})433 403 if len(description_div)>0: 434 404 desc=description_div[0].text 435 405 desc=desc.replace(':','.') 436 406 desc=desc.replace('&','&') 437 if len(icon_div)>0:438 icon_str=str(icon_div[0])439 icon=icon_str.split(' ')[9]440 icon=icon.lstrip('url(')441 if icon.startswith('http'):442 icon=icon.rstrip(');"></div>')443 icon=self._download_file(icon,app_name)444 print("Icon: %s"%icon)445 407 except Exception as e: 446 408 print("Can't get description from "+info_url) 447 409 print(str(e)) 448 410 pass 449 return( [desc,icon])411 return(desc) 450 412 #def _get_description 451 413 … … 463 425 #def _clean_bunlde_catalogue 464 426 465 def _download_file(self,url,app_name):466 # target_file=self.icons_folder+'/'+app_name+".png"467 target_file=self.icons_dir+'/'+app_name+".png"468 if not os.path.isfile(target_file):469 # shutil.copy("/usr/share/icons/hicolor/128x128/apps/lliurex-store.png",target_file)470 # if not os.fork():471 if not os.path.isfile(target_file):472 self._debug("Downloading %s to %s"%(url,target_file))473 try:474 with urllib.request.urlopen(url) as response, open(target_file, 'wb') as out_file:475 bf=16*1024476 acumbf=0477 file_size=int(response.info()['Content-Length'])478 while True:479 if acumbf>=file_size:480 break481 shutil.copyfileobj(response, out_file,bf)482 acumbf=acumbf+bf483 st = os.stat(target_file)484 except Exception as e:485 self._debug("Unable to download %s"%url)486 self._debug("Reason: %s"%e)487 target_file=url488 # os._exit(0)489 return(target_file)490 #def _download_file491 492 def _chk_bundle_dir(self,outdir):493 msg_status=True494 if not os.path.isdir(outdir):495 try:496 os.makedirs(outdir)497 except Exception as e:498 msg_status=False499 print(e)500 return(os.access(outdir,os.W_OK|os.R_OK|os.X_OK|os.F_OK))501 #def _chk_bundle_dir502 503 def _init_appinfo(self):504 appInfo={'appstream_id':'',\505 'id':'',\506 'name':'',\507 'version':'',\508 'releases':[],\509 'package':'',\510 'license':'',\511 'summary':'',\512 'description':'',\513 'categories':[],\514 'icon':'',\515 'screenshot':'',\516 'thumbnails':[],\517 'video':'',\518 'homepage':'',\519 'installerUrl':'',\520 'state':'',\521 'depends':'',\522 'kudos':'',\523 'suggests':'',\524 'extraInfo':'',\525 'size':'',\526 'bundle':'',\527 'updatable':'',\528 }529 return(appInfo)530 #def _init_appinfo531 532 def _get_info(self,app_info):533 app_info=self._get_releases(app_info)534 app_info['state']='available'535 if os.path.isfile(self.appimage_dir+'/'+app_info['package']):536 app_info['state']='installed'537 #Get size538 appimage_url=app_info['homepage']+'/'+app_info['package']539 dest_path=self.appimage_dir+'/'+app_info['package']540 if appimage_url:541 try:542 with urllib.request.urlopen(appimage_url) as response:543 app_info['size']=(response.info()['Content-Length'])544 except:545 app_info['size']=0546 self._set_status(0)547 self.partial_progress=100548 return(app_info)549 #def _get_info550 551 def _get_releases(self,app_info):552 releases=[]553 if app_info['installerUrl']:554 self._debug("Info url: %s"%app_info['installerUrl'])555 try:556 sw_git=False557 if 'github' in app_info['installerUrl']:558 sw_git=True559 # app_info['installerUrl']=app_info['installerUrl']+"/download"560 561 with urllib.request.urlopen(app_info['installerUrl']) as f:562 content=(f.read().decode('utf-8'))563 soup=BeautifulSoup(content,"html.parser")564 package_a=soup.findAll('a', attrs={ "href" : re.compile(r'.*\.[aA]pp[iI]mage$')})565 for package_data in package_a:566 package_name=package_data.findAll('strong', attrs={ "class" : "pl-1"})567 package_link=package_data['href']568 if sw_git:569 package_link="https://github.com"+package_link570 releases.append(package_link)571 self._debug("Link: %s"%package_link)572 except Exception as e:573 print(e)574 app_info['releases']=releases575 return app_info576 #def _get_releases577 578 def _get_releases_from_json(self,appimage):579 releases=[]580 if appimage['links']:581 for link in appimage['links']:582 if 'type' in link.keys():583 if link['type']=='Download':584 self._debug("Info url: %s"%link['url'])585 try:586 sw_git=False587 with urllib.request.urlopen(link['url']) as f:588 if 'github' in link['url']:589 sw_git=True590 content=(f.read().decode('utf-8'))591 soup=BeautifulSoup(content,"html.parser")592 package_a=soup.findAll('a', attrs={ "href" : re.compile(r'.*[aA]pp[iI]mage$')})593 for package_data in package_a:594 package_name=package_data.findAll('strong', attrs={ "class" : "pl-1"})595 package_link=package_data['href']596 if sw_git:597 package_link="https://github.com"+package_link598 releases.append(package_link)599 self._debug("Link: %s"%package_link)600 except Exception as e:601 print(e)602 return releases603 #def _get_releases_from_json604 -
lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/infoManager.py
r7137 r7143 3 3 class infomanager: 4 4 def __init__(self): 5 self.dbg= True5 self.dbg=False 6 6 self.plugin_actions={'get_info':'*'} 7 7 self.result={} … … 75 75 if app.get_pkgname_default(): 76 76 appInfo['package']=app.get_pkgname_default() 77 if len(app.get_pkgnames())>1:78 appInfo['packages']=app.get_pkgnames()79 77 if app.get_project_license(): 80 78 appInfo['license']=app.get_project_license() … … 96 94 appInfo['categories']=app.get_categories() 97 95 if app.get_icon_default(): 98 if app.get_icon_default().get_filename(): 99 appInfo['icon']=app.get_icon_default().get_filename() 100 else: 101 appInfo['icon']=app.get_icon_default().get_name() 96 appInfo['icon']=app.get_icon_default().get_name() 102 97 if appInfo['icon']==None: 103 98 icons=app.get_icons() … … 108 103 else: 109 104 appInfo['icon']='' 110 if appInfo['icon']==None: 111 appInfo['icon']='' 105 112 106 if app.get_screenshots(): 113 107 thumbnails_list=[] … … 140 134 appInfo["screenshots"]=screenshots_list 141 135 #The values are the values of appstream.UrlKind. 1=HOMEPAGE, 0=UNKNOWN 142 self._debug(app.get_url_item(0))143 136 if app.get_url_item(1): 144 137 appInfo['homepage']=app.get_url_item(1).strip() … … 168 161 if bundle.get_kind()==0: 169 162 kind=bundle.get_id().split('.')[-1] 170 appInfo['bundle'] .append(kind.lower())163 appInfo['bundle']=kind.lower() 171 164 if kind.lower=='sh': 172 165 appInfo['installerUrl']=bundle.get_id() … … 199 192 'extraInfo':'',\ 200 193 'size':'',\ 201 'bundle': [],\194 'bundle':'',\ 202 195 'updatable':'',\ 203 'component':'',\204 'releases':[]205 196 } 206 197 return(appInfo) -
lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/searchManager.py
r7137 r7143 7 7 def __init__(self): 8 8 self.locale=locale.getlocale()[0] 9 self.dbg= True9 self.dbg=False 10 10 self.store='' 11 11 self.plugin_actions={'search':'*','list':'*','list_sections':'*','info':'*'} … … 183 183 #4.- Try exact match by pkgname 184 184 app=self.store.get_app_by_pkgname(app_name) 185 if not app:186 app=self.store.get_app_by_id_ignore_prefix(app_name)187 185 self._debug("App found %s"%app) 188 186 return(app) 189 187 190 188 def _get_apps_by_match(self,tokens,applist=[]): 191 #Add items wit h match >= self.precision189 #Add items witch match >= self.precision 192 190 self._debug("Searching app by fuzzy match") 193 191 if not applist: -
lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/plugins/snapManager.py
r7132 r7143 116 116 self._set_status(1) 117 117 for pkg in pkgs: 118 app=self.store.get_app_by_pkgname(pkg.get_name()) 119 if not app: 120 self._debug("Searching for %s"%pkg.get_name()) 121 app=self.store.get_app_by_id(pkg.get_name().lower()+".desktop") 122 if app: 123 bundle=appstream.Bundle() 124 bundle.set_kind(bundle.kind_from_string('SNAP')) 125 bundle.set_id(pkg.get_name()+'.snap') 126 app.add_bundle(bundle) 127 app.add_category("Snap") 128 # store.add_app(self._generate_appstream_app_from_snap(pkg)) 129 else: 130 store.add_app(self._generate_appstream_app_from_snap(pkg)) 118 store.add_app(self._generate_appstream_app(pkg)) 131 119 return(store) 132 120 133 def _generate_appstream_app _from_snap(self,pkg):121 def _generate_appstream_app(self,pkg): 134 122 bundle=appstream.Bundle() 135 123 app=appstream.App() … … 142 130 app.add_bundle(bundle) 143 131 app.set_name("C",pkg.get_name()) 144 # app.add_pkgname(pkg.get_name()+'.snap') 145 app.add_pkgname(pkg.get_name()) 132 app.add_pkgname(pkg.get_name()+'.snap') 146 133 app.add_category("Snap") 147 134 release=appstream.Release() 148 135 release.set_version(pkg.get_version()) 149 136 app.add_release(release) 150 app.set_id("io.snapcraft.%s"%pkg.get_name()+'.snap') 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())) 151 145 # app.set_id(pkg.get_name()+'.snap') 152 146 app.set_id_kind=appstream.IdKind.DESKTOP … … 247 241 self._debug("Unable to download %s"%url) 248 242 self._debug("Reason: %s"%e) 249 target_file=''250 243 # os._exit(0) 251 244 return(target_file) … … 259 252 pkg=None 260 253 try: 261 pkg=self.snap_client.list_one_sync(app_info[' package'])254 pkg=self.snap_client.list_one_sync(app_info['name']) 262 255 app_info['state']='installed' 263 256 pkgs=[pkg] … … 265 258 app_info['state']='available' 266 259 if self.cli_mode: 267 pkgs=self._search_snap(app_info[' package'])260 pkgs=self._search_snap(app_info['name']) 268 261 else: 269 pkgs=self._search_snap_async(app_info[' package'])262 pkgs=self._search_snap_async(app_info['name']) 270 263 self._debug("Getting extended info for %s %s"%(app_info['name'],pkgs)) 271 264 if type(pkgs)==type([]): -
lliurex-store/trunk/fuentes/python3-lliurex-store.install/usr/share/lliurexstore/storeManager.py
r7137 r7143 17 17 class StoreManager(): 18 18 def __init__(self,*args,**kwargs): 19 self.dbg=False 19 20 if 'dbg' in kwargs.keys(): 20 21 self.dbg=kwargs['dbg'] 21 self.dbg=True22 22 self._propagate_dbg=False 23 23 self.store=None 24 self.stores={}25 24 self.related_actions={ 26 25 'load':['load'], … … 392 391 def _load_Store(self): 393 392 action='load' 394 #Load appstream metada first395 package_type='*'396 load_function=self._execute_class_method(action,package_type,launchedby=None)397 self.store=load_function.execute_action(action=action,store=self.store)['data']398 #Once appstream is loaded load the appstream plugins for other package types (snap, appimage...)399 393 for package_type in self.plugins_registered[action]: 400 if package_type!='*': 401 load_function=self._execute_class_method(action,package_type,launchedby=None) 402 self.store=load_function.execute_action(action=action,store=self.store)['data'] 394 load_function=self._execute_class_method(action,package_type,launchedby=None) 395 self.store=load_function.execute_action(action=action,store=self.store)['data'] 403 396 #def _load_Store 404 397 … … 424 417 # - Dict with the related info 425 418 #### 426 def _get_Extended_App_Info(self,info_applist,launchedby=None,fullsearch=True ,channel=''):419 def _get_Extended_App_Info(self,info_applist,launchedby=None,fullsearch=True): 427 420 #Check if there's any plugin for the distinct type of packages 428 421 action='pkginfo' … … 431 424 result['data']=[] 432 425 result['status']={'status':0,'msg':''} 433 processed=[]434 426 for app_info in info_applist: 435 if channel: 436 types_dict[channel]=[app_info] 427 package_type=self._check_package_type(app_info) 428 if package_type in types_dict: 429 types_dict[package_type].append(app_info) 437 430 else: 438 available_channels=self._check_package_type(app_info) 439 for package_type in available_channels: 440 if app_info['component']!='': 441 if app_info['package'] in processed: 442 continue 443 # processed.append(app_info['package']) 444 445 if package_type in types_dict: 446 types_dict[package_type].append(app_info) 447 else: 448 types_dict[package_type]=[app_info] 431 types_dict[package_type]=[app_info] 449 432 for package_type in types_dict: 450 433 self._debug("Checking plugin for %s %s"%(action,package_type)) 451 434 if package_type in self.plugins_registered[action]: 452 #Only sea ch full info if it's required435 #Only search full info if it's required 453 436 if (fullsearch==False and package_type=='deb'): 454 437 result['data'].extend(types_dict[package_type]) … … 514 497 if (launchedby=='search'): 515 498 exact_match=False 516 target_channel=''517 if '=' in search_item:518 target_channel=search_item.split('=')[-1]519 search_item=search_item.split('=')[0]520 499 for package_type in self.plugins_registered[action]: 521 500 search_function=self._execute_class_method(action,'*',launchedby=launchedby) … … 533 512 #2.- Get rest of metadata (slower) 534 513 subordinate_action='pkginfo' 535 self._debug("Target channel: %s"%target_channel) 536 result=self._get_Extended_App_Info(result['data'],launchedby,fullsearch,target_channel) 514 result=self._get_Extended_App_Info(result['data'],launchedby,fullsearch) 537 515 if launchedby: 538 516 realAction=launchedby … … 635 613 #Zomandos must have the subcategory "Zomando" 636 614 self._debug("Checking package type for app "+app_info['name']) 637 return_msg=[]638 if app_info['component']!='':639 return_msg.append('deb')640 615 if "Zomando" in app_info['categories']: 641 return_msg.append("zmd") 616 return_msg="zmd" 617 else: 642 618 #Standalone installers must have an installerUrl field loaded from a bundle type=script description 643 if app_info['bundle']: 644 return_msg.extend(app_info['bundle']) 645 if app_info['installerUrl']!='': 646 return_msg.append("sh") 647 print(return_msg) 619 if app_info['bundle']!='': 620 return_msg=app_info['bundle'] 621 elif app_info['installerUrl']!='': 622 return_msg="sh" 623 else: 624 return_msg="deb" 648 625 return(return_msg) 649 626 #def _check_package_type
Note: See TracChangeset
for help on using the changeset viewer.