def canDirectPlay(self, item, choice): maxResolution = item.settings.getMaxResolution(item.getQualityType(), self.isSupported4k(choice.media, choice.videoStream)) height = choice.media.getVideoResolution() if height > maxResolution: util.LOG("MDE: (DP) Video height is greater than max allowed: {0} > {1}".format(height, maxResolution)) if height > 1088 and item.settings.getPreference("allow_4k", True): util.LOG("MDE: (DP) Unsupported 4k media") return False maxBitrate = item.settings.getMaxBitrate(item.getQualityType()) bitrate = choice.media.bitrate.asInt() if bitrate > maxBitrate: util.LOG("MDE: (DP) Video bitrate is greater than the allowed max: {0} > {1}".format(bitrate, maxBitrate)) return False if choice.videoStream is None: util.ERROR_LOG("MDE: (DP) No video stream") return True if not item.settings.getGlobal("supports1080p60"): videoFrameRate = choice.videoStream.asInt() if videoFrameRate > 30 and height >= 1080: util.LOG("MDE: (DP) Frame rate is not supported for resolution: {0}@{1}".format(height, videoFrameRate)) return False if choice.videoStream.codec == "hevc" and not item.settings.getPreference("allow_hevc", False): util.LOG("MDE: (DP) Codec is HEVC, which is disabled") return False return True
def dl_tvh(): import kodijsonrpc try: if not os.path.isdir('/storage/.kodi/userdata/addon_data/service.multimedia.tvheadend'): show_error("tvheadend not installed") return selectConnections() #Set before so live TV is working when we set it util.LOG('Setting pvrmanager.syncchannelgroups to true...') result = kodijsonrpc.rpc.Settings.SetSettingValue(setting='pvrmanager.syncchannelgroups', value=True) util.LOG('Result: {0}'.format(result)) with util.ServiceControl('service.multimedia.tvheadend.service'): removeDir("/storage/.kodi/userdata/addon_data/service.multimedia.tvheadend/channel") removeDir("/storage/.kodi/userdata/addon_data/service.multimedia.tvheadend/input/dvb") tarFile = "/storage/.kodi/userdata/addon_data/service.multimedia.tvheadend/BackUp.tar.gz" downloadWithProgress(TVH_URL, tarFile, 'Downloading channel fix...') extractTar(tarFile, "/") os.remove(tarFile) xbmc.executebuiltin('Reboot') except DownloadCanceledException: show_error('Canceled') except: util.ERROR() show_error("Error")
def __init__(self, media=None, partIndex=0): self.media = media self.part = None self.forceTranscode = False self.isDirectPlayable = False self.videoStream = None self.audioStream = None self.subtitleStream = None self.isSelected = False self.subtitleDecision = self.SUBTITLES_DEFAULT self.sorts = util.AttributeDict() if media: self.indirectHeaders = media.indirectHeaders self.part = media.parts[partIndex] if self.part: # We generally just rely on PMS to have told us selected streams, so # initialize our streams accordingly. self.videoStream = self.part.getSelectedStreamOfType(plexstream.PlexStream.TYPE_VIDEO) self.audioStream = self.part.getSelectedStreamOfType(plexstream.PlexStream.TYPE_AUDIO) self.subtitleStream = self.part.getSelectedStreamOfType(plexstream.PlexStream.TYPE_SUBTITLE) else: util.WARN_LOG("Media does not contain a valid part") util.LOG("Choice media: {0} part:{1}".format(media, partIndex)) for streamType in ("videoStream", "audioStream", "subtitleStream"): attr = getattr(self, streamType) if attr: util.LOG("Choice {0}: {1}".format(streamType, repr(attr))) else: util.WARN_LOG("Could not create media choice for invalid media")
def getServerDecision(self): directPlay = not (self.metadata and self.metadata.isTranscoded) decisionPath = self.getDecisionPath(directPlay) newDecision = None if decisionPath: server = self.metadata.transcodeServer or self.item.getServer() request = plexrequest.PlexRequest(server, decisionPath) response = request.getWithTimeout(10) if response.isSuccess() and response.container: decision = serverdecision.ServerDecision(self, response, self) if decision.isSuccess(): util.LOG("MDE: Server was happy with client's original decision. {0}".format(decision)) elif decision.isDecision(True): util.WARN_LOG("MDE: Server was unhappy with client's original decision. {0}".format(decision)) return decision.getDecision() else: util.LOG("MDE: Server was unbiased about the decision. {0}".format(decision)) # Check if the server has provided a new media item to use it. If # there is no item, then we'll continue along as if there was no # decision made. newDecision = decision.getDecision(False) else: util.WARN_LOG("MDE: Server failed to provide a decision") else: util.WARN_LOG("MDE: Server or item does not support decisions") return newDecision or self
def findResourceByID(resources, ID): """ Searches server.clientIdentifier """ util.LOG('Looking for server by ID: {0}'.format(ID)) for server in resources: if ID == server.clientIdentifier: util.LOG('Server found by ID: {0}'.format(server)) return server util.LOG('Unable to find server by ID: {0}'.format(ID)) raise exceptions.NotFound('Unable to find server by ID: {0}'.format(ID))
def findResource(resources, search, port=32400): """ Searches server.name """ search = search.lower() util.LOG('Looking for server: {0}'.format(search)) for server in resources: if search == server.name.lower(): util.LOG('Server found: {0}'.format(server)) return server util.LOG('Unable to find server: {0}'.format(search)) raise exceptions.NotFound('Unable to find server: {0}'.format(search))
def start(): util.LOG('[- START -----------------------] [{0}]'.format( util.ADDON.getAddonInfo('version'))) util.setGlobalProperty('guide.filter', '') util.setGlobalProperty('section', '') with util.Cron(interval=5): bw = windows.BackgroundWindow.create() connected = False ID = util.loadTabloDeviceID() if ID: tablo.API.discover() connected = tablo.API.selectDevice(ID) while True: if not connected: if connected is None: w = windows.ConnectWindow.open(updating=True) del w connected = False if ID: tablo.API.discover() connected = tablo.API.selectDevice(ID) continue else: w = windows.ConnectWindow.open() if w.exit or not tablo.API.deviceSelected(): return del w if tablo.API.getUpdateStatus(): util.DEBUG_LOG('Updating ({0})'.format(tablo.API.device.name)) connected = None continue windows.WM.start() if windows.WM.exit: break connected = False bw.show() bw.setProperty('busy', '1') backgroundthread.BGThreader.shutdown() bw.doClose() del bw util.LOG('[- END -------------------------]')
def logState(self): util.LOG("Authenticated as {0}:{1}".format(self.ID, repr(self.title))) util.LOG("SignedIn: {0}".format(self.isSignedIn)) util.LOG("Offline: {0}".format(self.isOffline)) util.LOG("Authenticated: {0}".format(self.isAuthenticated)) util.LOG("PlexPass: {0}".format(self.isPlexPass)) util.LOG("Managed: {0}".format(self.isManaged)) util.LOG("Protected: {0}".format(self.isProtected)) util.LOG("Admin: {0}".format(self.isAdmin)) util.LOG("AdminPlexPass: {0}".format(self.adminHasPlexPass))
def checkSelectedServerSearch(self): if not self.selectedServer and self.searchContext: # If we're still waiting on the resources response then there's no # reason to settle, so don't even iterate over our servers. if self.searchContext.waitingForResources: util.DEBUG_LOG("Still waiting for plex.tv resources") return waitingForPreferred = False waitingForOwned = False waitingForAnything = False waitingToTestAll = bool(self.deferReachabilityTimer) # Iterate over all our servers and see if we're waiting on any results servers = self.getServers() pendingCount = 0 for server in servers: if server.pendingReachabilityRequests > 0: pendingCount = pendingCount + server.pendingReachabilityRequests if server.uuid == self.searchContext.preferredServer: waitingForPreferred = True elif server.owned: waitingForOwned = True else: waitingForAnything = True pendingString = "{0} pending reachability tests".format( pendingCount) if waitingForPreferred: util.LOG("Still waiting for preferred server: " + pendingString) elif waitingForOwned and (not self.searchContext.bestServer or not self.searchContext.bestServer.owned): util.LOG("Still waiting for an owned server: " + pendingString) elif waitingForAnything and not self.searchContext.bestServer: util.LOG( "Still waiting for any server: {0}".format(pendingString)) elif waitingToTestAll: util.LOG( "Preferred server not reachable, testing all servers now") self.updateReachability(True, False, False) else: # No hope for anything better, let's select what we found util.LOG("Settling for the best server we found") self.setSelectedServer( self.searchContext.bestServer or self.searchContext.fallbackServer, True)
def removeServer(self, server): del self.serversByUuid[server.uuid] self.trigger('remove:server') if server == self.selectedServer: util.LOG("The selected server went away") self.setSelectedServer(None, force=True) if server == self.transcodeServer: util.LOG("The selected transcode server went away") self.transcodeServer = None if server == self.channelServer: util.LOG("The selected channel server went away") self.channelServer = None
def chooseMedia(self, item, forceUpdate=False): # If we've already evaluated this item, use our previous choice. if not forceUpdate and item.mediaChoice is not None and item.mediaChoice.media is not None and not item.mediaChoice.media.isIndirect( ): return item.mediaChoice # See if we're missing media/stream details for this item. if item.isLibraryItem() and item.isVideoItem() and len( item.media) > 0 and not item.media[0].hasStreams(): # TODO(schuyler): Fetch the details util.WARN_LOG("Can't make media choice, missing details") # Take a first pass through the media items to create an array of candidates # that we'll evaluate more completely. If we find a forced item, we use it. # If we find an indirect, we only keep a single candidate. indirect = False candidates = [] maxResolution = item.settings.getMaxResolution(item.getQualityType()) for mediaIndex in range(len(item.media)): media = item.media[mediaIndex] media.mediaIndex = mediaIndex if media.isSelected(): candidates = [] candidates.append(media) break if media.isIndirect(): # Only add indirect media if the resolution fits. We cannot # exit early as the user may have selected media. indirect = True if media.getVideoResolution() <= maxResolution: candidates.append(media) elif media.isAccessible(): # Only consider testing available media candidates.append(media) # Only use the first indirect media item if indirect and candidates: candidates = candidates[0] # Make sure we have at least one valid item, regardless of availability if len(candidates) == 0: candidates.append(item.media[0]) # Now that we have an array of candidates, evaluate them completely. choices = [] for media in candidates: choice = None if media is not None: if item.isVideoItem(): choice = self.evaluateMediaVideo(item, media) elif item.isMusicItem(): choice = self.evaluateMediaMusic(item, media) else: choice = mediachoice.MediaChoice(media) choices.append(choice) item.mediaChoice = self.sortChoices(choices)[-1] util.LOG("MDE: MediaChoice: {0}".format(item.mediaChoice)) return item.mediaChoice
def getItemsFromString(dstring): try: data = json.loads(dstring) return [Item.fromDict(ddict) for ddict in data['items']] except ValueError: if dstring and dstring.startswith('{'): util.LOG(repr(dstring[:100])) util.ERROR() else: try: return getItemsFromXMLString(dstring) except: util.LOG(repr(dstring[:100])) util.ERROR() return None
def rebuild(self, item, decision=None): # item.settings = self.item.settings oldChoice = self.choice self.init(item, True) util.LOG("Replacing '{0}' with '{1}' and rebuilding.".format(oldChoice, self.choice)) self.build() self.decision = decision
def setSelectedServer(self, server, force=False): # Don't do anything if the server is already selected. if self.selectedServer and self.selectedServer == server: return False if server: # Don't select servers that don't have connections. if not server.activeConnection: return False # Don't select servers that are not supported if not server.isSupported: return False if not self.selectedServer or force: util.LOG("Setting selected server to {0}".format(server)) self.selectedServer = server # Update our saved state. self.saveState() # Notify anyone who might care. plexapp.APP.trigger("change:selectedServer", server=server) return True return False
def updateHomeUsers(self): # Ignore request and clear any home users we are not signed in if not self.isSignedIn: self.homeUsers = [] if self.isOffline: self.homeUsers.append(MyPlexAccount()) self.lastHomeUserUpdate = None return # Cache home users for 60 seconds, mainly to stop back to back tests epoch = time.time() if not self.lastHomeUserUpdate: self.lastHomeUserUpdate = epoch elif self.lastHomeUserUpdate + 60 > epoch: util.DEBUG_LOG( "Skipping home user update (updated {0} seconds ago)".format( epoch - self.lastHomeUserUpdate)) return req = myplexrequest.MyPlexRequest("/api/home/users") xml = req.getToStringWithTimeout() data = ElementTree.fromstring(xml) if data.attrib.get('size') and data.find('User') is not None: self.homeUsers = [] for user in data.findall('User'): homeUser = HomeUser(user.attrib) homeUser.isAdmin = homeUser.admin == "1" homeUser.isManaged = homeUser.restricted == "1" homeUser.isProtected = homeUser.protected == "1" self.homeUsers.append(homeUser) self.lastHomeUserUpdate = epoch util.LOG("home users: {0}".format(self.homeUsers))
def updateReachability(self, force=True, allowFallback=False): if not force and self.activeConnection and self.activeConnection.state != plexresource.ResourceConnection.STATE_UNKNOWN: return util.LOG('Updating reachability for {0}: conns={1}, allowFallback={2}'. format(repr(self.name), len(self.connections), allowFallback)) epoch = time.time() retrySeconds = 60 minSeconds = 10 for i in range(len(self.connections)): conn = self.connections[i] diff = epoch - (conn.lastTestedAt or 0) if conn.hasPendingRequest: util.DEBUG_LOG( "Skip reachability test for {0} (has pending request)". format(conn)) elif diff < minSeconds or (not self.isSecondary() and self.isReachable() and diff < retrySeconds): util.DEBUG_LOG( "Skip reachability test for {0} (checked {1} secs ago)". format(conn, diff)) elif conn.testReachability(self, allowFallback): self.pendingReachabilityRequests += 1 if conn.isSecure: self.pendingSecureRequests += 1 if self.pendingReachabilityRequests == 1: self.trigger("started:reachability") if self.pendingReachabilityRequests <= 0: self.trigger("completed:reachability")
def query(self, path, method=None, **kwargs): method = method or self.session.get url = self.buildUrl(path, includeToken=True) # If URL is empty, try refresh resources and return empty set for now if not url: util.WARN_LOG( "Empty server url, returning None and refreshing resources") plexapp.refreshResources(True) return None util.LOG('{0} {1}'.format( method.__name__.upper(), re.sub('X-Plex-Token=[^&]+', 'X-Plex-Token=****', url))) try: response = method(url, **kwargs) if response.status_code not in (200, 201): codename = http.status_codes.get(response.status_code, ['Unknown'])[0] raise exceptions.BadRequest('({0}) {1}'.format( response.status_code, codename)) data = response.text.encode('utf8') except asyncadapter.TimeoutException: util.ERROR() plexapp.refreshResources(True) return None except http.requests.ConnectionError: util.ERROR() return None return ElementTree.fromstring(data) if data else None
def deleteRule(self, ep=None): if not self.rule and not ep: util.LOG('RecordDialog.deleteRule(): No rule to modify') return if self.parent: if ep: self.parent.deleteRule(self.series, ep=ep) else: self.parent.deleteRule(self.rule) else: if ep: self.storageServer.deleteRule(self.series, ep=ep) else: self.storageServer.deleteRule(self.rule) self.series['RecordingRule'] = 0 if not ep: self.setProperty('show.hasRule', '') self.fillEpisodeList() self.series['RecordingRule'] = any([e.hasRule for e in self.episodes]) self.showHideButton() if self.dialogSource == 'RULES': self.doClose()
def refreshManualConnections(self): manualConnections = self.getManualConnections() if not manualConnections: return util.LOG("Refreshing {0} manual connections".format( len(manualConnections))) for conn in manualConnections: # Default to http, as the server will need to be signed in for https to work, # so the client should too. We'd also have to allow hostname entry, instead of # IP address for the cert to validate. proto = "http" port = conn.port or "32400" serverAddress = "{0}://{1}:{2}".format(proto, conn.connection, port) request = http.HttpRequest(serverAddress + "/identity") context = request.createRequestContext( "manual_connections", callback.Callable(self.onManualConnectionsResponse)) context.serverAddress = serverAddress context.address = conn.connection context.proto = proto context.port = port context.timeout = 10000 plexapp.APP.startRequest(request, context)
def dl_restore(): try: if not os.path.exists("/storage/backup"): os.makedirs("/storage/backup") SettingsBackup.backupAll() if not backupFreeSpace() >= 500: util.LOG('DELETING RECORDINGS') deleteRecordings() downloadWithProgress(RESTORE_URL, BACKUP_PATH, 'Downloading restore file...') # meheh. not an error show_error("Downloaded. Click OK to restore.") restore() return except DownloadCanceledException: show_error('Canceled') except: util.ERROR() show_error("Error") #We only get here on error if os.path.exists(BACKUP_PATH): os.remove(BACKUP_PATH) if os.path.exists(oscamBackupFile): os.remove(oscamBackupFile)
def getTranscodeServer(self, transcodeType=None): if not self.selectedServer: return None transcodeMap = { 'audio': "supportsAudioTranscoding", 'video': "supportsVideoTranscoding", 'photo': "supportsPhotoTranscoding" } transcodeSupport = transcodeMap[transcodeType] # Try to use a better transcoding server for synced or secondary servers if self.selectedServer.synced or self.selectedServer.isSecondary(): if self.transcodeServer and self.transcodeServer.isReachable(): return self.transcodeServer self.transcodeServer = None for server in self.getServers(): if not server.synced and server.isReachable( ) and self.compareServers(self.transcodeServer, server) < 0: if not transcodeSupport or server.transcodeSupport: self.transcodeServer = server if self.transcodeServer: transcodeTypeString = transcodeType or '' util.LOG( "Found a better {0} transcode server than {1}, using: {2}". format(transcodeTypeString, self.selectedserver, self.transcodeServer)) return self.transcodeServer return self.selectedServer
def getPostWithTimeout(self, seconds=10, body=None): if self._cancel: return self.logRequest(body, seconds, False) try: if self.method == 'PUT': res = self.session.put(self.url, timeout=seconds, stream=True) elif self.method == 'DELETE': res = self.session.delete(self.url, timeout=seconds, stream=True) elif self.method == 'HEAD': res = self.session.head(self.url, timeout=seconds, stream=True) elif self.method == 'POST' or body is not None: res = self.session.post(self.url, data=body, timeout=seconds, stream=True) else: res = self.session.get(self.url, timeout=seconds, stream=True) self.currentResponse = res if self._cancel: return None util.LOG("Got a {0} from {1}".format(res.status_code, util.cleanToken(self.url))) # self.event = msg return res except Exception, e: util.WARN_LOG( "Request to {0} errored out after {1} ms: {2}".format( self.url, seconds, e.message))
def testReachability(self, server, allowFallback=False): # Check if we will allow the connection test. If this is a fallback connection, # then we will defer it until we "allowFallback" (test insecure connections # after secure tests have completed and failed). Insecure connections will be # tested if the policy "always" allows them, or if set to "same_network" and # the current connection is local and server has (publicAddressMatches=1). allowConnectionTest = not self.isFallback if not allowConnectionTest: insecurePolicy = plexapp.INTERFACE.getPreference("allow_insecure") if insecurePolicy == "always" or (insecurePolicy == "same_network" and server.sameNetwork and self.isLocal): allowConnectionTest = allowFallback server.hasFallback = not allowConnectionTest util.LOG('{0} for {1}'.format( allowConnectionTest and "Continuing with insecure connection testing" or "Insecure connection testing is deferred", server)) else: util.LOG( "Insecure connections not allowed. Ignore insecure connection test for {0}" .format(server)) self.state = self.STATE_INSECURE callable = callback.Callable(server.onReachabilityResult, [self], random.randint(0, 256)) callable.deferCall() return True if allowConnectionTest: if not self.isSecure and ( not allowFallback and server.hasSecureConnections() or server.activeConnection and server.activeConnection.state != self.STATE_REACHABLE and server.activeConnection.isSecure): util.DEBUG_LOG("Invalid insecure connection test in progress") self.request = http.HttpRequest(self.buildUrl(server, "/")) context = self.request.createRequestContext( "reachability", callback.Callable(self.onReachabilityResponse)) context.server = server context.timeout = 10000 util.addPlexHeaders(self.request, server.getToken()) self.hasPendingRequest = plexapp.APP.startRequest( self.request, context) return True return False
def collectDataFromRoot(self, data): # Make sure we're processing data for our server, and not some other # server that happened to be at the same IP. if self.uuid != data.attrib.get('machineIdentifier'): util.LOG( "Got a reachability response, but from a different server") return False self.serverClass = data.attrib.get('serverClass') self.supportsAudioTranscoding = data.attrib.get( 'transcoderAudio') == '1' self.supportsVideoTranscoding = data.attrib.get( 'transcoderVideo') == '1' or data.attrib.get( 'transcoderVideoQualities') self.supportsVideoRemuxOnly = data.attrib.get( 'transcoderVideoRemuxOnly') == '1' self.supportsPhotoTranscoding = data.attrib.get( 'transcoderPhoto') == '1' or ( not data.attrib.get('transcoderPhoto') and not self.synced and not self.isSecondary()) self.allowChannelAccess = data.attrib.get( 'allowChannelAccess') == '1' or ( not data.attrib.get('allowChannelAccess') and self.owned and not self.synced and not self.isSecondary()) self.supportsScrobble = not self.isSecondary() or self.synced self.allowsMediaDeletion = not self.synced and self.owned and data.attrib.get( 'allowMediaDeletion') == '1' self.multiuser = data.attrib.get('multiuser') == '1' self.name = data.attrib.get('friendlyName') or self.name self.platform = data.attrib.get('platform') # TODO(schuyler): Process transcoder qualities self.rawVersion = data.attrib.get('version') if self.rawVersion: self.versionNorm = util.normalizedVersion(self.rawVersion) features = { 'mkvTranscode': '0.9.11.11', 'themeTranscode': '0.9.14.0', 'allPartsStreamSelection': '0.9.12.5', 'claimServer': '0.9.14.2', 'streamingBrain': '1.2.0' } for f, v in features.items(): if verlib.suggest_normalized_version(v) <= self.versionNorm: self.features[f] = True appMinVer = plexapp.INTERFACE.getGlobal('minServerVersionArr', '0.0.0.0') self.isSupported = self.isSecondary( ) or verlib.suggest_normalized_version(appMinVer) <= self.versionNorm util.DEBUG_LOG( "Server information updated from reachability check: {0}".format( self)) return True
def fetchResources(token): headers = util.BASE_HEADERS.copy() headers['X-Plex-Token'] = token util.LOG('GET {0}?X-Plex-Token={1}'.format(RESOURCES, util.hideToken(token))) response = http.GET(RESOURCES) data = ElementTree.fromstring(response.text.encode('utf8')) import plexserver return [plexserver.PlexServer(elem) for elem in data]
def evaluateMediaMusic(self, item, media): # Resolve indirects before doing anything else. if media.isIndirect(): util.LOG("Resolve indirect media for {0}".format(item)) media = media.resolveIndirect() choice = mediachoice.MediaChoice(media) if media is None: return choice # Verify the server supports audio transcoding, otherwise force direct play if not item.getServer().supportsAudioTranscoding: util.LOG( "MDE: force direct play because the server does not support audio transcoding" ) choice.isDirectPlayable = True return choice # See if this part has a server decision to transcode and obey it if choice.part and choice.part.get( "decision", serverdecision.ServerDecision.DECISION_DIRECT_PLAY ) != serverdecision.ServerDecision.DECISION_DIRECT_PLAY: util.WARN_LOG("MDE: Server has decided this cannot direct play") return choice # Verify the codec and container are compatible codec = media.audioCodec container = media.get('container') canPlayCodec = item.settings.supportsAudioStream( codec, media.audioChannels.asInt()) canPlayContainer = ( codec == container) or True # (container in ("mp4", "mka", "mkv")) choice.isDirectPlayable = (canPlayCodec and canPlayContainer) if choice.isDirectPlayable: # Inspect the audio stream attributes if the codec/container can direct # play. For now we only need to verify the sample rate. if choice.audioStream is not None and choice.audioStream.samplingRate.asInt( ) >= 192000: util.LOG("MDE: sampling rate is not compatible") choice.isDirectPlayable = False else: util.LOG("MDE: container or codec is incompatible") return choice
def __getattr__(self, attr): a = PlexValue('', self) a.NA = True try: setattr(self, attr, a) except AttributeError: util.LOG('Failed to set attribute: {0} ({1})'.format(attr, self.__class__)) return a
def updateCore(force=False): if not force: return import xbmc import os, urllib, urllib2 import tarfile util.LOG('Checking for new youtube_dl core version...') currentVersion = util.getSetting('core_version') try: newVersion = urllib2.urlopen(VERSION_URL).read().strip() if currentVersion == newVersion: util.LOG('Core version up to date') return False except: util.ERROR() return False util.LOG('Updating youtube_dl core to new version: {0}'.format(newVersion)) profile = xbmc.translatePath( util.ADDON.getAddonInfo('profile')).decode('utf-8') archivePath = os.path.join(profile, 'youtube_dl.tar.gz') extractedPath = os.path.join(profile, 'youtube-dl') try: if os.path.exists(extractedPath): import shutil shutil.rmtree(extractedPath, ignore_errors=True) util.LOG('Old version removed') urllib.urlretrieve(LATEST_URL, filename=archivePath) with tarfile.open(archivePath, mode='r:gz') as tf: members = [ m for m in tf.getmembers() if m.name.startswith('youtube-dl/youtube_dl') ] #get just the files from the youtube_dl source directory tf.extractall(path=profile, members=members) except: util.ERROR('Core update FAILED') util.LOG('Core update complete') return True
def discoveryFinished(self, *args, **kwargs): # Time's up, report whatever we found self.close() if self.servers: util.LOG("Finished GDM discovery, found {0} server(s)".format( len(self.servers))) import plexapp plexapp.SERVERMANAGER.updateFromConnectionType( self.servers, plexconnection.PlexConnection.SOURCE_DISCOVERED) self.servers = None
def migrateDB(DB, version): util.LOG('Migrating database from version {0} to {1}'.format( version, DATABASE_VERSION)) from peewee.playhouse import migrate migrator = migrate.SqliteMigrator(DB) migratorW = migrate.SqliteMigrator(W_DB) if version < 1: try: migrate.migrate( migrator.add_column('RatingsBumpers', 'style', peewee.CharField(default='Classic'))) except peewee.OperationalError: util.MINOR_ERROR('Migration (RatingsBumpers: Add style column)') except: util.ERROR() return False if version < 2: try: migrate.migrate( migrator.add_column('RatingSystem', 'regions', peewee.CharField(null=True)), migrator.drop_not_null('RatingSystem', 'context'), ) except peewee.OperationalError: util.MINOR_ERROR('Migration (RatingSystem: Add region column)') except: util.ERROR() return False if version < 5: try: migrate.migrate( migratorW.add_column('Trailers', 'is3D', peewee.BooleanField(default=False)), ) except peewee.OperationalError: util.MINOR_ERROR('Migration (Trailers: Add is3D column)') except: util.ERROR() return False if version < 6: try: migrate.migrate( migratorW.add_column('Trailers', 'verified', peewee.BooleanField(default=True)), ) except peewee.OperationalError: util.MINOR_ERROR('Migration (Trailers: Add verified column)') except: util.ERROR() return False return True