def _syncEpgIds(self): conn = DBConnection() # By not including inactive channels, we automatically delete epgIds that # are currently not active uniqueEpgIds = Channel.getUniqueEpgIdsFromDb(conn, includeRadio=True) conn.delayCommit(True) # Get epgids from database (contains channels per epg_id and strategy) epgIds = EpgId.getAllFromDb(conn, includeRadio=True) epgIdsDict = {epgId.epgId: epgId for epgId in epgIds} currentEpgIds = epgIdsDict.keys() for epgId in epgIds: if epgId.epgId not in uniqueEpgIds: epgId.deleteFromDb(conn) self._logger.info("_syncEpgIds: removing epgId=%s" % (epgId.epgId)) newEpgIds = set(uniqueEpgIds).difference(set(currentEpgIds)) self._logger.info("_syncEpgIds: newEpgIds=%r" % (newEpgIds)) for newEpgId in newEpgIds: epgId = EpgId(newEpgId, "none") epgId.addToDb(conn) self._logger.info("_syncEpgIds: adding epgId=%s" % (epgId.epgId)) conn.delayCommit(False)
def _syncEpgIds( self ): conn = DBConnection() # By not including inactive channels, we automatically delete epgIds that # are currently not active uniqueEpgIds = Channel.getUniqueEpgIdsFromDb( conn, includeRadio=True ) conn.delayCommit( True ) # Get epgids from database (contains channels per epg_id and strategy) epgIds = EpgId.getAllFromDb( conn, includeRadio=True ) epgIdsDict = { epgId.epgId: epgId for epgId in epgIds } currentEpgIds = epgIdsDict.keys() for epgId in epgIds: if epgId.epgId not in uniqueEpgIds: epgId.deleteFromDb( conn ) self._logger.info( "_syncEpgIds: removing epgId=%s" % ( epgId.epgId ) ) newEpgIds = set( uniqueEpgIds ).difference( set( currentEpgIds ) ) self._logger.info( "_syncEpgIds: newEpgIds=%r" % ( newEpgIds ) ) for newEpgId in newEpgIds: epgId = EpgId( newEpgId, "none" ) epgId.addToDb( conn ) self._logger.info( "_syncEpgIds: adding epgId=%s" % ( epgId.epgId ) ) conn.delayCommit( False )
def setChannelList( self, channelList ): self._logger.debug( "setChannelList( %s )" % ( channelList ) ) try: channels = json.loads( channelList ) conn = DBConnection() conn.delayCommit( True ) newChannelNumbers = [] for channel in channels: channelId = -1 channelOld = PendingChannel.getByNumberFromDb( conn, channel["id"] ) if channelOld: channelId = channelOld.id channelNew = self._getChannelFromJson( channel, channelId ) newChannelNumbers.append( channelNew.number ) self._logger.debug( "setChannelList: processing channel: %s" % ( channelNew.dump() ) ) if not channelNew: self._logger.error( "setChannelList: unable to create channel for channel=%s", ( channel ) ) elif not channelOld: self._logger.info( "setChannelList: adding channel: %i - %s" % ( channelNew.number, channelNew.name ) ) channelNew.addToDb( conn ) elif channelOld != channelNew: self._logger.info( "setChannelList: updating channel: %i - %s" % ( channelNew.number, channelNew.name ) ) channelNew.addToDb( conn ) else: self._logger.debug( "setChannelList: same channel: %i - %s" % ( channelNew.number, channelNew.name ) ) currentChannels = PendingChannel.getAllFromDb( conn, includeRadio=True, tv=True ) currentChannelNumbers = [ channel.number for channel in currentChannels ] removedChannelNumbers = set( currentChannelNumbers ).difference( set( newChannelNumbers ) ) for number in removedChannelNumbers: channel = PendingChannel.getByNumberFromDb( conn, number ) if channel: self._logger.info( "setChannelList: remove channel: %i - %s" % ( channel.number, channel.name ) ) channel.deleteFromDb( conn ) return self._createResponse( API.STATUS_SUCCESS, { "numChannels": len( channels ) } ) except: self._logger.exception( "setChannelList: exception: channelList=%s" % ( channelList ) ) return self._createResponse( API.STATUS_FAIL, { "numChannels": 0 } )
if len(currChannels) > 0: logger.warning( "Channels found, but no Url match for chanId=%i, epgId=%s" % (mythTvChannel.chanId, epgId)) mythTvChannelMap[ mythTvChannel.chanId] = currChannels[0] mythTvChannelUrlTypeMap[ mythTvChannel.chanId] = "sd" for channel in currChannels: logger.info("Channel: %s" % (channel.dump())) else: logger.warning( "No channels found for chanId=%i, epgId=%s" % (mythTvChannel.chanId, epgId)) conn.delayCommit(True) # Convert MythTV records (schedule entries) to AminoPVR schedules for record in mythTvRecords: # If the channel is not in the channel map (yet), it does not exist # in the AminoPVR database. # If there is enough information on MythTV side, create an inactive # channel. if record.chanId != 0 and record.chanId not in mythTvChannelMap: channel, urlType = _addChannel(record.chanId, mythTvChannelsDict, mythTvIptvChannelsDict, dryRun) if channel: logger.warning("Adding Channel: %s" % (channel.dump()))
def _grabEpgForChannel( self, channel=None, epgId=None ): conn = DBConnection() if channel: epgId = EpgId.getFromDb( conn, channel.epgId ) self._logger.info( "Grabbing EPG for channel: %s (%s; method: %s)" % ( channel.name, channel.epgId, epgId.strategy ) ) if not epgId: return else: self._logger.info( "Grabbing EPG for epgId: %s (method: %s)" % ( epgId.epgId, epgId.strategy ) ) # Check if _fail_# is behind strategy # This is to indicate epg grabbing for this epgId failed previously strategy = epgId.strategy strategyRe = re.compile( r'_fail_(?P<fail>\d+)' ) failMatch = strategyRe.search( strategy ) failCount = 0 if failMatch: failCount = int( failMatch.group( "fail" ) ) strategy = epgId.strategy.split( '_' )[0] # We're going to attempt to grab EPG information for this channel 5 times # before we stop grabbing this epgId in the future. if failCount < 5: now = time.localtime() nowDay = datetime.datetime( now[0], now[1], now[2] ) daysDetailDelta = datetime.timedelta( days = 3 ) epgFilename = "/%s.json.gz" % ( epgId.epgId ) epgUrl = self._glashartConfig.epgChannelsPath + epgFilename currentPrograms = EpgProgram.getAllByEpgIdFromDb( conn, epgId.epgId ) currentProgramsDict = { currProgram.originalId: currProgram for currProgram in currentPrograms } newProgramsDict = {} content, _, _ = getPage( epgUrl ) if content: fileHandle = gzip.GzipFile( fileobj=StringIO( content ) ) epgData = json.loads( fileHandle.read() ) # If strategy has changed (working after (a few) failed attempts) if epgId.strategy != strategy: epgId.strategy = strategy epgId.addToDb( conn ) numPrograms = 0 numProgramsDetail = 0 numProgramsDetailFailed = 0 numProgramsNew = 0 numProgramsUpdated = 0 for program in epgData: if not self._running: break numPrograms += 1 programNew = self._getProgramFromJson( epgId.epgId, program ) if programNew.originalId in newProgramsDict: self._logger.warning( "Program with originalId %d already in newProgramsDict" % ( programNew.originalId ) ) newProgramsDict[programNew.originalId] = programNew updateDetailedData = True programOld = None if programNew.originalId in currentProgramsDict: programOld = currentProgramsDict[programNew.originalId] # If the old program has detailed info, copy those fields # TODO: do this somewhere else if programOld and programOld.detailed: programNew.subtitle = programOld.subtitle programNew.description = programOld.description programNew.aspectRatio = programOld.aspectRatio programNew.parentalRating = programOld.parentalRating programNew.genres = programOld.genres programNew.actors = programOld.actors programNew.directors = programOld.directors programNew.presenters = programOld.presenters programNew.ratings = programOld.ratings programNew.detailed = programOld.detailed # Now, compare the old program and the new program # Are they the same, then we don't need to download detailed information if programOld and programOld.detailed and programNew == programOld: programNew = programOld updateDetailedData = False if updateDetailedData: if ( ( epgId.strategy == "default" and (nowDay + daysDetailDelta) > datetime.datetime.fromtimestamp( programNew.startTime ) ) or ( epgId.strategy == "full" ) ): time.sleep( random.uniform( 0.5, 1.0 ) ) programNew, grabbed = self._grabDetailedEpgForProgram( programNew ) if grabbed: numProgramsDetail += 1 else: # if more than 10 detailed program information grabs failed, set strategy to none. numProgramsDetailFailed += 1 if numProgramsDetailFailed == 10: self._logger.error( "Couldn't download at least 10 detailed program information files, so setting strategy to 'none', but do not store" ) epgId.strategy = "none" conn.delayCommit( True ) for programId in newProgramsDict: programNew = newProgramsDict[programId] programOld = None if programNew.originalId in currentProgramsDict: programOld = currentProgramsDict[programNew.originalId] if not programOld or programNew != programOld: if programOld: self._logger.debug( "Updated program: id = %s" % ( programNew.originalId ) ) self._logger.debug( "Start time: %s > %s" % ( str( programOld.startTime ), str( programNew.startTime ) ) ) self._logger.debug( "End time: %s > %s" % ( str( programOld.endTime ), str( programNew.endTime ) ) ) self._logger.debug( "Name: %s > %s" % ( repr( programOld.title ), repr( programNew.title ) ) ) programNew.id = programOld.id numProgramsUpdated += 1 else: numProgramsNew += 1 try: programNew.addToDb( conn ) except: self._logger.exception( programNew.dump() ) conn.delayCommit( False ) if self._running: self._logger.debug( "Num programs: %i" % ( numPrograms ) ) self._logger.debug( "Num program details: %i" % ( numProgramsDetail ) ) self._logger.info( "Num new programs: %i" % ( numProgramsNew ) ) self._logger.info( "Num updated programs: %i" % ( numProgramsUpdated ) ) if numProgramsNew == 0: self._logger.warning( "No new programs were added for epgId: %s" % ( epgId.epgId ) ) else: self._logger.warning( "Unable to download EPG information for epgId: %s" % ( epgId.epgId ) ) failCount += 1 epgId.strategy = "%s_fail_%d" % ( strategy, failCount ) epgId.addToDb( conn ) else: self._logger.info( "Downloading of EPG information for epgId: %s skipped becaused it failed too many times" % ( epgId.epgId ) )
def _grabEpgForChannel(self, channel=None, epgId=None): conn = DBConnection() if channel: epgId = EpgId.getFromDb(conn, channel.epgId) self._logger.info("Grabbing EPG for channel: %s (%s; method: %s)" % (channel.name, channel.epgId, epgId.strategy)) if not epgId: return else: self._logger.info("Grabbing EPG for epgId: %s (method: %s)" % (epgId.epgId, epgId.strategy)) # Check if _fail_# is behind strategy # This is to indicate epg grabbing for this epgId failed previously strategy = epgId.strategy strategyRe = re.compile(r'_fail_(?P<fail>\d+)') failMatch = strategyRe.search(strategy) failCount = 0 if failMatch: failCount = int(failMatch.group("fail")) strategy = epgId.strategy.split('_')[0] # We're going to attempt to grab EPG information for this channel 5 times # before we stop grabbing this epgId in the future. if failCount < 5: now = time.localtime() nowDay = datetime.datetime(now[0], now[1], now[2]) daysDetailDelta = datetime.timedelta(days=3) epgFilename = "/%s.json.gz" % (epgId.epgId) epgUrl = self._glashartConfig.epgChannelsPath + epgFilename currentPrograms = EpgProgram.getAllByEpgIdFromDb(conn, epgId.epgId) currentProgramsDict = { currProgram.originalId: currProgram for currProgram in currentPrograms } newProgramsDict = {} content, _, _ = getPage(epgUrl) if content: fileHandle = gzip.GzipFile(fileobj=StringIO(content)) epgData = json.loads(fileHandle.read()) # If strategy has changed (working after (a few) failed attempts) if epgId.strategy != strategy: epgId.strategy = strategy epgId.addToDb(conn) numPrograms = 0 numProgramsDetail = 0 numProgramsDetailFailed = 0 numProgramsNew = 0 numProgramsUpdated = 0 for program in epgData: if not self._running: break numPrograms += 1 programNew = self._getProgramFromJson(epgId.epgId, program) if programNew.originalId in newProgramsDict: self._logger.warning( "Program with originalId %d already in newProgramsDict" % (programNew.originalId)) newProgramsDict[programNew.originalId] = programNew updateDetailedData = True programOld = None if programNew.originalId in currentProgramsDict: programOld = currentProgramsDict[programNew.originalId] # If the old program has detailed info, copy those fields # TODO: do this somewhere else if programOld and programOld.detailed: programNew.subtitle = programOld.subtitle programNew.description = programOld.description programNew.aspectRatio = programOld.aspectRatio programNew.parentalRating = programOld.parentalRating programNew.genres = programOld.genres programNew.actors = programOld.actors programNew.directors = programOld.directors programNew.presenters = programOld.presenters programNew.ratings = programOld.ratings programNew.detailed = programOld.detailed # Now, compare the old program and the new program # Are they the same, then we don't need to download detailed information if programOld and programOld.detailed and programNew == programOld: programNew = programOld updateDetailedData = False if updateDetailedData: if ((epgId.strategy == "default" and (nowDay + daysDetailDelta) > datetime.datetime.fromtimestamp( programNew.startTime)) or (epgId.strategy == "full")): time.sleep(random.uniform(0.5, 1.0)) programNew, grabbed = self._grabDetailedEpgForProgram( programNew) if grabbed: numProgramsDetail += 1 else: # if more than 10 detailed program information grabs failed, set strategy to none. numProgramsDetailFailed += 1 if numProgramsDetailFailed == 10: self._logger.error( "Couldn't download at least 10 detailed program information files, so setting strategy to 'none', but do not store" ) epgId.strategy = "none" conn.delayCommit(True) for programId in newProgramsDict: programNew = newProgramsDict[programId] programOld = None if programNew.originalId in currentProgramsDict: programOld = currentProgramsDict[programNew.originalId] if not programOld or programNew != programOld: if programOld: self._logger.debug("Updated program: id = %s" % (programNew.originalId)) self._logger.debug("Start time: %s > %s" % (str(programOld.startTime), str(programNew.startTime))) self._logger.debug("End time: %s > %s" % (str( programOld.endTime), str(programNew.endTime))) self._logger.debug("Name: %s > %s" % (repr( programOld.title), repr(programNew.title))) programNew.id = programOld.id numProgramsUpdated += 1 else: numProgramsNew += 1 try: programNew.addToDb(conn) except: self._logger.exception(programNew.dump()) conn.delayCommit(False) if self._running: self._logger.debug("Num programs: %i" % (numPrograms)) self._logger.debug("Num program details: %i" % (numProgramsDetail)) self._logger.info("Num new programs: %i" % (numProgramsNew)) self._logger.info("Num updated programs: %i" % (numProgramsUpdated)) if numProgramsNew == 0: self._logger.warning( "No new programs were added for epgId: %s" % (epgId.epgId)) else: self._logger.warning( "Unable to download EPG information for epgId: %s" % (epgId.epgId)) failCount += 1 epgId.strategy = "%s_fail_%d" % (strategy, failCount) epgId.addToDb(conn) else: self._logger.info( "Downloading of EPG information for epgId: %s skipped becaused it failed too many times" % (epgId.epgId))
def setChannelList(self, channelList): self._logger.debug("setChannelList( %s )" % (channelList)) try: channels = json.loads(channelList) conn = DBConnection() conn.delayCommit(True) newChannelNumbers = [] for channel in channels: channelId = -1 channelOld = PendingChannel.getByNumberFromDb( conn, channel["id"]) if channelOld: channelId = channelOld.id channelNew = self._getChannelFromJson(channel, channelId) newChannelNumbers.append(channelNew.number) self._logger.debug("setChannelList: processing channel: %s" % (channelNew.dump())) if not channelNew: self._logger.error( "setChannelList: unable to create channel for channel=%s", (channel)) elif not channelOld: self._logger.info( "setChannelList: adding channel: %i - %s" % (channelNew.number, channelNew.name)) channelNew.addToDb(conn) elif channelOld != channelNew: self._logger.info( "setChannelList: updating channel: %i - %s" % (channelNew.number, channelNew.name)) channelNew.addToDb(conn) else: self._logger.debug( "setChannelList: same channel: %i - %s" % (channelNew.number, channelNew.name)) currentChannels = PendingChannel.getAllFromDb(conn, includeRadio=True, tv=True) currentChannelNumbers = [ channel.number for channel in currentChannels ] removedChannelNumbers = set(currentChannelNumbers).difference( set(newChannelNumbers)) for number in removedChannelNumbers: channel = PendingChannel.getByNumberFromDb(conn, number) if channel: self._logger.info( "setChannelList: remove channel: %i - %s" % (channel.number, channel.name)) channel.deleteFromDb(conn) return self._createResponse(API.STATUS_SUCCESS, {"numChannels": len(channels)}) except: self._logger.exception( "setChannelList: exception: channelList=%s" % (channelList)) return self._createResponse(API.STATUS_FAIL, {"numChannels": 0})
def activatePendingChannels(self): self._logger.debug("activatePendingChannels()") conn = DBConnection() pendingChannels = PendingChannel.getAllFromDb(conn, includeInactive=True, includeRadio=True, tv=True) pendingChannelNumbers = [channel.number for channel in pendingChannels] conn.delayCommit(True) for channel in pendingChannels: currChannel = Channel.getByNumberFromDb(conn, channel.number) if currChannel and currChannel.epgId != channel.epgId: # Found a channel on the same channel number, but epgId is different # Find another match. self._logger.info( "activatePendingChannels: epgId mismatch for channel %i - %s: %s != %s" % (channel.number, channel.name, channel.epgId, currChannel.epgId)) # If channel name is the same (or partially the same), then they must have changed epgId # Else, try to find a channel that would match if (channel.name != currChannel.name) and \ (not channel.name in currChannel.name) and \ (not currChannel.name in channel.name): currChannel = None epgIdChannels = Channel.getAllByEpgIdFromDb( conn, channel.epgId, includeInactive=True, includeRadio=True) for epgIdChannel in epgIdChannels: if (epgIdChannel.name == channel.name) or \ (channel.name in epgIdChannel.name) or \ (epgIdChannel.name in channel.name): currChannel = epgIdChannel break # TODO: if still no match is found (based on epgId), then look for similar names # and maybe equal urls if currChannel: # Convert PendingChannel to Channel but keep channel id newCurrChannel = Channel.copy(channel, currChannel.id) # Keep the scrambled setting from ChannelUrl's currently in the Db. # This setting cannot be retrieved from the source for key in currChannel.urls.keys(): if newCurrChannel.urls.has_key(key): newCurrChannel.urls[key].scrambled = currChannel.urls[ key].scrambled # Has the channel really changed? if newCurrChannel != currChannel: self._logger.info( "activatePendingChannels: existing channel: %i - %s" % (channel.number, channel.name)) # Hmm, channel number and name are the same, but epgId is different if newCurrChannel.epgId != currChannel.epgId: self._logger.info( "activatePendingChannels: epgId has changed: %s > %s" % (currChannel.epgId, newCurrChannel.epgId)) # Make sure the changed channel is activated (again) newCurrChannel.inactive = False if currChannel.logo != "" and os.path.basename( newCurrChannel.logo) != os.path.basename( currChannel.logo): currChannel.removeLogo(conn) if currChannel.thumbnail != "" and os.path.basename( newCurrChannel.thumbnail) != os.path.basename( currChannel.thumbnail): currChannel.removeThumbnail(conn) # Download the logo and thumbnail for this channel newCurrChannel.downloadLogoAndThumbnail() newCurrChannel.addToDb(conn) else: self._logger.info( "activatePendingChannels: new channel: %i - %s" % (channel.number, channel.name)) newChannel = Channel.copy(channel) newChannel.downloadLogoAndThumbnail() newChannel.addToDb(conn) currentChannels = Channel.getAllFromDb(conn, includeInactive=True, includeRadio=True, tv=True) currentChannelNumbers = [channel.number for channel in currentChannels] removedChannelNumbers = set(currentChannelNumbers).difference( set(pendingChannelNumbers)) self._logger.info( "activatePendingChannels: %i, %i, %i" % (len(set(currentChannelNumbers)), len( set(pendingChannelNumbers)), len(removedChannelNumbers))) for number in removedChannelNumbers: currChannel = Channel.getByNumberFromDb(conn, number) if not currChannel.inactive: self._logger.info( "activatePendingChannels: inactive channel: %i - %s" % (currChannel.number, currChannel.name)) currChannel.inactive = True currChannel.addToDb(conn) conn.delayCommit(False) channels = Channel.getAllFromDb(conn, includeRadio=True, tv=True) channelsArray = [] for channel in channels: channelJson = channel.toDict(InputStreamProtocol.HTTP, includeScrambled=False, includeHd=True) if channelJson: channelsArray.append(channelJson) return self._createResponse(API.STATUS_SUCCESS, channelsArray)
mythTvChannelMap[mythTvChannel.chanId] = channel mythTvChannelUrlTypeMap[mythTvChannel.chanId] = urlType break # We didn't find a match if mythTvChannel.chanId not in mythTvChannelMap: if len( currChannels ) > 0: logger.warning( "Channels found, but no Url match for chanId=%i, epgId=%s" % ( mythTvChannel.chanId, epgId ) ) mythTvChannelMap[mythTvChannel.chanId] = currChannels[0] mythTvChannelUrlTypeMap[mythTvChannel.chanId] = "sd" for channel in currChannels: logger.info( "Channel: %s" % ( channel.dump() ) ) else: logger.warning( "No channels found for chanId=%i, epgId=%s" % ( mythTvChannel.chanId, epgId ) ) conn.delayCommit( True ) # Convert MythTV records (schedule entries) to AminoPVR schedules for record in mythTvRecords: # If the channel is not in the channel map (yet), it does not exist # in the AminoPVR database. # If there is enough information on MythTV side, create an inactive # channel. if record.chanId != 0 and record.chanId not in mythTvChannelMap: channel, urlType =_addChannel( record.chanId, mythTvChannelsDict, mythTvIptvChannelsDict, dryRun ) if channel: logger.warning( "Adding Channel: %s" % ( channel.dump() ) ) if not dryRun: channel.addToDb( conn ) mythTvChannelMap[record.chanId] = channel mythTvChannelUrlTypeMap[record.chanId] = urlType
def activatePendingChannels( self ): self._logger.debug( "activatePendingChannels()" ) conn = DBConnection() pendingChannels = PendingChannel.getAllFromDb( conn, includeInactive=True, includeRadio=True, tv=True ) pendingChannelNumbers = [ channel.number for channel in pendingChannels ] conn.delayCommit( True ) for channel in pendingChannels: currChannel = Channel.getByNumberFromDb( conn, channel.number ) if currChannel and currChannel.epgId != channel.epgId: # Found a channel on the same channel number, but epgId is different # Find another match. self._logger.info( "activatePendingChannels: epgId mismatch for channel %i - %s: %s != %s" % ( channel.number, channel.name, channel.epgId, currChannel.epgId ) ) # If channel name is the same (or partially the same), then they must have changed epgId # Else, try to find a channel that would match if (channel.name != currChannel.name) and \ (not channel.name in currChannel.name) and \ (not currChannel.name in channel.name): currChannel = None epgIdChannels = Channel.getAllByEpgIdFromDb( conn, channel.epgId, includeInactive=True, includeRadio=True ) for epgIdChannel in epgIdChannels: if (epgIdChannel.name == channel.name) or \ (channel.name in epgIdChannel.name) or \ (epgIdChannel.name in channel.name): currChannel = epgIdChannel break # TODO: if still no match is found (based on epgId), then look for similar names # and maybe equal urls if currChannel: # Convert PendingChannel to Channel but keep channel id newCurrChannel = Channel.copy( channel, currChannel.id ) # Keep the scrambled setting from ChannelUrl's currently in the Db. # This setting cannot be retrieved from the source for key in currChannel.urls.keys(): if newCurrChannel.urls.has_key( key ): newCurrChannel.urls[key].scrambled = currChannel.urls[key].scrambled # Has the channel really changed? if newCurrChannel != currChannel: self._logger.info( "activatePendingChannels: existing channel: %i - %s" % ( channel.number, channel.name ) ) # Hmm, channel number and name are the same, but epgId is different if newCurrChannel.epgId != currChannel.epgId: self._logger.info( "activatePendingChannels: epgId has changed: %s > %s" % ( currChannel.epgId, newCurrChannel.epgId ) ) # Make sure the changed channel is activated (again) newCurrChannel.inactive = False if currChannel.logo != "" and os.path.basename( newCurrChannel.logo ) != os.path.basename( currChannel.logo ): currChannel.removeLogo( conn ) if currChannel.thumbnail != "" and os.path.basename( newCurrChannel.thumbnail ) != os.path.basename( currChannel.thumbnail ): currChannel.removeThumbnail( conn ) # Download the logo and thumbnail for this channel newCurrChannel.downloadLogoAndThumbnail() newCurrChannel.addToDb( conn ) else: self._logger.info( "activatePendingChannels: new channel: %i - %s" % ( channel.number, channel.name ) ) newChannel = Channel.copy( channel ) newChannel.downloadLogoAndThumbnail() newChannel.addToDb( conn ) currentChannels = Channel.getAllFromDb( conn, includeInactive=True, includeRadio=True, tv=True ) currentChannelNumbers = [ channel.number for channel in currentChannels ] removedChannelNumbers = set( currentChannelNumbers ).difference( set( pendingChannelNumbers ) ) self._logger.info( "activatePendingChannels: %i, %i, %i" % ( len( set( currentChannelNumbers ) ), len( set( pendingChannelNumbers ) ), len( removedChannelNumbers ) ) ) for number in removedChannelNumbers: currChannel = Channel.getByNumberFromDb( conn, number ) if not currChannel.inactive: self._logger.info( "activatePendingChannels: inactive channel: %i - %s" % ( currChannel.number, currChannel.name ) ) currChannel.inactive = True currChannel.addToDb( conn ) conn.delayCommit( False ) channels = Channel.getAllFromDb( conn, includeRadio=True, tv=True ) channelsArray = [] for channel in channels: channelJson = channel.toDict( InputStreamProtocol.HTTP, includeScrambled=False, includeHd=True ) if channelJson: channelsArray.append( channelJson ) return self._createResponse( API.STATUS_SUCCESS, channelsArray )