Advertisement
Guest User

default.py for CBC

a guest
May 20th, 2023
96
0
13 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 15.36 KB | Source Code | 0 0
  1. """Default plugin module."""
  2. import re
  3. import os
  4. import json
  5. import unicodedata
  6. from urllib import urlencode
  7. from urlparse import parse_qs, parse_qsl
  8.  
  9. import xbmc
  10. import xbmcplugin
  11. import xbmcgui
  12. import xbmcaddon
  13. import inputstreamhelper
  14. import routing
  15.  
  16. from resources.lib.cbc import CBC
  17. from resources.lib.utils import log, getAuthorizationFile, get_cookie_file, get_iptv_channels_file
  18. from resources.lib.livechannels import LiveChannels
  19. # from resources.lib.gemv2 import GemV2
  20. # from resources.lib.iptvmanager import IPTVManager
  21.  
  22. getString = xbmcaddon.Addon().getLocalizedString
  23. LIVE_CHANNELS = getString(30004)
  24. GEMS = {
  25.     'featured': getString(30005),
  26.     'shows': getString(30006),
  27.     'documentaries': getString(30024),
  28.     'kids': getString(30025)
  29. }
  30. SEARCH = getString(30026)
  31.  
  32.  
  33. plugin = routing.Plugin()
  34.  
  35.  
  36. def remove_utf8_stuff(data):
  37.     return(unicodedata.normalize('NFKD', data).encode('ascii', 'ignore'))
  38.  
  39.  
  40. def asciify_list(data):
  41.     ret = []
  42.     for item in data:
  43.         if isinstance(item, unicode):
  44.             item = remove_utf8_stuff(item)
  45.             item = item.encode('utf-8')
  46.         elif isinstance(item, list):
  47.             item = asciify_list(item)
  48.         elif isinstance(item, dict):
  49.             item = asciify_dict(item)
  50.         ret.append(item)
  51.     return ret
  52.  
  53.  
  54. def asciify_dict(data):
  55.     ret = {}
  56.     for key, value in data.iteritems():
  57.         if isinstance(key, unicode):
  58.             key = remove_utf8_stuff(key)
  59.             key = key.encode('utf-8')
  60.         if isinstance(value, unicode):
  61.             value = remove_utf8_stuff(value)
  62.             value = value.encode('utf-8')
  63.         elif isinstance(value, list):
  64.             value = asciify_list(value)
  65.         elif isinstance(value, dict):
  66.             value = asciify_dict(value)
  67.         ret[key] = value
  68.     return ret
  69.  
  70.  
  71. def authorize():
  72.     """Authorize the client."""
  73.     prog = xbmcgui.DialogProgress()
  74.     prog.create(getString(30001))
  75.     cbc = CBC()
  76.  
  77.     username = xbmcaddon.Addon().getSetting("username")
  78.     if len(username) == 0:
  79.         username = None
  80.  
  81.     password = xbmcaddon.Addon().getSetting("password")
  82.     if len(password) == 0:
  83.         password = None
  84.         username = None
  85.  
  86.     if not cbc.azure_authorize(username, password, prog.update):
  87.         log('(authorize) unable to authorize', True)
  88.         prog.close()
  89.         xbmcgui.Dialog().ok(getString(30002), getString(30002))
  90.         return False
  91.  
  92.     prog.close()
  93.     return True
  94.  
  95.  
  96. def play(labels, image, url):
  97.     """Play the stream using the configured player."""
  98.     item = xbmcgui.ListItem(labels['title'], path=url)
  99.     if image:
  100.         item.setArt({'thumb': image, 'poster': image})
  101.     labels['mediatype'] = 'episode'
  102.     item.setInfo(type="video", infoLabels=labels)
  103.     helper = inputstreamhelper.Helper('hls')
  104.     if not xbmcaddon.Addon().getSettingBool("ffmpeg") and helper.check_inputstream():
  105.         item.setProperty('inputstream', 'inputstream.adaptive')
  106.         item.setProperty('inputstream.adaptive.manifest_type', 'hls')
  107.     xbmcplugin.addSortMethod(plugin.handle, xbmcplugin.SORT_METHOD_EPISODE)
  108.     xbmcplugin.setResolvedUrl(plugin.handle, True, item)
  109.     if url is None:
  110.         xbmcgui.Dialog().ok(getString(30010), getString(30011))
  111.  
  112. def add_items(handle, items):
  113.     cbc = CBC()
  114.     for item in items:
  115.         list_item = xbmcgui.ListItem(item['title'])
  116.         # list_item.setInfo(type="Video", infoLabels=CBC.get_labels(item))
  117.         list_item.setInfo(type="Video", infoLabels=cbc.get_labels(item))
  118.         image = item['image'].replace('(Size)', '224')
  119.         list_item.setArt({'thumb': image, 'poster': image})
  120.         item_type = item['type']
  121.         is_folder = True
  122.         if item_type == 'SHOW':
  123.             url = plugin.url_for(gem_show_menu, item['id'])
  124.         elif item_type == 'ASSET':
  125.             url = plugin.url_for(gem_asset, item['id'])
  126.             list_item.setProperty('IsPlayable', 'true')
  127.             is_folder = False
  128.         elif item_type == 'SEASON':
  129.             # ignore the season and go to the show (its what the web UI does)
  130.             url = plugin.url_for(gem_show_menu, item['id'].split('/')[0])
  131.         else:
  132.             log('Unable to handle shelf item type "{item_type}".', True)
  133.             url = None
  134.         xbmcplugin.addDirectoryItem(handle, url, list_item, is_folder)
  135.  
  136.  
  137. @plugin.route('/logout')
  138. def logout():
  139.     """Remove authorization stuff."""
  140.     log('Logging out...', True)
  141.     os.remove(getAuthorizationFile())
  142.     os.remove(get_cookie_file())
  143.  
  144.  
  145. @plugin.route('/smil')
  146. def play_smil():
  147.     """Play an SMIL file."""
  148.     cbc = CBC()
  149.     url = cbc.parseSmil(plugin.args['url'][0])
  150.     labels = dict(parse_qsl(plugin.args['labels'][0])) if 'labels' in plugin.args else None
  151.     return play(labels, plugin.args['image'][0], url)
  152.  
  153.  
  154. # @plugin.route('/iptv/channels')
  155. # def iptv_channels():
  156. #     """Send a list of IPTV channels."""
  157. #     port = int(plugin.args.get('port')[0])
  158. #     IPTVManager(port).send_channels()
  159.  
  160.  
  161. # @plugin.route('/iptv/epg')
  162. # def iptv_epg():
  163. #     """Get EPG information for IPTV manager."""
  164. #     port = int(plugin.args.get('port')[0])
  165. #     IPTVManager(port).send_epg()
  166.  
  167.  
  168. @plugin.route('/iptv/addall')
  169. def live_channels_add_all():
  170.     """Add all channels back to the PVR listing."""
  171.     os.remove(get_iptv_channels_file())
  172.  
  173.  
  174. @plugin.route('/iptv/add/<station>')
  175. def live_channels_add(station):
  176.     """Add a single station."""
  177.     LiveChannels.add_iptv_channel(station)
  178.  
  179.  
  180. @plugin.route('/iptv/remove/<station>')
  181. def live_channels_remove(station):
  182.     """Remove a station."""
  183.     LiveChannels.remove_iptv_channel(station)
  184.  
  185.  
  186. @plugin.route('/iptv/addonly/<station>')
  187. def live_channels_add_only(station):
  188.     """Remove all but the specified station from the IPTV station list."""
  189.     LiveChannels.add_only_iptv_channel(station)
  190.  
  191.  
  192. @plugin.route('/channels')
  193. def live_channels_menu():
  194.     """Populate the menu with live channels."""
  195.     xbmcplugin.setContent(plugin.handle, 'videos')
  196.     chans = LiveChannels()
  197.     chan_list = chans.get_live_channels()
  198.     cbc = CBC()
  199.     for channel in chan_list:
  200.         # labels = CBC.get_labels(channel)
  201.         labels = cbc.get_labels(channel)
  202.         callsign = cbc.get_callsign(channel)
  203.         image = cbc.getImage(channel)
  204.         item = xbmcgui.ListItem(labels['title'])
  205.         item.setArt({'thumb': image, 'poster': image})
  206.         item.setInfo(type="Video", infoLabels=labels)
  207.         item.setProperty('IsPlayable', 'true')
  208.         item.addContextMenuItems([
  209.             (getString(30014), 'RunPlugin({})'.format(plugin.url_for(live_channels_add_all))),
  210.             (getString(30015), 'RunPlugin({})'.format(plugin.url_for(live_channels_add, callsign))),
  211.             (getString(30016), 'RunPlugin({})'.format(plugin.url_for(live_channels_remove, callsign))),
  212.             (getString(30017), 'RunPlugin({})'.format(plugin.url_for(live_channels_add_only, callsign))),
  213.         ])
  214.         xbmcplugin.addDirectoryItem(plugin.handle,
  215.                                     plugin.url_for(play_smil, url=channel['content'][0]['url'],
  216.                                                    labels=urlencode(labels), image=image), item, False)
  217.     xbmcplugin.endOfDirectory(plugin.handle)
  218.  
  219.  
  220. @plugin.route('/gem/show/episode/episode')
  221. def gem_episode():
  222.     """Play an episode."""
  223.     cbc = CBC()
  224.     json_str = plugin.args['query'][0]
  225.     episode = json.loads(json_str)
  226.  
  227.     # get the url, and failing that, attempt authorization, then retry
  228.     # resp = GemV2().get_episode(episode['url'])
  229.     resp = cbc.GemV2_get_episode(episode['url'])
  230.     url = None if not resp else resp['url'] if 'url' in resp else None
  231.     if not url:
  232.         log('Failed to get stream URL, attempting to authorize.')
  233.         if authorize():
  234.             # resp = GemV2().get_episode(episode['url'])
  235.             resp = cbc.GemV2_get_episode(episode['url'])
  236.             url = resp['url'] if 'url' in resp else None
  237.  
  238.     labels = episode['labels']
  239.     play(labels, None, url)
  240.  
  241. @plugin.route('/gem/show/season/season')
  242. def gem_show_season():
  243.     """Create a menu for a show season."""
  244.     cbc = CBC()
  245.     xbmcplugin.setContent(plugin.handle, 'videos')
  246.     json_str = plugin.args['query'][0]
  247.     # remember show['season'] is season details but there is general show info in show as well
  248.     show = json.loads(json_str)
  249.     for episode in show['season']['assets']:
  250.         item = xbmcgui.ListItem(episode['title'])
  251.         image = episode['image'].replace('(Size)', '224')
  252.         item.setArt({'thumb': image, 'poster': image})
  253.         item.setProperty('IsPlayable', 'true')
  254.         # labels = GemV2.get_labels(show, episode)
  255.         labels = cbc.GemV2_get_labels(show, episode)
  256.         item.setInfo(type="Video", infoLabels=labels)
  257.         episode_info = {'url': episode['playSession']['url'], 'labels': labels}
  258.         episode_info = asciify_dict(episode_info)
  259.         url = plugin.url_for(gem_episode, query=json.dumps(episode_info))
  260.         xbmcplugin.addDirectoryItem(plugin.handle, url, item, False)
  261.     xbmcplugin.endOfDirectory(plugin.handle)
  262.  
  263.  
  264. @plugin.route('/gem/asset/<path:asset>')
  265. def gem_asset(asset):
  266.     cbc = CBC()
  267.  
  268.     # asset_layout = GemV2.get_asset_by_id(asset)
  269.     asset_layout = cbc.GemV2_get_asset_by_id(asset)
  270.  
  271.     # resp = GemV2.get_episode(asset_layout['playSession']['url'])
  272.     resp = cbc.GemV2_get_episode(asset_layout['playSession']['url'])
  273.     url = None if not resp else resp['url'] if 'url' in resp else None
  274.     if not url:
  275.         log('Failed to get stream URL, attempting to authorize.')
  276.         if authorize():
  277.             # resp = GemV2().get_episode(asset_layout['playSession']['url'])
  278.             resp = cbc.GemV2_get_episode(asset_layout['playSession']['url'])
  279.             url = resp['url'] if 'url' in resp else None
  280.  
  281.     # labels = GemV2.get_labels({'title': asset_layout['series'], asset_layout)
  282.     labels = cbc.GemV2_get_labels({'title': asset_layout['series']}, asset_layout)
  283.  
  284.     image = asset_layout['image']
  285.  
  286.     play(labels, image, url)
  287.  
  288.  
  289. def gem_add_film_assets(assets):
  290.     for asset in assets:
  291.         cbc = CBC()
  292.         # labels = GemV2.get_labels({'title': asset['series']}, asset)
  293.         labels = cbc.GemV2_get_labels({'title': asset['series']}, asset)
  294.         image = asset['image']
  295.         item = xbmcgui.ListItem(labels['title'])
  296.         item.setInfo(type="Video", infoLabels=labels)
  297.         item.setArt({'thumb': image, 'poster': image})
  298.         item.setProperty('IsPlayable', 'true')
  299.         episode_info = {'url': asset['playSession']['url'], 'labels': labels}
  300.         url = plugin.url_for(gem_episode, query=json.dumps(episode_info))
  301.         xbmcplugin.addDirectoryItem(plugin.handle, url, item, False)
  302.  
  303.  
  304. @plugin.route('/gem/show/<show_id>')
  305. def gem_show_menu(show_id):
  306.     """Create a menu for a shelfs items."""
  307.     cbc = CBC()
  308.     xbmcplugin.setContent(plugin.handle, 'videos')
  309.     # show_layout = GemV2.get_show_layout_by_id(show_id)
  310.     show_layout = cbc.GemV2_get_show_layout_by_id(show_id)
  311.     show_layout = asciify_dict(show_layout)
  312.     show = {k: v for (k, v) in show_layout.items() if k not in ['sponsors', 'seasons']}
  313.     show = asciify_dict(show)
  314.     for season in show_layout['seasons']:
  315.  
  316.         # films seem to have been shoe-horned (with teeth) into the structure oddly -- compensate
  317.         if season['title'] == 'Film':
  318.             gem_add_film_assets(season['assets'])
  319.         else:
  320.             # labels = GemV2.get_labels(season, season)
  321.             labels = cbc.GemV2_get_labels(season, season)
  322.             item = xbmcgui.ListItem(season['title'])
  323.             item.setInfo(type="Video", infoLabels=labels)
  324.             image = season['image'].replace('(Size)', '224')
  325.             item.setArt({'thumb': image, 'poster': image})
  326.             show['season'] = season
  327.             url = plugin.url_for(gem_show_season, query=json.dumps(show))
  328.             xbmcplugin.addDirectoryItem(plugin.handle, url, item, True)
  329.     xbmcplugin.endOfDirectory(plugin.handle)
  330.  
  331.  
  332. @plugin.route('/gem/shelf')
  333. def gem_shelf_menu():
  334.     """Create a menu item for each shelf."""
  335.     cbc = CBC()
  336.     handle = plugin.handle
  337.     xbmcplugin.setContent(handle, 'videos')
  338.     json_str = plugin.args['query'][0]
  339.     shelf_items = json.loads(json_str)
  340.     shelf_items = asciify_list(shelf_items)
  341.     add_items(handle, shelf_items)
  342.     xbmcplugin.addSortMethod(plugin.handle, xbmcplugin.SORT_METHOD_TITLE_IGNORE_THE)
  343.     xbmcplugin.endOfDirectory(handle)
  344.  
  345.  
  346. @plugin.route('/gem/categories/<category_id>')
  347. def gem_category_menu(category_id):
  348.     """Populate a menu with categorical content."""
  349.     cbc = CBC()
  350.     handle = plugin.handle
  351.     xbmcplugin.setContent(handle, 'videos')
  352.     # category = GemV2.get_category(category_id)
  353.     category = cbc.GemV2_get_category(category_id)
  354.     for show in category['items']:
  355.         item = xbmcgui.ListItem(show['title'])
  356.         # item.setInfo(type="Video", infoLabels=CBC.get_labels(show))
  357.         item.setInfo(type="Video", infoLabels=cbc.get_labels(show))
  358.         image = show['image'].replace('(Size)', '224')
  359.         item.setArt({'thumb': image, 'poster': image})
  360.         url = plugin.url_for(gem_show_menu, show['id'])
  361.         xbmcplugin.addDirectoryItem(handle, url, item, True)
  362.     xbmcplugin.addSortMethod(handle, xbmcplugin.SORT_METHOD_TITLE_IGNORE_THE)
  363.     xbmcplugin.endOfDirectory(handle)
  364.  
  365.  
  366. @plugin.route('/gem/search')
  367. def search():
  368.     cbc = CBC()
  369.     handle = plugin.handle
  370.     term = xbmcgui.Dialog().input(SEARCH, type=xbmcgui.INPUT_ALPHANUM)
  371.     # results = GemV2.search_by_term(term)
  372.     results = cbc.GemV2_search_by_term(term)
  373.     add_items(handle, results)
  374.     xbmcplugin.endOfDirectory(handle)
  375.  
  376.  
  377. @plugin.route('/gem/layout/<layout>')
  378. def layout_menu(layout):
  379.     """Populate the menu with featured items."""
  380.     cbc = CBC()
  381.     handle = plugin.handle
  382.     xbmcplugin.setContent(handle, 'videos')
  383.     # layout = GemV2.get_layout(layout)
  384.     layout = cbc.GemV2_get_layout(layout)
  385.     layout = asciify_dict(layout)
  386.     if 'categories' in layout:
  387.         for category in layout['categories']:
  388.             item = xbmcgui.ListItem(category['title'])
  389.             url = plugin.url_for(gem_category_menu, category['id'])
  390.             xbmcplugin.addDirectoryItem(handle, url, item, True)
  391.     if 'shelves' in layout:
  392.         for shelf in layout['shelves']:
  393.             item = xbmcgui.ListItem(shelf['title'])
  394.             shelf_items = json.dumps(shelf['items'])
  395.             url = plugin.url_for(gem_shelf_menu, query=shelf_items)
  396.             xbmcplugin.addDirectoryItem(handle, url, item, True)
  397.     xbmcplugin.endOfDirectory(handle)
  398.  
  399.  
  400. @plugin.route('/')
  401. def main_menu():
  402.     """Populate the menu with the main menu items."""
  403.     data_path = xbmc.translatePath(xbmcaddon.Addon().getAddonInfo('profile'))
  404.     if not os.path.exists(data_path):
  405.         os.makedirs(data_path)
  406.     if not os.path.exists(getAuthorizationFile()):
  407.         authorize()
  408.  
  409.     handle = plugin.handle
  410.     xbmcplugin.setContent(handle, 'videos')
  411.     for key, value in GEMS.items():
  412.         xbmcplugin.addDirectoryItem(handle, plugin.url_for(layout_menu, key), xbmcgui.ListItem(value), True)
  413.     xbmcplugin.addDirectoryItem(handle, plugin.url_for(live_channels_menu), xbmcgui.ListItem(LIVE_CHANNELS), True)
  414.     xbmcplugin.addDirectoryItem(handle, plugin.url_for(search), xbmcgui.ListItem(SEARCH), True)
  415.     xbmcplugin.endOfDirectory(handle)
  416.  
  417.  
  418. if __name__ == '__main__':
  419.     plugin.run()
  420.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement