From a55a6475b943a804fd76b5181b7d82968c2ea096 Mon Sep 17 00:00:00 2001 From: Leo Moll Date: Mon, 22 Jan 2018 01:01:34 +0100 Subject: [plugin.video.mediathekview] 0.4.2 --- .../resources/lib/base/Logger.py | 2 +- .../resources/lib/channelui.py | 22 ++-- .../resources/lib/exceptions.py | 3 + plugin.video.mediathekview/resources/lib/filmui.py | 13 +- .../resources/lib/initialui.py | 18 ++- .../resources/lib/kodi/KodiAddon.py | 52 +++++++- .../resources/lib/kodi/KodiUI.py | 40 +++--- .../resources/lib/mvupdate.py | 6 +- .../resources/lib/mvutils.py | 56 +++++---- .../resources/lib/notifier.py | 15 ++- .../resources/lib/settings.py | 2 + plugin.video.mediathekview/resources/lib/showui.py | 39 ++++-- .../resources/lib/storemysql.py | 136 +++++++++++++++------ .../resources/lib/storesqlite.py | 129 +++++++++++++------ .../resources/lib/ttml2srt.py | 6 +- .../resources/lib/updater.py | 48 ++++---- 16 files changed, 404 insertions(+), 183 deletions(-) (limited to 'plugin.video.mediathekview/resources/lib') diff --git a/plugin.video.mediathekview/resources/lib/base/Logger.py b/plugin.video.mediathekview/resources/lib/base/Logger.py index 3d74680..850ff44 100644 --- a/plugin.video.mediathekview/resources/lib/base/Logger.py +++ b/plugin.video.mediathekview/resources/lib/base/Logger.py @@ -28,6 +28,6 @@ class Logger( object ): def warn( self, message, *args ): pass - + def error( self, message, *args ): pass diff --git a/plugin.video.mediathekview/resources/lib/channelui.py b/plugin.video.mediathekview/resources/lib/channelui.py index 36743e8..fc9d826 100644 --- a/plugin.video.mediathekview/resources/lib/channelui.py +++ b/plugin.video.mediathekview/resources/lib/channelui.py @@ -3,17 +3,19 @@ # # -- Imports ------------------------------------------------ -import sys, urllib -import xbmcplugin, xbmcgui +import xbmcgui +import xbmcplugin + +import resources.lib.mvutils as mvutils from resources.lib.channel import Channel # -- Classes ------------------------------------------------ class ChannelUI( Channel ): - def __init__( self, handle, sortmethods = None, nextdir = 'initial' ): - self.base_url = sys.argv[0] + def __init__( self, plugin, sortmethods = None, nextdir = 'initial' ): + self.plugin = plugin + self.handle = plugin.addon_handle self.nextdir = nextdir - self.handle = handle self.sortmethods = sortmethods if sortmethods is not None else [ xbmcplugin.SORT_METHOD_TITLE ] self.count = 0 @@ -24,9 +26,14 @@ class ChannelUI( Channel ): def Add( self, altname = None ): resultingname = self.channel if self.count == 0 else '%s (%d)' % ( self.channel, self.count, ) li = xbmcgui.ListItem( label = resultingname if altname is None else altname ) + icon = 'special://home/addons/' + self.plugin.addon_id + '/resources/icons/' + self.channel.lower() + '-m.png' + li.setArt( { + 'thumb': icon, + 'icon': icon + } ) xbmcplugin.addDirectoryItem( handle = self.handle, - url = self.build_url( { + url = mvutils.build_url( { 'mode': self.nextdir, 'channel': self.id } ), @@ -36,6 +43,3 @@ class ChannelUI( Channel ): def End( self ): xbmcplugin.endOfDirectory( self.handle ) - - def build_url( self, query ): - return self.base_url + '?' + urllib.urlencode( query ) diff --git a/plugin.video.mediathekview/resources/lib/exceptions.py b/plugin.video.mediathekview/resources/lib/exceptions.py index 53d7f14..b66fb4f 100644 --- a/plugin.video.mediathekview/resources/lib/exceptions.py +++ b/plugin.video.mediathekview/resources/lib/exceptions.py @@ -7,3 +7,6 @@ class DatabaseCorrupted( RuntimeError ): class DatabaseLost( RuntimeError ): """This exception is raised when the connection to the database is lost during update""" + +class ExitRequested( Exception ): + """This exception is thrown if the addon is shut down by Kodi or by another same addon""" diff --git a/plugin.video.mediathekview/resources/lib/filmui.py b/plugin.video.mediathekview/resources/lib/filmui.py index af04798..23eaf98 100644 --- a/plugin.video.mediathekview/resources/lib/filmui.py +++ b/plugin.video.mediathekview/resources/lib/filmui.py @@ -3,7 +3,8 @@ # # -- Imports ------------------------------------------------ -import xbmcplugin, xbmcgui +import xbmcgui +import xbmcplugin from resources.lib.film import Film from resources.lib.settings import Settings @@ -45,7 +46,7 @@ class FilmUI( Film ): infoLabels = { 'title' : resultingtitle + videohds, - 'sorttitle' : resultingtitle, + 'sorttitle' : resultingtitle.lower(), 'tvshowtitle' : self.show, 'plot' : self.description } @@ -63,9 +64,15 @@ class FilmUI( Film ): infoLabels['aired'] = airedstring infoLabels['dateadded'] = airedstring - li = xbmcgui.ListItem( resultingtitle, self.description ) + icon = 'special://home/addons/' + self.plugin.addon_id + '/resources/icons/' + self.channel.lower() + '-m.png' + + li = xbmcgui.ListItem( resultingtitle ) li.setInfo( type = 'video', infoLabels = infoLabels ) li.setProperty( 'IsPlayable', 'true' ) + li.setArt( { + 'thumb': icon, + 'icon': icon + } ) # create context menu contextmenu = [] diff --git a/plugin.video.mediathekview/resources/lib/initialui.py b/plugin.video.mediathekview/resources/lib/initialui.py index 71d9aef..b59d409 100644 --- a/plugin.video.mediathekview/resources/lib/initialui.py +++ b/plugin.video.mediathekview/resources/lib/initialui.py @@ -3,13 +3,16 @@ # # -- Imports ------------------------------------------------ -import sys, urllib -import xbmcplugin, xbmcgui +import xbmcgui +import xbmcplugin + +import resources.lib.mvutils as mvutils # -- Classes ------------------------------------------------ class InitialUI( object ): - def __init__( self, handle, sortmethods = None ): - self.handle = handle + def __init__( self, plugin, sortmethods = None ): + self.plugin = plugin + self.handle = plugin.addon_handle self.sortmethods = sortmethods if sortmethods is not None else [ xbmcplugin.SORT_METHOD_TITLE ] self.channelid = 0 self.initial = '' @@ -28,7 +31,7 @@ class InitialUI( object ): li = xbmcgui.ListItem( label = resultingname ) xbmcplugin.addDirectoryItem( handle = self.handle, - url = _build_url( { + url = mvutils.build_url( { 'mode': "shows", 'channel': self.channelid, 'initial': self.initial, @@ -40,8 +43,3 @@ class InitialUI( object ): def End( self ): xbmcplugin.endOfDirectory( self.handle ) - -# -- Functions ---------------------------------------------- - -def _build_url( query ): - return sys.argv[0] + '?' + urllib.urlencode( query ) diff --git a/plugin.video.mediathekview/resources/lib/kodi/KodiAddon.py b/plugin.video.mediathekview/resources/lib/kodi/KodiAddon.py index f9c0cd7..4081044 100644 --- a/plugin.video.mediathekview/resources/lib/kodi/KodiAddon.py +++ b/plugin.video.mediathekview/resources/lib/kodi/KodiAddon.py @@ -3,14 +3,19 @@ # # -- Imports ------------------------------------------------ -import sys, urllib -import xbmc, xbmcgui, xbmcaddon, xbmcplugin +import os +import sys +import urllib + +import xbmc +import xbmcgui +import xbmcaddon +import xbmcplugin from resources.lib.kodi.KodiLogger import KodiLogger # -- Classes ------------------------------------------------ class KodiAddon( KodiLogger ): - def __init__( self ): self.addon = xbmcaddon.Addon() self.addon_id = self.addon.getAddonInfo( 'id' ) @@ -29,6 +34,7 @@ class KodiAddon( KodiLogger ): return self.addon.setSetting( setting_id, value ) def doAction( self, action ): + self.debug( 'Triggered action {}', action ) xbmc.executebuiltin( 'Action({})'.format( action ) ) class KodiService( KodiAddon ): @@ -66,3 +72,43 @@ class KodiPlugin( KodiAddon ): def endOfDirectory( self, succeeded = True, updateListing = False, cacheToDisc = True ): xbmcplugin.endOfDirectory( self.addon_handle, succeeded, updateListing, cacheToDisc ) + + +class KodiInterlockedMonitor( xbmc.Monitor ): + def __init__( self, service, setting_id ): + super( KodiInterlockedMonitor, self ).__init__() + self.instance_id = ''.join( format( x, '02x' ) for x in bytearray( os.urandom( 16 ) ) ) + self.setting_id = setting_id + self.service = service + + def RegisterInstance( self, waittime = 1 ): + if self.BadInstance(): + self.service.info( 'Found other instance with id {}', self.instance_id ) + self.service.info( 'Startup delayed by {} second(s) waiting the other instance to shut down', waittime ) + self.service.setSetting( self.setting_id, self.instance_id ) + xbmc.Monitor.waitForAbort( self, waittime ) + else: + self.service.setSetting( self.setting_id, self.instance_id ) + + def UnregisterInstance( self ): + self.service.setSetting( self.setting_id, '' ) + + def BadInstance( self ): + instance_id = self.service.getSetting( self.setting_id ) + return len( instance_id ) > 0 and self.instance_id != instance_id + + def abortRequested( self ): + return self.BadInstance() or xbmc.Monitor.abortRequested( self ) + + def waitForAbort( self, timeout = None ): + if timeout is None: + # infinite wait + while not self.abortRequested(): + if xbmc.Monitor.waitForAbort( self, 1 ): + return True + return True + else: + for _ in range( timeout ): + if self.BadInstance() or xbmc.Monitor.waitForAbort( self, 1 ): + return True + return self.BadInstance() diff --git a/plugin.video.mediathekview/resources/lib/kodi/KodiUI.py b/plugin.video.mediathekview/resources/lib/kodi/KodiUI.py index dee8dbb..138af50 100644 --- a/plugin.video.mediathekview/resources/lib/kodi/KodiUI.py +++ b/plugin.video.mediathekview/resources/lib/kodi/KodiUI.py @@ -3,15 +3,21 @@ # # -- Imports ------------------------------------------------ -import xbmc, xbmcgui +import xbmc +import xbmcgui +import xbmcaddon # -- Classes ------------------------------------------------ class KodiUI( object ): def __init__( self ): - self.bgdialog = None + self.addon = xbmcaddon.Addon() + self.language = self.addon.getLocalizedString + self.bgdialog = KodiBGDialog() - def GetEnteredText( self, deftext = '', heading = '', hidden = False ): + def GetEnteredText( self, deftext = None, heading = None, hidden = False ): + heading = self.language( heading ) if isinstance( heading, int ) else heading if heading is not None else '' + deftext = self.language( deftext ) if isinstance( deftext, int ) else deftext if deftext is not None else '' keyboard = xbmc.Keyboard( deftext, heading, 1 if hidden else 0 ) keyboard.doModal() if keyboard.isConfirmed(): @@ -19,39 +25,39 @@ class KodiUI( object ): return deftext def ShowNotification( self, heading, message, icon = xbmcgui.NOTIFICATION_INFO, time = 5000, sound = True ): + heading = self.language( heading ) if isinstance( heading, int ) else heading + message = self.language( message ) if isinstance( message, int ) else message xbmcgui.Dialog().notification( heading, message, icon, time, sound ) def ShowWarning( self, heading, message, time = 5000, sound = True ): - xbmcgui.Dialog().notification( heading, message, xbmcgui.NOTIFICATION_WARNING, time, sound ) + self.ShowNotification( heading, message, xbmcgui.NOTIFICATION_WARNING, time, sound ) def ShowError( self, heading, message, time = 5000, sound = True ): - xbmcgui.Dialog().notification( heading, message, xbmcgui.NOTIFICATION_ERROR, time, sound ) + self.ShowNotification( heading, message, xbmcgui.NOTIFICATION_ERROR, time, sound ) def ShowBGDialog( self, heading = None, message = None ): - if self.bgdialog is None: - self.bgdialog = xbmcgui.DialogProgressBG() - self.bgdialog.create( heading, message ) - else: - self.bgdialog.update( 0, heading, message ) + self.bgdialog.Create( heading, message ) def UpdateBGDialog( self, percent, heading = None, message = None ): - if self.bgdialog is not None: - self.bgdialog.update( percent, heading, message ) + self.bgdialog.Update( percent, heading, message ) + + def HookBGDialog( self, blockcount, blocksize, totalsize ): + self.bgdialog.UrlRetrieveHook( blockcount, blocksize, totalsize ) def CloseBGDialog( self ): - if self.bgdialog is not None: - self.bgdialog.close() - del self.bgdialog - self.bgdialog = None + self.bgdialog.Close() class KodiBGDialog( object ): def __init__( self ): + self.language = xbmcaddon.Addon().getLocalizedString self.bgdialog= None def __del__( self ): self.Close() def Create( self, heading = None, message = None ): + heading = self.language( heading ) if isinstance( heading, int ) else heading + message = self.language( message ) if isinstance( message, int ) else message if self.bgdialog is None: self.bgdialog = xbmcgui.DialogProgressBG() self.bgdialog.create( heading, message ) @@ -60,6 +66,8 @@ class KodiBGDialog( object ): def Update( self, percent, heading = None, message = None ): if self.bgdialog is not None: + heading = self.language( heading ) if isinstance( heading, int ) else heading + message = self.language( message ) if isinstance( message, int ) else message self.bgdialog.update( percent, heading, message ) def UrlRetrieveHook( self, blockcount, blocksize, totalsize ): diff --git a/plugin.video.mediathekview/resources/lib/mvupdate.py b/plugin.video.mediathekview/resources/lib/mvupdate.py index 7595417..477139e 100644 --- a/plugin.video.mediathekview/resources/lib/mvupdate.py +++ b/plugin.video.mediathekview/resources/lib/mvupdate.py @@ -6,7 +6,7 @@ import os import sys import argparse import datetime -import xml.etree.ElementTree as ET +import defusedxml.ElementTree as ET from resources.lib.base.Logger import Logger from resources.lib.updater import MediathekViewUpdater @@ -24,6 +24,8 @@ class Settings( object ): self.database = args.database self.nofuture = True self.minlength = 0 + self.maxage = 86400 + self.recentmode = 0 self.groupshows = False self.updenabled = True self.updinterval = 3600 @@ -104,6 +106,8 @@ class Notifier( object ): pass def UpdateUpdateProgress( self, percent, count, channels, shows, movies ): pass + def HookDownloadProgress( self, blockcount, blocksize, totalsize ): + pass def CloseUpdateProgress( self ): pass diff --git a/plugin.video.mediathekview/resources/lib/mvutils.py b/plugin.video.mediathekview/resources/lib/mvutils.py index d4c7663..7ccaf3a 100644 --- a/plugin.video.mediathekview/resources/lib/mvutils.py +++ b/plugin.video.mediathekview/resources/lib/mvutils.py @@ -3,12 +3,21 @@ # -- Imports ------------------------------------------------ import os +import sys import stat import string +import urllib import urllib2 -import xbmcvfs from contextlib import closing +from resources.lib.exceptions import ExitRequested + +# -- Kodi Specific Imports ---------------------------------- +try: + import xbmcvfs + is_kodi = True +except ImportError: + is_kodi = False # -- Functions ---------------------------------------------- def dir_exists( name ): @@ -58,30 +67,29 @@ def cleanup_filename( val ): search = ''.join( [ c for c in val if c in cset ] ) return search.strip() -def url_retrieve( url, filename, reporthook, chunk_size = 8192 ): +def url_retrieve( url, filename, reporthook, chunk_size = 8192, aborthook = None ): with closing( urllib2.urlopen( url ) ) as u, closing( open( filename, 'wb' ) ) as f: - total_size = int( u.info().getheader( 'Content-Length' ).strip() ) if u.info() and u.info().getheader( 'Content-Length' ) else 0 - total_chunks = 0 + _chunked_url_copier( u, f, reporthook, chunk_size, aborthook ) + +def url_retrieve_vfs( url, filename, reporthook, chunk_size = 8192, aborthook = None ): + with closing( urllib2.urlopen( url ) ) as u, closing( xbmcvfs.File( filename, 'wb' ) ) as f: + _chunked_url_copier( u, f, reporthook, chunk_size, aborthook ) - while True: - reporthook( total_chunks, chunk_size, total_size ) - chunk = u.read( chunk_size ) - if not chunk: - break - f.write( chunk ) - total_chunks += 1 - return ( filename, [], ) +def build_url( query ): + return sys.argv[0] + '?' + urllib.urlencode( query ) -def url_retrieve_vfs( videourl, filename, reporthook, chunk_size = 8192 ): - with closing( urllib2.urlopen( videourl ) ) as u, closing( xbmcvfs.File( filename, 'wb' ) ) as f: - total_size = int( u.info().getheader( 'Content-Length' ).strip() ) if u.info() and u.info().getheader( 'Content-Length' ) else 0 - total_chunks = 0 +def _chunked_url_copier( u, f, reporthook, chunk_size, aborthook ): + aborthook = aborthook if aborthook is not None else lambda: False + total_size = int( u.info().getheader( 'Content-Length' ).strip() ) if u.info() and u.info().getheader( 'Content-Length' ) else 0 + total_chunks = 0 - while True: - reporthook( total_chunks, chunk_size, total_size ) - chunk = u.read( chunk_size ) - if not chunk: - break - f.write( chunk ) - total_chunks += 1 - return ( filename, [], ) + while not aborthook(): + reporthook( total_chunks, chunk_size, total_size ) + chunk = u.read( chunk_size ) + if not chunk: + # operation has finished + return + f.write( chunk ) + total_chunks += 1 + # abort requested + raise ExitRequested( 'Reception interrupted.' ) diff --git a/plugin.video.mediathekview/resources/lib/notifier.py b/plugin.video.mediathekview/resources/lib/notifier.py index d257a52..517da9e 100644 --- a/plugin.video.mediathekview/resources/lib/notifier.py +++ b/plugin.video.mediathekview/resources/lib/notifier.py @@ -14,28 +14,31 @@ class Notifier( KodiUI ): self.language = xbmcaddon.Addon().getLocalizedString def ShowDatabaseError( self, err ): - self.ShowError( self.language( 30951 ), '{}'.format( err ) ) + self.ShowError( 30951, '{}'.format( err ) ) def ShowDownloadError( self, name, err ): - self.ShowError( self.language( 30952 ), self.language( 30953 ).format( name, err ) ) + self.ShowError( 30952, self.language( 30953 ).format( name, err ) ) def ShowMissingExtractorError( self ): - self.ShowError( self.language( 30952 ), self.language( 30954 ), time = 10000 ) + self.ShowError( 30952, 30954, time = 10000 ) def ShowLimitResults( self, maxresults ): - self.ShowNotification( self.language( 30980 ), self.language( 30981 ).format( maxresults ) ) + self.ShowNotification( 30980, self.language( 30981 ).format( maxresults ) ) def ShowDownloadProgress( self ): - self.ShowBGDialog( self.language( 30955 ) ) + self.ShowBGDialog( 30955 ) def UpdateDownloadProgress( self, percent, message = None ): self.UpdateBGDialog( percent, message = message ) + def HookDownloadProgress( self, blockcount, blocksize, totalsize ): + self.HookBGDialog( blockcount, blocksize, totalsize ) + def CloseDownloadProgress( self ): self.CloseBGDialog() def ShowUpdateProgress( self ): - self.ShowBGDialog( self.language( 30956 ) ) + self.ShowBGDialog( 30956 ) def UpdateUpdateProgress( self, percent, count, channels, shows, movies ): message = self.language( 30957 ) % ( count, channels, shows, movies ) diff --git a/plugin.video.mediathekview/resources/lib/settings.py b/plugin.video.mediathekview/resources/lib/settings.py index 32bd95a..13d86e0 100644 --- a/plugin.video.mediathekview/resources/lib/settings.py +++ b/plugin.video.mediathekview/resources/lib/settings.py @@ -19,6 +19,8 @@ class Settings( object ): self.minlength = int( float( self.addon.getSetting( 'minlength' ) ) ) * 60 self.groupshows = self.addon.getSetting( 'groupshows' ) == 'true' self.maxresults = int( self.addon.getSetting( 'maxresults' ) ) + self.maxage = int( self.addon.getSetting( 'maxage' ) ) * 86400 + self.recentmode = int( self.addon.getSetting( 'recentmode' ) ) self.downloadpath = self.addon.getSetting( 'downloadpath' ) self.type = self.addon.getSetting( 'dbtype' ) self.host = self.addon.getSetting( 'dbhost' ) diff --git a/plugin.video.mediathekview/resources/lib/showui.py b/plugin.video.mediathekview/resources/lib/showui.py index b0bf7f9..64aff20 100644 --- a/plugin.video.mediathekview/resources/lib/showui.py +++ b/plugin.video.mediathekview/resources/lib/showui.py @@ -3,35 +3,55 @@ # # -- Imports ------------------------------------------------ -import sys, urllib -import xbmcplugin, xbmcgui +import xbmcgui +import xbmcplugin + +import resources.lib.mvutils as mvutils from resources.lib.show import Show # -- Classes ------------------------------------------------ class ShowUI( Show ): - def __init__( self, handle, sortmethods = None ): - self.base_url = sys.argv[0] - self.handle = handle + def __init__( self, plugin, sortmethods = None ): + self.plugin = plugin + self.handle = plugin.addon_handle self.sortmethods = sortmethods if sortmethods is not None else [ xbmcplugin.SORT_METHOD_TITLE ] self.querychannelid = 0 def Begin( self, channelid ): - self.querychannelid = channelid + self.querychannelid = int( channelid ) for method in self.sortmethods: xbmcplugin.addSortMethod( self.handle, method ) def Add( self, altname = None ): if altname is not None: resultingname = altname - elif self.querychannelid == '0': + elif self.querychannelid == 0: resultingname = self.show + ' [' + self.channel + ']' else: resultingname = self.show + + infoLabels = { + 'title' : resultingname, + 'sorttitle' : resultingname.lower() + } + + + if self.channel.find( ',' ) == -1: + icon = 'special://home/addons/' + self.plugin.addon_id + '/resources/icons/' + self.channel.lower() + '-m.png' + else: + icon = 'special://home/addons/' + self.plugin.addon_id + '/resources/icons/default-m.png' + li = xbmcgui.ListItem( label = resultingname ) + li.setInfo( type = 'video', infoLabels = infoLabels ) + li.setArt( { + 'thumb': icon, + 'icon': icon + } ) + xbmcplugin.addDirectoryItem( handle = self.handle, - url = self.build_url( { + url = mvutils.build_url( { 'mode': "films", 'show': self.id } ), @@ -41,6 +61,3 @@ class ShowUI( Show ): def End( self ): xbmcplugin.endOfDirectory( self.handle ) - - def build_url( self, query ): - return self.base_url + '?' + urllib.urlencode( query ) diff --git a/plugin.video.mediathekview/resources/lib/storemysql.py b/plugin.video.mediathekview/resources/lib/storemysql.py index e2419cc..9268eec 100644 --- a/plugin.video.mediathekview/resources/lib/storemysql.py +++ b/plugin.video.mediathekview/resources/lib/storemysql.py @@ -20,7 +20,7 @@ class StoreMySQL( object ): # useful query fragments self.sql_query_films = "SELECT film.id,`title`,`show`,`channel`,`description`,TIME_TO_SEC(`duration`) AS `seconds`,`size`,`aired`,`url_sub`,`url_video`,`url_video_sd`,`url_video_hd` FROM `film` LEFT JOIN `show` ON show.id=film.showid LEFT JOIN `channel` ON channel.id=film.channelid" self.sql_query_filmcnt = "SELECT COUNT(*) FROM `film` LEFT JOIN `show` ON show.id=film.showid LEFT JOIN `channel` ON channel.id=film.channelid" - self.sql_cond_recent = "( TIMESTAMPDIFF(HOUR,`aired`,CURRENT_TIMESTAMP()) < 24 )" + self.sql_cond_recent = "( TIMESTAMPDIFF(SECOND,{},CURRENT_TIMESTAMP()) <= {} )".format( "aired" if settings.recentmode == 0 else "film.dtCreated", settings.maxage ) self.sql_cond_nofuture = " AND ( ( `aired` IS NULL ) OR ( TIMESTAMPDIFF(HOUR,`aired`,CURRENT_TIMESTAMP()) > 0 ) )" if settings.nofuture else "" self.sql_cond_minlength = " AND ( ( `duration` IS NULL ) OR ( TIME_TO_SEC(`duration`) >= %d ) )" % settings.minlength if settings.minlength > 0 else "" @@ -48,17 +48,21 @@ class StoreMySQL( object ): self.conn.close() def Search( self, search, filmui ): - self._Search_Condition( '( ( `title` LIKE "%%%s%%" ) OR ( `show` LIKE "%%%s%%" ) )' % ( search, search, ), filmui, True, True, self.settings.maxresults ) + searchmask = '%' + search.decode('utf-8') + '%' + self._Search_Condition( '( ( `title` LIKE %s ) OR ( `show` LIKE %s ) )', ( searchmask, searchmask, ), filmui, True, True, self.settings.maxresults ) def SearchFull( self, search, filmui ): - self._Search_Condition( '( ( `title` LIKE "%%%s%%" ) OR ( `show` LIKE "%%%s%%" ) ) OR ( `description` LIKE "%%%s%%") )' % ( search, search, search ), filmui, True, True, self.settings.maxresults ) + searchmask = '%' + search.decode('utf-8') + '%' + self._Search_Condition( '( ( `title` LIKE %s ) OR ( `show` LIKE %s ) OR ( `description` LIKE %s ) )', ( searchmask, searchmask, searchmask ), filmui, True, True, self.settings.maxresults ) def GetRecents( self, channelid, filmui ): - sql_cond_channel = ' AND ( film.channelid=' + str( channelid ) + ' ) ' if channelid != '0' else '' - self._Search_Condition( self.sql_cond_recent + sql_cond_channel, filmui, True, False, 10000 ) + if channelid != '0': + self._Search_Condition( self.sql_cond_recent + ' AND ( film.channelid=%s )', ( int( channelid ), ), filmui, True, False, 10000 ) + else: + self._Search_Condition( self.sql_cond_recent, (), filmui, True, False, 10000 ) def GetLiveStreams( self, filmui ): - self._Search_Condition( '( show.search="LIVESTREAM" )', filmui, False, False, 10000 ) + self._Search_Condition( '( show.search="LIVESTREAM" )', (), filmui, False, False, 10000 ) def GetChannels( self, channelui ): self._Channels_Condition( None, channelui ) @@ -70,18 +74,30 @@ class StoreMySQL( object ): if self.conn is None: return try: - condition = 'WHERE ( `channelid`=' + str( channelid ) + ' ) ' if channelid != '0' else '' - self.logger.info( 'MySQL Query: {}', - 'SELECT LEFT(`search`,1) AS letter,COUNT(*) AS `count` FROM `show` ' + - condition + - 'GROUP BY LEFT(search,1)' - ) + channelid = int( channelid ) cursor = self.conn.cursor() - cursor.execute( - 'SELECT LEFT(`search`,1) AS letter,COUNT(*) AS `count` FROM `show` ' + - condition + - 'GROUP BY LEFT(`search`,1)' - ) + if channelid != 0: + self.logger.info( + 'MySQL Query: SELECT LEFT(`search`,1) AS letter,COUNT(*) AS `count` FROM `show` WHERE ( `channelid`={} ) GROUP BY LEFT(search,1)', + channelid + ) + cursor.execute( """ + SELECT LEFT(`search`,1) AS `letter`, + COUNT(*) AS `count` + FROM `show` + WHERE ( `channelid`=%s ) + GROUP BY LEFT(`search`,1) + """, ( channelid, ) ) + else: + self.logger.info( + 'MySQL Query: SELECT LEFT(`search`,1) AS letter,COUNT(*) AS `count` FROM `show` GROUP BY LEFT(search,1)' + ) + cursor.execute( """ + SELECT LEFT(`search`,1) AS `letter`, + COUNT(*) AS `count` + FROM `show` + GROUP BY LEFT(`search`,1) + """ ) initialui.Begin( channelid ) for ( initialui.initial, initialui.count ) in cursor: initialui.Add() @@ -95,15 +111,57 @@ class StoreMySQL( object ): if self.conn is None: return try: - if channelid == '0' and self.settings.groupshows: - query = 'SELECT GROUP_CONCAT(show.id),GROUP_CONCAT(`channelid`),`show`,GROUP_CONCAT(`channel`) FROM `show` LEFT JOIN `channel` ON channel.id=show.channelid WHERE ( `show` LIKE "%s%%" ) GROUP BY `show`' % initial - elif channelid == '0': - query = 'SELECT show.id,show.channelid,show.show,channel.channel FROM `show` LEFT JOIN channel ON channel.id=show.channelid WHERE ( `show` LIKE "%s%%" )' % initial - else: - query = 'SELECT show.id,show.channelid,show.show,channel.channel FROM `show` LEFT JOIN channel ON channel.id=show.channelid WHERE ( `channelid`=%s ) AND ( `show` LIKE "%s%%" )' % ( channelid, initial ) - self.logger.info( 'MySQL Query: {}', query ) + channelid = int( channelid ) cursor = self.conn.cursor() - cursor.execute( query ) + if channelid == 0 and self.settings.groupshows: + cursor.execute( """ + SELECT GROUP_CONCAT(show.id), + GROUP_CONCAT(`channelid`), + `show`, + GROUP_CONCAT(`channel`) + FROM `show` + LEFT JOIN `channel` + ON ( channel.id = show.channelid ) + WHERE ( `show` LIKE %s ) + GROUP BY `show` + """, ( initial + '%', ) ) + elif channelid == 0: + cursor.execute( """ + SELECT show.id, + show.channelid, + show.show, + channel.channel + FROM `show` + LEFT JOIN `channel` + ON ( channel.id = show.channelid ) + WHERE ( `show` LIKE %s ) + """, ( initial + '%', ) ) + elif initial: + cursor.execute( """ + SELECT show.id, + show.channelid, + show.show, + channel.channel + FROM `show` + LEFT JOIN `channel` + ON ( channel.id = show.channelid ) + WHERE ( + ( `channelid` = %s ) + AND + ( `show` LIKE %s ) + ) + """, ( channelid, initial + '%', ) ) + else: + cursor.execute( """ + SELECT show.id, + show.channelid, + show.show, + channel.channel + FROM `show` + LEFT JOIN `channel` + ON ( channel.id = show.channelid ) + WHERE ( `channelid` = %s ) + """, ( channelid, ) ) showui.Begin( channelid ) for ( showui.id, showui.channelid, showui.show, showui.channel ) in cursor: showui.Add() @@ -118,13 +176,10 @@ class StoreMySQL( object ): return if showid.find( ',' ) == -1: # only one channel id - condition = '( `showid`=%s )' % showid - showchannels = False + self._Search_Condition( '( `showid` = %s )', ( int( showid ), ), filmui, False, False, 10000 ) else: # multiple channel ids - condition = '( `showid` IN ( %s ) )' % showid - showchannels = True - self._Search_Condition( condition, filmui, False, showchannels, 10000 ) + self._Search_Condition( '( `showid` IN ( {} ) )'.format( showid ), (), filmui, False, True, 10000 ) def _Channels_Condition( self, condition, channelui): if self.conn is None: @@ -132,11 +187,14 @@ class StoreMySQL( object ): try: if condition is None: query = 'SELECT `id`,`channel`,0 AS `count` FROM `channel`' + qtail = '' else: - query = 'SELECT channel.id AS `id`,`channel`,COUNT(*) AS `count` FROM `film` LEFT JOIN `channel` ON channel.id=film.channelid WHERE ' + condition + ' GROUP BY channel.id' - self.logger.info( 'MySQL Query: {}', query ) + query = 'SELECT channel.id AS `id`,`channel`,COUNT(*) AS `count` FROM `film` LEFT JOIN `channel` ON channel.id=film.channelid' + qtail = ' WHERE ' + condition + self.sql_cond_nofuture + self.sql_cond_minlength + ' GROUP BY channel.id' + self.logger.info( 'MySQL Query: {}', query + qtail ) + cursor = self.conn.cursor() - cursor.execute( query ) + cursor.execute( query + qtail ) channelui.Begin() for ( channelui.id, channelui.channel, channelui.count ) in cursor: channelui.Add() @@ -146,7 +204,7 @@ class StoreMySQL( object ): self.logger.error( 'Database error: {}', err ) self.notifier.ShowDatabaseError( err ) - def _Search_Condition( self, condition, filmui, showshows, showchannels, maxresults ): + def _Search_Condition( self, condition, params, filmui, showshows, showchannels, maxresults ): if self.conn is None: return try: @@ -164,7 +222,8 @@ class StoreMySQL( object ): condition + self.sql_cond_nofuture + self.sql_cond_minlength + - ' LIMIT {}'.format( maxresults + 1 ) if maxresults else '' + ' LIMIT {}'.format( maxresults + 1 ) if maxresults else '', + params ) ( results, ) = cursor.fetchone() if maxresults and results > maxresults: @@ -175,7 +234,8 @@ class StoreMySQL( object ): condition + self.sql_cond_nofuture + self.sql_cond_minlength + - ' LIMIT {}'.format( maxresults + 1 ) if maxresults else '' + ' LIMIT {}'.format( maxresults + 1 ) if maxresults else '', + params ) filmui.Begin( showshows, showchannels ) for ( filmui.id, filmui.title, filmui.show, filmui.channel, filmui.description, filmui.seconds, filmui.size, filmui.aired, filmui.url_sub, filmui.url_video, filmui.url_video_sd, filmui.url_video_hd ) in cursor: @@ -518,10 +578,10 @@ class StoreMySQL( object ): cursor = self.conn.cursor() cursor.callproc( 'ftInsertChannel', ( channel, ) ) for result in cursor.stored_results(): - for ( id, added ) in result: + for ( idd, added ) in result: cursor.close() self.conn.commit() - return ( id, added ) + return ( idd, added ) # should never happen cursor.close() self.conn.commit() diff --git a/plugin.video.mediathekview/resources/lib/storesqlite.py b/plugin.video.mediathekview/resources/lib/storesqlite.py index 601db67..90d10b1 100644 --- a/plugin.video.mediathekview/resources/lib/storesqlite.py +++ b/plugin.video.mediathekview/resources/lib/storesqlite.py @@ -23,7 +23,7 @@ class StoreSQLite( object ): # useful query fragments self.sql_query_films = "SELECT film.id,title,show,channel,description,duration,size,datetime(aired, 'unixepoch', 'localtime'),url_sub,url_video,url_video_sd,url_video_hd FROM film LEFT JOIN show ON show.id=film.showid LEFT JOIN channel ON channel.id=film.channelid" self.sql_query_filmcnt = "SELECT COUNT(*) FROM film LEFT JOIN show ON show.id=film.showid LEFT JOIN channel ON channel.id=film.channelid" - self.sql_cond_recent = "( ( UNIX_TIMESTAMP() - aired ) <= 86400 )" + self.sql_cond_recent = "( ( UNIX_TIMESTAMP() - {} ) <= {} )".format( "aired" if settings.recentmode == 0 else "film.dtCreated", settings.maxage ) self.sql_cond_nofuture = " AND ( ( aired IS NULL ) OR ( ( UNIX_TIMESTAMP() - aired ) > 0 ) )" if settings.nofuture else "" self.sql_cond_minlength = " AND ( ( duration IS NULL ) OR ( duration >= %d ) )" % settings.minlength if settings.minlength > 0 else "" @@ -55,17 +55,21 @@ class StoreSQLite( object ): self.conn = None def Search( self, search, filmui ): - self._Search_Condition( '( ( title LIKE "%%%s%%" ) OR ( show LIKE "%%%s%%" ) )' % ( search, search ), filmui, True, True, self.settings.maxresults ) + searchmask = '%' + search.decode('utf-8') + '%' + self._Search_Condition( '( ( title LIKE ? ) OR ( show LIKE ? ) )', ( searchmask, searchmask, ), filmui, True, True, self.settings.maxresults ) def SearchFull( self, search, filmui ): - self._Search_Condition( '( ( title LIKE "%%%s%%" ) OR ( show LIKE "%%%s%%" ) OR ( description LIKE "%%%s%%") )' % ( search, search, search ), filmui, True, True, self.settings.maxresults ) + searchmask = '%' + search.decode('utf-8') + '%' + self._Search_Condition( '( ( title LIKE ? ) OR ( show LIKE ? ) OR ( description LIKE ? ) )', ( searchmask, searchmask, searchmask ), filmui, True, True, self.settings.maxresults ) def GetRecents( self, channelid, filmui ): - sql_cond_channel = ' AND ( film.channelid=' + str( channelid ) + ' ) ' if channelid != '0' else '' - self._Search_Condition( self.sql_cond_recent + sql_cond_channel, filmui, True, False, 10000 ) + if channelid != '0': + self._Search_Condition( self.sql_cond_recent + ' AND ( film.channelid=? )', ( int( channelid ), ), filmui, True, False, 10000 ) + else: + self._Search_Condition( self.sql_cond_recent, (), filmui, True, False, 10000 ) def GetLiveStreams( self, filmui ): - self._Search_Condition( '( show.search="LIVESTREAM" )', filmui, False, False, 10000 ) + self._Search_Condition( '( show.search="LIVESTREAM" )', (), filmui, False, False, 10000 ) def GetChannels( self, channelui ): self._Channels_Condition( None, channelui ) @@ -77,18 +81,28 @@ class StoreSQLite( object ): if self.conn is None: return try: - condition = 'WHERE ( channelid=' + str( channelid ) + ' ) ' if channelid != '0' else '' - self.logger.info( 'SQlite Query: {}', - 'SELECT SUBSTR(search,1,1),COUNT(*) FROM show ' + - condition + - 'GROUP BY LEFT(search,1)' - ) + channelid = int( channelid ) cursor = self.conn.cursor() - cursor.execute( - 'SELECT SUBSTR(search,1,1),COUNT(*) FROM show ' + - condition + - 'GROUP BY SUBSTR(search,1,1)' - ) + if channelid != 0: + self.logger.info( + 'SQlite Query: SELECT SUBSTR(search,1,1),COUNT(*) FROM show WHERE ( channelid={} ) GROUP BY LEFT(search,1)', + channelid + ) + cursor.execute( """ + SELECT SUBSTR(search,1,1),COUNT(*) + FROM show + WHERE ( channelid=? ) + GROUP BY SUBSTR(search,1,1) + """, ( channelid, ) ) + else: + self.logger.info( + 'SQlite Query: SELECT SUBSTR(search,1,1),COUNT(*) FROM show GROUP BY LEFT(search,1)' + ) + cursor.execute( """ + SELECT SUBSTR(search,1,1),COUNT(*) + FROM show + GROUP BY SUBSTR(search,1,1) + """ ) initialui.Begin( channelid ) for ( initialui.initial, initialui.count ) in cursor: initialui.Add() @@ -102,15 +116,57 @@ class StoreSQLite( object ): if self.conn is None: return try: - if channelid == '0' and self.settings.groupshows: - query = 'SELECT GROUP_CONCAT(show.id),GROUP_CONCAT(channelid),show,GROUP_CONCAT(channel) FROM show LEFT JOIN channel ON channel.id=show.channelid WHERE ( show LIKE "%s%%" ) GROUP BY show' % initial - elif channelid == '0': - query = 'SELECT show.id,show.channelid,show.show,channel.channel FROM show LEFT JOIN channel ON channel.id=show.channelid WHERE ( show LIKE "%s%%" )' % initial - else: - query = 'SELECT show.id,show.channelid,show.show,channel.channel FROM show LEFT JOIN channel ON channel.id=show.channelid WHERE ( channelid=%s ) AND ( show LIKE "%s%%" )' % ( channelid, initial ) - self.logger.info( 'SQLite Query: {}', query ) + channelid = int( channelid ) cursor = self.conn.cursor() - cursor.execute( query ) + if channelid == 0 and self.settings.groupshows: + cursor.execute( """ + SELECT GROUP_CONCAT(show.id), + GROUP_CONCAT(channelid), + show, + GROUP_CONCAT(channel) + FROM show + LEFT JOIN channel + ON ( channel.id = show.channelid ) + WHERE ( show LIKE ? ) + GROUP BY show + """, ( initial + '%', ) ) + elif channelid == 0: + cursor.execute( """ + SELECT show.id, + show.channelid, + show.show, + channel.channel + FROM show + LEFT JOIN channel + ON ( channel.id = show.channelid ) + WHERE ( show LIKE ? ) + """, ( initial + '%', ) ) + elif initial: + cursor.execute( """ + SELECT show.id, + show.channelid, + show.show, + channel.channel + FROM show + LEFT JOIN channel + ON ( channel.id = show.channelid ) + WHERE ( + ( channelid=? ) + AND + ( show LIKE ? ) + ) + """, ( channelid, initial + '%', ) ) + else: + cursor.execute( """ + SELECT show.id, + show.channelid, + show.show, + channel.channel + FROM show + LEFT JOIN channel + ON ( channel.id = show.channelid ) + WHERE ( channelid=? ) + """, ( channelid, ) ) showui.Begin( channelid ) for ( showui.id, showui.channelid, showui.show, showui.channel ) in cursor: showui.Add() @@ -125,13 +181,10 @@ class StoreSQLite( object ): return if showid.find( ',' ) == -1: # only one channel id - condition = '( showid=%s )' % showid - showchannels = False + self._Search_Condition( '( showid=? )', ( int( showid ), ), filmui, False, False, 10000 ) else: # multiple channel ids - condition = '( showid IN ( %s ) )' % showid - showchannels = True - self._Search_Condition( condition, filmui, False, showchannels, 10000 ) + self._Search_Condition( '( showid IN ( {} ) )'.format( showid ), (), filmui, False, True, 10000 ) def _Channels_Condition( self, condition, channelui ): if self.conn is None: @@ -139,11 +192,13 @@ class StoreSQLite( object ): try: if condition is None: query = 'SELECT id,channel,0 AS `count` FROM channel' + qtail = '' else: - query = 'SELECT channel.id AS `id`,channel,COUNT(*) AS `count` FROM film LEFT JOIN channel ON channel.id=film.channelid WHERE ' + condition + ' GROUP BY channel' - self.logger.info( 'SQLite Query: {}', query ) + query = 'SELECT channel.id AS `id`,channel,COUNT(*) AS `count` FROM film LEFT JOIN channel ON channel.id=film.channelid' + qtail = ' WHERE ' + condition + ' GROUP BY channel' + self.logger.info( 'SQLite Query: {}', query + qtail ) cursor = self.conn.cursor() - cursor.execute( query ) + cursor.execute( query + qtail ) channelui.Begin() for ( channelui.id, channelui.channel, channelui.count ) in cursor: channelui.Add() @@ -153,7 +208,7 @@ class StoreSQLite( object ): self.logger.error( 'Database error: {}', err ) self.notifier.ShowDatabaseError( err ) - def _Search_Condition( self, condition, filmui, showshows, showchannels, maxresults ): + def _Search_Condition( self, condition, params, filmui, showshows, showchannels, maxresults ): if self.conn is None: return try: @@ -172,7 +227,8 @@ class StoreSQLite( object ): condition + self.sql_cond_nofuture + self.sql_cond_minlength + - ' LIMIT {}'.format( maxresults + 1 ) if maxresults else '' + ' LIMIT {}'.format( maxresults + 1 ) if maxresults else '', + params ) ( results, ) = cursor.fetchone() if maxresults and results > maxresults: @@ -183,7 +239,8 @@ class StoreSQLite( object ): condition + self.sql_cond_nofuture + self.sql_cond_minlength + - ' LIMIT {}'.format( maxresults ) if maxresults else '' + ' LIMIT {}'.format( maxresults ) if maxresults else '', + params ) filmui.Begin( showshows, showchannels ) for ( filmui.id, filmui.title, filmui.show, filmui.channel, filmui.description, filmui.seconds, filmui.size, filmui.aired, filmui.url_sub, filmui.url_video, filmui.url_video_sd, filmui.url_video_hd ) in cursor: diff --git a/plugin.video.mediathekview/resources/lib/ttml2srt.py b/plugin.video.mediathekview/resources/lib/ttml2srt.py index 7bfdc47..5c2c4e3 100644 --- a/plugin.video.mediathekview/resources/lib/ttml2srt.py +++ b/plugin.video.mediathekview/resources/lib/ttml2srt.py @@ -27,7 +27,7 @@ import re import io from datetime import timedelta -from xml.etree import ElementTree as ET +from defusedxml import ElementTree as ET def ttml2srt( infile, outfile ): tree = ET.parse( infile ) @@ -59,7 +59,7 @@ def ttml2srt( infile, outfile ): def parse_time_expression(expression, default_offset=timedelta(0)): offset_time = re.match(r'^([0-9]+(\.[0-9]+)?)(h|m|s|ms|f|t)$', expression) if offset_time: - time_value, fraction, metric = offset_time.groups() + time_value, _, metric = offset_time.groups() time_value = float(time_value) if metric == 'h': return default_offset + timedelta(hours=time_value) @@ -79,7 +79,7 @@ def ttml2srt( infile, outfile ): clock_time = re.match( r'^([0-9]{2,}):([0-9]{2,}):([0-9]{2,}(\.[0-9]+)?)$', expression) if clock_time: - hours, minutes, seconds, fraction = clock_time.groups() + hours, minutes, seconds, _ = clock_time.groups() return timedelta(hours=int(hours), minutes=int(minutes), seconds=float(seconds)) clock_time_frames = re.match( diff --git a/plugin.video.mediathekview/resources/lib/updater.py b/plugin.video.mediathekview/resources/lib/updater.py index afdf840..95c99d0 100644 --- a/plugin.video.mediathekview/resources/lib/updater.py +++ b/plugin.video.mediathekview/resources/lib/updater.py @@ -2,9 +2,15 @@ # Copyright (c) 2017-2018, Leo Moll # -- Imports ------------------------------------------------ -import os, urllib2, subprocess, ijson, datetime, time -import xml.etree.ElementTree as etree - +import os +import time +import ijson +import random +import urllib2 +import datetime +import subprocess + +import defusedxml.ElementTree as etree import resources.lib.mvutils as mvutils from operator import itemgetter @@ -12,6 +18,7 @@ from operator import itemgetter from resources.lib.store import Store from resources.lib.exceptions import DatabaseCorrupted from resources.lib.exceptions import DatabaseLost +from resources.lib.exceptions import ExitRequested # -- Unpacker support --------------------------------------- upd_can_bz2 = False @@ -106,7 +113,7 @@ class MediathekViewUpdater( object ): self.Import( full ) def Import( self, full ): - ( _, compfile, destfile, avgrecsize ) = self._get_update_info( full ) + ( _, _, destfile, avgrecsize ) = self._get_update_info( full ) if not mvutils.file_exists( destfile ): self.logger.error( 'File {} does not exists', destfile ) return False @@ -178,14 +185,14 @@ class MediathekViewUpdater( object ): except DatabaseLost as err: self.logger.error( '{}', err ) self.notifier.CloseUpdateProgress() - except IOError as err: + except Exception as err: self.logger.error( 'Error {} wile processing {}', err, destfile ) self._update_end( full, 'ABORTED' ) self.notifier.CloseUpdateProgress() return False def GetNewestList( self, full ): - ( url, compfile, destfile, avgrecsize ) = self._get_update_info( full ) + ( url, compfile, destfile, _ ) = self._get_update_info( full ) if url is None: self.logger.error( 'No suitable archive extractor available for this system' ) self.notifier.ShowMissingExtractorError() @@ -199,20 +206,18 @@ class MediathekViewUpdater( object ): self.logger.error( 'Failure opening {}', url ) self.notifier.ShowDownloadError( url, err ) return False - root = etree.fromstring ( data ) urls = [] for server in root.findall( 'Server' ): try: URL = server.find( 'URL' ).text Prio = server.find( 'Prio' ).text - urls.append( ( self._get_update_url( URL ), Prio ) ) + urls.append( ( self._get_update_url( URL ), float( Prio ) + random.random() * 1.2 ) ) self.logger.info( 'Found mirror {} (Priority {})', URL, Prio ) except AttributeError: pass urls = sorted( urls, key = itemgetter( 1 ) ) urls = [ url[0] for url in urls ] - result = None # cleanup downloads self.logger.info( 'Cleaning up old downloads...' ) @@ -227,17 +232,23 @@ class MediathekViewUpdater( object ): lasturl = url self.logger.info( 'Trying to download {} from {}...', os.path.basename( compfile ), url ) self.notifier.UpdateDownloadProgress( 0, url ) - result = mvutils.url_retrieve( url, filename = compfile, reporthook = self._reporthook ) + mvutils.url_retrieve( url, filename = compfile, reporthook = self.notifier.HookDownloadProgress, aborthook = self.monitor.abortRequested ) break except urllib2.URLError as err: self.logger.error( 'Failure downloading {}', url ) + self.notifier.CloseDownloadProgress() + self.notifier.ShowDownloadError( lasturl, err ) + return False + except ExitRequested as err: + self.logger.error( 'Immediate exit requested. Aborting download of {}', url ) + self.notifier.CloseDownloadProgress() + self.notifier.ShowDownloadError( lasturl, err ) + return False except Exception as err: self.logger.error( 'Failure writng {}', url ) - if result is None: - self.logger.info( 'No file downloaded' ) - self.notifier.CloseDownloadProgress() - self.notifier.ShowDownloadError( lasturl, err ) - return False + self.notifier.CloseDownloadProgress() + self.notifier.ShowDownloadError( lasturl, err ) + return False # decompress filmliste if self.use_xz is True: @@ -304,13 +315,6 @@ class MediathekViewUpdater( object ): self.logger.error( 'Failed to remove {}: error {}', name, err ) return False - def _reporthook( self, blockcount, blocksize, totalsize ): - downloaded = blockcount * blocksize - if totalsize > 0: - percent = int( (downloaded * 100) / totalsize ) - self.notifier.UpdateDownloadProgress( percent ) - self.logger.debug( 'Downloading blockcount={}, blocksize={}, totalsize={}', blockcount, blocksize, totalsize ) - def _update_start( self, full ): self.logger.info( 'Initializing update...' ) self.add_chn = 0 -- cgit v1.2.3