def load_instances(self): inst_defn_obj = ConfigDefn(self.plugin_path, PLUGIN_INSTANCE_DEFN_FILE, self.config_obj.data, True) # determine in the config data whether the instance of this name exists. It would have a section name = 'name-instance' self.instances = self.find_instances() for inst in self.instances: self.plugin_db.save_instance(self.namespace, inst, '') # create a defn with the instance name as the section name. then process it. inst_defn_obj.is_instance_defn = False for area, area_data in inst_defn_obj.config_defn.items(): if len(area_data['sections']) != 1: self.logger.error('INSTANCE MUST HAVE ONE AND ONLY ONE SECTION') raise exceptions.CabernetException('plugin defn must have one and only one instance section') section = list(area_data['sections'].keys())[0] base_section = section.split('_', 1)[0] area_data['sections'][base_section + '_' + inst] = area_data['sections'].pop(section) if 'label' in self.config_obj.data[base_section + '_' + inst] \ and self.config_obj.data[base_section + '_' + inst]['label'] is not None: area_data['sections'][base_section + '_' + inst]['label'] = self.config_obj.data[base_section + '_' + inst]['label'] inst_defn_obj.save_defn_to_db() default_config = inst_defn_obj.get_default_config() self.config_obj.merge_config(default_config) inst_defn_obj.call_oninit(self.config_obj) self.config_obj.defn_json.merge_defn_obj(inst_defn_obj) for area, area_data in inst_defn_obj.config_defn.items(): for section, section_data in area_data['sections'].items(): for setting in section_data['settings'].keys(): new_value = self.config_obj.fix_value_type( section, setting, self.config_obj.data[section][setting]) self.config_obj.data[section][setting] = new_value self.db_configdefn.add_config(self.config_obj.data)
def __init__(self, _locast_inst): self.config_obj = _locast_inst.config_obj config_section = _locast_inst.config_section self.zipcode = self.config_obj.data[config_section][ "overrides-zipcode"] self.latitude = self.config_obj.data[config_section][ "overrides-latitude"] self.longitude = self.config_obj.data[config_section][ "overrides-longitude"] self.dma = None self.city = None self.active = None self.has_dma_changed = False if self.find_location(): self.logger.debug("Got location as {} - DMA {}".format( self.city, self.dma)) else: raise exceptions.CabernetException( "Unable to retrieve DMA location") # Check that Locast reports this market is currently active and available. if not self.active: self.logger.error( "Locast reports that this DMA/Market area is not currently active!" ) raise exceptions.CabernetException( "Locast indicates DMA location not active") if 'dma' in self.config_obj.data[config_section] \ and self.config_obj.data[config_section]['dma'] \ != self.dma: self.logger.debug( 'DMA has changed, purging old DMA data for this instance') self.has_dma_changed = True # update config file with DMA and City self.config_obj.write(config_section, 'dma', self.dma) self.config_obj.write(config_section, 'city', self.city)
def login(self): if not self.username: return None if not self.password: return None login_invalid = self.config_obj.data[self.section]['login-invalid'] if login_invalid is not None: delta_secs = time.time() - login_invalid # if over 1hr 30 min, then retry login if delta_secs < 5400: self.logger.error( '{} Unable to login due to invalid logins. Clear config entry login_invalid to try again' .format(self.section)) raise exceptions.CabernetException('Locast Login Failed') else: self.logger.info( '{} Resetting invalid logins config value and retrying login to Locast' .format(self.section)) self.config_obj.write(self.section, 'login-invalid', "") if self.validate_user(True): self.logger.info('Reusing Locast token [{}]'.format(self.section)) return True self.logger.info('Logging into Locast [{}]'.format(self.section)) self.token = self.get_token() if not self.token: self.logger.error( 'Invalid Locast Login Credentials. Disabling instance') current_time = str(int(time.time())) self.config_obj.write(self.section, 'login-invalid', current_time) raise exceptions.CabernetException("Locast Login Failed") else: self.config_obj.write(self.section, 'login-token', self.token) return self.validate_user(False)
def merge_dict(d1, d2, override=False, ignore_conflicts=False): for key in d2: if key in d1: if isinstance(d1[key], dict) and isinstance(d2[key], dict): merge_dict(d1[key], d2[key], override, ignore_conflicts) elif d1[key] == d2[key]: pass elif override: d1[key] = d2[key] elif not ignore_conflicts: raise exceptions.CabernetException( 'Conflict when merging dictionaries {}'.format(str(key))) else: d1[key] = d2[key] return d1
def get_locast_channels(self): channels_url = 'https://api.locastnet.org/api/watch/epg/{}' \ .format(self.locast_instance.location.dma) url_headers = { 'Content-Type': 'application/json', 'authorization': 'Bearer {}'.format(self.locast_instance.token), 'User-agent': constants.DEFAULT_USER_AGENT} req = urllib.request.Request(channels_url, headers=url_headers) with urllib.request.urlopen(req) as resp: ch_json = json.load(resp) ch_list = [] if len(ch_json) == 0: self.logger.warning('Locast HTTP Channel Request Failed for instance {}'.format(self.instance)) raise exceptions.CabernetException('Locast HTTP Channel Request Failed') self.logger.info("{}: Found {} stations for DMA {} on instance {}" .format(self.locast.name, len(ch_json), str(self.locast_instance.location.dma), self.instance)) for locast_channel in ch_json: hd = 0 ch_id = str(locast_channel['id']) ch_callsign = locast_channel['name'] thumbnail = None thumbnail_size = None if 'logoUrl' in locast_channel.keys(): thumbnail = locast_channel['logoUrl'] elif 'logo226Url' in locast_channel.keys(): thumbnail = locast_channel['logo226Url'] if thumbnail is not None: thumbnail_size = channels.get_thumbnail_size(thumbnail) try: if 'videoProperties' in locast_channel['listings'][0]: if 'HD' in locast_channel['listings'][0]['videoProperties']: hd = 1 else: hd = 0 except IndexError: pass try: assert (float(locast_channel['callSign'].split()[0])) channel = locast_channel['callSign'].split()[0] friendly_name = locast_channel['callSign'].split()[1] channel = { 'id': ch_id, 'enabled': True, 'callsign': ch_callsign, 'number': channel, 'name': friendly_name, 'HD': hd, 'group_hdtv': self.locast_instance.config_obj.data[self.config_section]['m3u-group_hdtv'], 'group_sdtv': self.locast_instance.config_obj.data[self.config_section]['m3u-group_sdtv'], 'groups_other': None, # array list of groups/categories 'thumbnail': thumbnail, 'thumbnail_size': thumbnail_size } ch_list.append(channel) except ValueError: self.logger.warning( '################### CALLSIGN ERROR Channel ignored: {} {}' .format(ch_id, locast_channel['callSign'])) return ch_list