def get_iptv_channels(self): """Get the channels in a IPTV Manager compatible list.""" cbc = CBC() channels = self.get_live_channels() blocked = self.get_blocked_iptv_channels() result = [] for channel in channels: callsign = CBC.get_callsign(channel) # if the user has omitted this from the list of their channels, don't populate it if callsign in blocked: continue labels = CBC.get_labels(channel) image = cbc.getImage(channel) values = { 'url': channel['content'][0]['url'], 'image': image, 'labels': urlencode(labels) } channel_dict = { 'name': channel['title'], 'stream': 'plugin://plugin.video.cbc/smil?' + urlencode(values), 'id': callsign, 'logo': image } # Use "CBC Toronto" instead of "Toronto" if len(channel_dict['name']) < 4 or channel_dict['name'][0:4] != 'CBC ': channel_dict['name'] = 'CBC {}'.format(channel_dict['name']) result.append(channel_dict) return result
def live_channels_menu(): """Populate the menu with live channels.""" xbmcplugin.setContent(plugin.handle, 'videos') chans = LiveChannels() chan_list = chans.get_live_channels() cbc = CBC() for channel in chan_list: labels = CBC.get_labels(channel) callsign = cbc.get_callsign(channel) image = cbc.getImage(channel) item = xbmcgui.ListItem(labels['title']) item.setArt({'thumb': image, 'poster': image}) item.setInfo(type="Video", infoLabels=labels) item.setProperty('IsPlayable', 'true') item.addContextMenuItems([ (getString(30014), 'RunPlugin({})'.format(plugin.url_for(live_channels_add_all))), (getString(30015), 'RunPlugin({})'.format(plugin.url_for(live_channels_add, callsign))), (getString(30016), 'RunPlugin({})'.format( plugin.url_for(live_channels_remove, callsign))), (getString(30017), 'RunPlugin({})'.format( plugin.url_for(live_channels_add_only, callsign))), ]) xbmcplugin.addDirectoryItem( plugin.handle, plugin.url_for(play_smil, url=channel['content'][0]['url'], labels=urlencode(labels), image=image), item, False) xbmcplugin.endOfDirectory(plugin.handle)
def play_smil(): """Play an SMIL file.""" cbc = CBC() url = cbc.parseSmil(plugin.args['url'][0]) labels = dict(parse_qsl( plugin.args['labels'][0])) if 'labels' in plugin.args else None return play(labels, plugin.args['image'][0], url)
def get_iptv_epg(): """Get the EPG Data.""" live = LiveChannels() channels = live.get_live_channels() blocked = live.get_blocked_iptv_channels() unblocked = [] for channel in channels: callsign = CBC.get_callsign(channel) if callsign not in blocked: unblocked.append(channel) channel_map = map_channel_ids(unblocked) epg_data = {} future_to_callsign = {} log('Starting EPG update') with futures.ThreadPoolExecutor(max_workers=20) as executor: for callsign, guide_id in channel_map.items(): # determine if we're dealing with news network newsnetwork = callsign == 'NN' # add empty array of programs epg_data[callsign] = [] # submit three concurrent requests for a days guide data for day_offset in [0, 1, 2]: dttm = datetime.now() + timedelta(days=day_offset) future = executor.submit(get_channel_data, dttm, guide_id, newsnetwork) future_to_callsign[future] = callsign for future in futures.as_completed(future_to_callsign): callsign = future_to_callsign[future] epg_data[callsign].extend(future.result()) log('EPG update complete.') return epg_data
def map_channel_ids(unblocked): """Map channel IDs to guide names.""" data = call_guide_url(datetime.now()) soup = BeautifulSoup(data, features="html.parser") select = soup.find('select', id="selectlocation-tv") options = select.find_all('option') channel_map = {'NN': None} for option in options: title = option.get_text() value = option['value'] for channel in unblocked: if unidecode(channel['title']).lower() == unidecode(title).lower(): channel_map[CBC.get_callsign(channel)] = value return channel_map
def add_only_iptv_channel(channel): """ Add only a single specified channel to the list of IPTV channels. This method gets the list of all channels, and removes the only one the user wants, leaving the rest as an extensive filter. """ blocked = [CBC.get_callsign(chan) for chan in LiveChannels().get_live_channels()] if channel in blocked: blocked.remove(channel) with open(get_iptv_channels_file(), 'w') as chan_file: json.dump(blocked, chan_file)
def authorize(): """Authorize the client.""" prog = xbmcgui.DialogProgress() prog.create(getString(30001)) cbc = CBC() username = xbmcaddon.Addon().getSetting("username") if len(username) == 0: username = None password = xbmcaddon.Addon().getSetting("password") if len(password) == 0: password = None username = None if not cbc.authorize(username, password, prog.update): log('(authorize) unable to authorize', True) prog.close() xbmcgui.Dialog().ok(getString(30002), getString(30002)) return False prog.close() return True
def gem_category_menu(category_id): """Populate a menu with categorical content.""" handle = plugin.handle xbmcplugin.setContent(handle, 'videos') category = GemV2.get_category(category_id) for show in category['items']: item = xbmcgui.ListItem(show['title']) item.setInfo(type="Video", infoLabels=CBC.get_labels(show)) image = show['image'].replace('(Size)', '224') item.setArt({'thumb': image, 'poster': image}) url = plugin.url_for(gem_show_menu, show['id']) xbmcplugin.addDirectoryItem(handle, url, item, True) xbmcplugin.addSortMethod(handle, xbmcplugin.SORT_METHOD_TITLE_IGNORE_THE) xbmcplugin.endOfDirectory(handle)
def add_items(handle, items): for item in items: list_item = xbmcgui.ListItem(item['title']) list_item.setInfo(type="Video", infoLabels=CBC.get_labels(item)) image = item['image'].replace('(Size)', '224') list_item.setArt({'thumb': image, 'poster': image}) item_type = item['type'] is_folder = True if item_type == 'SHOW': url = plugin.url_for(gem_show_menu, item['id']) elif item_type == 'ASSET': url = plugin.url_for(gem_asset, item['id']) list_item.setProperty('IsPlayable', 'true') is_folder = False elif item_type == 'SEASON': # ignore the season and go to the show (its what the web UI does) url = plugin.url_for(gem_show_menu, item['id'].split('/')[0]) else: log(f'Unable to handle shelf item type "{item_type}".', True) url = None xbmcplugin.addDirectoryItem(handle, url, list_item, is_folder)
def search_by_term(term): params = {'term': term} resp = CBC.get_session().get(SEARCH_BY_NAME, params=params) return json.loads(resp.content)
def get_category(category_id): """Get a Gem V2 category by ID.""" url = CATEGORY_BY_ID.format(category_id) resp = CBC.get_session().get(url) return json.loads(resp.content)
def get_asset_by_id(asset_id): url = ASSET_BY_ID.format(asset_id) resp = CBC.get_session().get(url) return json.loads(resp.content)
def get_show_layout_by_id(show_id): """Get a Gem V2 show layout by ID.""" url = SHOW_BY_ID.format(show_id) resp = CBC.get_session().get(url) return json.loads(resp.content)
def get_layout(name): """Get a Gem V2 layout by name.""" url = LAYOUT_MAP[name] resp = CBC.get_session().get(url) return json.loads(resp.content)
dest='layout', help='CBC Gem V2 layout') (options, args) = parser.parse_args() from resources.lib.livechannels import * from resources.lib.liveprograms import * from resources.lib.shows import * from resources.lib.cbc import CBC from resources.lib.gemv2 import GemV2 def progress(x): print(x) cbc = CBC() chans = LiveChannels() events = LivePrograms() shows = Shows() res = [] if options.authorize: if not cbc.authorize(options.username, options.password, progress): print('Error: Authorization failed') sys.exit(1) print('Authorization successful') sys.exit(0) if options.chans: res = chans.get_live_channels() elif options.progs: