def parse(root): channels = {} version = root.get("version", "1") if version.startswith("1"): log.warning( _("Skipping old channels file") ) elif version.startswith("2") or version.startswith("3") or version.startswith("4"): log.debug("Channel XML Version 4") ChannelsBase.channels_changed = True if root: for element in root.findall("Channel"): name = element.get("name", "") reference = element.get("reference", "") if name and reference: alternatives = [] for alternative in element.findall("Alternative"): alternatives.append( alternative.text ) channels[reference] = (name, list(set(alternatives))) log.debug("Channel", reference, channels[reference] ) else: # XMLTV compatible channels file log.debug("Channel XML Version 5") if root: for element in root.findall("channel"): alternatives = [] id = readFromXML(element.get("id", "")) alternatives.append( id ) name = readFromXML(element.get("name", "")) reference = readFromXML(element.text) #Test customization but XML conform for web in element.findall("web"): alternatives.append( readFromXML(web.text) ) channels[reference] = (name, list(set(alternatives))) log.debug("Channel", reference, channels[reference] ) return channels
def timerCallback(self, timer, data=None): log.debug("timerCallback", data) if data and isinstance(data, dict) and timer: # Episode data available, refactor name and description timer.name = str(refactorTitle(timer.name, data)) timer.description = str(refactorDescription(timer.description, data)) timer.dirname = str(refactorDirectory(timer.dirname or config.usage.default_path.value, data)) timer.calculateFilename() msg = _("Success: %s" % (timer.name)) log.debug(msg) timer.log(610, "[SeriesPlugin]" + " " + msg) if config.plugins.seriesplugin.timer_add_tag.value: timer.tags.append(TAG) elif data: msg = _("Failed: %s." % ( str( data ) )) log.debug(msg) timer.log(611, "[SeriesPlugin]" + " " + msg) SeriesPluginTimer.data.append( str(timer.name) + ": " + msg ) else: msg = _("No data available") log.debug(msg) timer.log(612, "[SeriesPlugin]" + " " + msg) SeriesPluginTimer.data.append( str(timer.name) + ": " + msg ) timer.sp_in_queue = False SeriesPluginTimer.counter = SeriesPluginTimer.counter +1 # Maybe there is a better way to avoid multiple Popups from SeriesPlugin import getInstance instance = getInstance() if instance.thread.empty() and instance.thread.finished(): if SeriesPluginTimer.data: msg = "SeriesPlugin:\n" + _("Timer rename has been finished with %d errors:\n") % (len(SeriesPluginTimer.data)) +"\n" +"\n".join(SeriesPluginTimer.data) log.warning(msg) else: if SeriesPluginTimer.counter > 0: msg = "SeriesPlugin:\n" + _("%d timer renamed successfully") % (SeriesPluginTimer.counter) log.success(msg) SeriesPluginTimer.data = [] SeriesPluginTimer.counter = 0 return timer
def bareShowResult(): global loop_data, loop_counter if loop_data: msg = "SeriesPlugin:\n" + _("Finished with errors:\n") +"\n" +"\n".join(loop_data) log.warning(msg) else: if loop_counter > 0: msg = "SeriesPlugin:\n" + _("Lookup of %d episodes was successful") % (loop_counter) log.success(msg) loop_data = [] loop_counter = 0
def bareShowResult(): global loop_data, loop_counter if loop_data: msg = "SeriesPlugin:\n" + _( "Finished with errors:\n") + "\n" + "\n".join(loop_data) log.warning(msg) else: if loop_counter > 0: msg = "SeriesPlugin:\n" + _( "Lookup of %d episodes was successful") % (loop_counter) log.success(msg) loop_data = [] loop_counter = 0
def osrename(src, dst): #Py3 for f in glob( escape(src) + "*" ): glob_src = CompiledRegexpGlobEscape.sub("[\\1]", src) log.debug("glob_src ", glob_src) for f in glob( glob_src + ".*" ): log.debug("servicepathRnm", f) to = f.replace(src, dst) log.debug("servicepathTo ", to) if not os.path.exists(to): try: os.rename(f, to) except: log.exception("rename error", f, to) elif config.plugins.seriesplugin.rename_existing_files.value: log.debug("Destination file already exists", to, " - Append '_'") return osrename( src, dst + "_") break else: log.warning( _("Skipping rename because file already exists") + "\n" + to + "\n\n" + _("Can be configured within the setup") ) return True
def renamerCallback(self, servicepath, name, short, data=None): log.debug("renamerCallback", name, data) result = None if data and isinstance(data, dict): result = rename(servicepath, name, short, data) elif data and isinstance(data, basestring): msg = _("Failed: %s." % (str(data))) log.debug(msg) self.data.append(name + ": " + msg) else: msg = _("No data available") log.debug(msg) self.data.append(name + ": " + msg) self.counter = self.counter + 1 # Maybe there is a better way to avoid multiple Popups from SeriesPlugin import getInstance instance = getInstance() if instance.thread.empty() and instance.thread.finished(): if self.data: msg = "SeriesPlugin:\n" + _( "Record rename has been finished with %d errors:\n") % ( len(self.data)) + "\n" + "\n".join(self.data) log.warning(msg) else: if self.counter > 0: msg = "SeriesPlugin:\n" + _( "%d records renamed successfully") % (self.counter) log.success(msg) self.data = [] self.counter = 0
def osrename(src, dst): #Py3 for f in glob( escape(src) + "*" ): glob_src = CompiledRegexpGlobEscape.sub("[\\1]", src) log.debug("glob_src ", glob_src) for f in glob(glob_src + ".*"): log.debug("servicepathRnm", f) to = f.replace(src, dst) log.debug("servicepathTo ", to) if not os.path.exists(to): try: os.rename(f, to) except: log.exception("rename error", f, to) elif config.plugins.seriesplugin.rename_existing_files.value: log.debug("Destination file already exists", to, " - Append '_'") return osrename(src, dst + "_") break else: log.warning( _("Skipping rename because file already exists") + "\n" + to + "\n\n" + _("Can be configured within the setup")) return True
def renamerCallback(self, servicepath, name, short, data=None): log.debug("renamerCallback", name, data) result = None if data and isinstance(data, dict): result = rename(servicepath, name, short, data) elif data and isinstance(data, basestring): msg = _("Failed: %s." % ( str( data ) )) log.debug(msg) self.data.append( name + ": " + msg ) else: msg = _("No data available") log.debug(msg) self.data.append( name + ": " + msg ) self.counter = self.counter +1 # Maybe there is a better way to avoid multiple Popups from SeriesPlugin import getInstance instance = getInstance() if instance.thread.empty() and instance.thread.finished(): if self.data: msg = "SeriesPlugin:\n" + _("Record rename has been finished with %d errors:\n") % (len(self.data)) +"\n" +"\n".join(self.data) log.warning(msg) else: if self.counter > 0: msg = "SeriesPlugin:\n" + _("%d records renamed successfully") % (self.counter) log.success(msg) self.data = [] self.counter = 0
def getInstance(): global instance if instance is None: log.reinit() from plugin import VERSION log.debug(" SERIESPLUGIN NEW INSTANCE " + VERSION) log.debug( " ", strftime("%a, %d %b %Y %H:%M:%S", localtime()) ) try: from Tools.HardwareInfo import HardwareInfo log.debug( " DeviceName " + HardwareInfo().get_device_name().strip() ) except: sys.exc_clear() try: from Components.About import about log.debug( " EnigmaVersion " + about.getEnigmaVersionString().strip() ) log.debug( " ImageVersion " + about.getVersionString().strip() ) except: sys.exc_clear() try: #http://stackoverflow.com/questions/1904394/python-selecting-to-read-the-first-line-only log.debug( " dreamboxmodel " + open("/proc/stb/info/model").readline().strip() ) log.debug( " imageversion " + open("/etc/image-version").readline().strip() ) log.debug( " imageissue " + open("/etc/issue.net").readline().strip() ) except: sys.exc_clear() try: for key, value in config.plugins.seriesplugin.dict().iteritems(): log.debug( " config..%s = %s" % (key, str(value.value)) ) except Exception as e: sys.exc_clear() global CompiledRegexpReplaceChars try: if config.plugins.seriesplugin.replace_chars.value: CompiledRegexpReplaceChars = re.compile('['+config.plugins.seriesplugin.replace_chars.value.replace("\\", "\\\\\\\\")+']') except: log.exception( " Config option 'Replace Chars' is no valid regular expression" ) CompiledRegexpReplaceChars = re.compile("[:\!/\\,\(\)'\?]") # Check autotimer try: from Plugins.Extensions.AutoTimer.plugin import autotimer deprecated = False try: from Plugins.Extensions.AutoTimer.plugin import AUTOTIMER_VERSION if int(AUTOTIMER_VERSION[0]) < 4: deprecated = True except ImportError: AUTOTIMER_VERSION = "deprecated" deprecated = True log.debug( " AutoTimer: " + AUTOTIMER_VERSION ) if deprecated: log.warning( _("Your autotimer is deprecated") + "\n" +_("Please update it") ) except ImportError: log.debug( " AutoTimer: Not found" ) # Check dependencies start = True from imp import find_module dependencies = ["difflib", "json", "re", "xml", "xmlrpclib"] for dependency in dependencies: try: find_module(dependency) except ImportError: start = False log.error( _("Error missing dependency") + "\n" + "python-"+dependency + "\n\n" +_("Please install missing python paket manually") ) if start: instance = SeriesPlugin() return instance
def getEpisode(self, callback, name, begin, end=None, service=None, future=False, today=False, elapsed=False, block=False, rename=False): if config.plugins.seriesplugin.skip_during_records.value: try: import NavigationInstance if NavigationInstance.instance.RecordTimer.isRecording(): msg = _("Skip check during running records") + "\n\n" + _("Can be configured within the setup") log.warning( msg) if callable(callback): callback(msg) return msg except: pass # Check for episode information in title match = self.compiledRegexpSeries.match(name) if match: #log.debug(match.group(0)) # Entire match #log.debug(match.group(1)) # First parenthesized subgroup if not rename and config.plugins.seriesplugin.skip_pattern_match.value: msg = _("Skip check because of pattern match") + "\n" + name + "\n\n" + _("Can be configured within the setup") log.warning(msg) if callable(callback): callback(msg) return msg if match.group(1): name = match.group(1) if elapsed: identifier = self.identifier_elapsed elif today: identifier = self.identifier_today elif future: identifier = self.identifier_future else: identifier = self.modules and self.instantiateModule( self.modules.itervalues().next() ) if not identifier: msg = _("No identifier available") + "\n\n" + _("Please check Your installation") log.error(msg) if callable(callback): callback(msg) return msg elif self.channelsEmpty(): msg = _("Channels are not matched") + "\n\n" + _("Please open the channel editor (setup) and match them") log.error(msg) if callable(callback): callback(msg) return msg else: # Reset title search depth on every new request identifier.search_depth = 0; # Reset the knownids on every new request identifier.knownids = [] try: serviceref = service.toString() except: sys.exc_clear() serviceref = str(service) serviceref = re.sub('::.*', ':', serviceref) if block == False: self.thread.add( ThreadItem(identifier, callback, name, begin, end, serviceref) ) else: result = None try: result = identifier.getEpisode( name, begin, end, serviceref ) except Exception, e: log.exception("Worker:", str(e)) # Exception finish job with error result = str(e) config.plugins.seriesplugin.lookup_counter.value += 1 data = normalizeResult(result) if callable(callback): callback(data) return data
def getEpisode(self, timer, block=False): log.info("timername, service, begin, end:", timer.name, str(timer.service_ref.ref), timer.begin, timer.end) if hasattr(timer, 'sp_in_queue'): if timer.sp_in_queue: msg = _("Skipping timer because it is already in queue") log.warning(msg, timer.name) timer.log(601, "[SeriesPlugin]" + " " + msg ) return # We have to compare the length, # because of the E2 special chars handling for creating the filenames #if timer.name == name: # Mad Men != Mad_Men if TAG in timer.tags: msg = _("Skipping timer because it is already handled") + "\n\n" + _("Can be configured within the setup") log.info(msg, timer.name) timer.log(607, "[SeriesPlugin]" + " " + msg ) return if timer.begin < time() + 60: msg = _("Skipping timer because it starts in less than 60 seconds") log.debug(msg, timer.name) timer.log(604, "[SeriesPlugin]" + " " + msg ) return if timer.isRunning(): msg = _("Skipping timer because it is already running") log.debug(msg, timer.name) timer.log(605, "[SeriesPlugin]" + " " + msg ) return if timer.justplay: msg = _("Skipping timer because it is a just play timer") log.debug(msg, timer.name) timer.log(606, "[SeriesPlugin]" + " " + msg ) return event = None epgcache = eEPGCache.getInstance() if timer.eit: event = epgcache.lookupEventId(timer.service_ref.ref, timer.eit) log.debug("lookupEventId", timer.eit, event) if not(event): event = epgcache.lookupEventTime( timer.service_ref.ref, timer.begin + ((timer.end - timer.begin) /2) ); log.debug("lookupEventTime", event ) if event: if not ( len(timer.name) == len(event.getEventName()) ): msg = _("Skipping timer because it is already modified %s" % (timer.name) ) log.info(msg) timer.log(602, "[SeriesPlugin]" + " " + msg ) return begin = event.getBeginTime() or 0 duration = event.getDuration() or 0 end = begin + duration else: if config.plugins.seriesplugin.timer_eit_check.value: msg = _("Skipping timer because no event was found") log.info(msg, timer.name) timer.log(603, "[SeriesPlugin]" + " " + msg ) return else: # We don't know the exact margins, we will assume the E2 default margins log.debug("We don't know the exact margins, we will assume the E2 default margins") begin = timer.begin + (config.recording.margin_before.value * 60) end = timer.end - (config.recording.margin_after.value * 60) timer.log(600, "[SeriesPlugin]" + " " + _("Try to find infos for %s" % (timer.name) ) ) seriesPlugin = getInstance() if timer.service_ref: log.debug("getEpisode:", timer.name, timer.begin, timer.end, block) timer.sp_in_queue = True return seriesPlugin.getEpisode( boundFunction(self.timerCallback, timer), timer.name, begin, end, timer.service_ref, future=True, block=block ) else: msg = _("Skipping lookup because no channel is specified") log.warning(msg) self.timerCallback(timer, msg) return None