# -*- coding: UTF-8 -*- """ Kan Video plugin """ # Copyright (c) 2017 Tzafrir Cohen # SPDX-License-Identifier: GPL-2.0+ # # License-Filename: LICENSE from bs4 import BeautifulSoup import datetime import re import sys import urllib #import urllib2 import requests import simplecache import urlparse import xbmc import xbmcgui import xbmcplugin KAN_URL = 'http://www.kan.org.il' USER_AGENT = 'Kodi/plugin.video.kan/1.0' # I'm optimistic PLUGIN_NAME = "plugin.video.kan" # FIXME: a better way to get this? SiteCache = simplecache.SimpleCache() # FIXME: avoid this global def trace(msg): xbmc.log(msg="Tzafrir: " + msg, level=xbmc.LOGNOTICE) class Page: def __init__(self, argv): self.base_url = argv[0] self.addon_handle = int(argv[1]) self.args = urlparse.parse_qs(argv[2][1:]) self.mode = self.args.get('mode', None) self.content_type = self.args.get('content_type', None) def build_url(self, query): #query['addon_handle'] = self.addon_handle return self.base_url + '?' + urllib.urlencode(query) def add_directory_item(self, **kwargs): xbmcplugin.addDirectoryItem(handle=self.addon_handle, **kwargs) def end_directory(self): xbmcplugin.endOfDirectory(self.addon_handle) def placeholder_folder(self, foldername): """ A folder with a single dummy item """ url = 'http://localhost/some_video.mkv' li = xbmcgui.ListItem(foldername + 'Not Implemented', iconImage='DefaultVideo.png') self.add_directory_item(url=url, listitem=li) self.end_directory() def placeholder_item(self, name, label): """ An item that calls a placeholder folder """ url = self.build_url({'mode': 'placeholder', 'name': name}) li = xbmcgui.ListItem(label) self.add_directory_item(url=url, listitem=li, isFolder=True) def __str__(self): return "[base_url: {}, addon_handle: {}, mode: {}, content_type: {}]" \ .format(self.base_url, self.addon_handle, self.mode, self.content_type) def read_url(url): cache_id = PLUGIN_NAME + '.url.' + url cached_read = SiteCache.get(cache_id) if cached_read: return cached_read headers = {'user-agent': USER_AGENT} response = requests.get(url, headers=headers) if response.status_code != 200: raise IOError("Invalid URL {}".format(url)) SiteCache.set(cache_id, response.content, expiration=datetime.timedelta(days=1)) return response.content def get_show_title(base_url, path): url = base_url + '/' + path page = read_url(url) parsed = BeautifulSoup(page, "html.parser") title = parsed.title.string title = re.sub('[|-].*', '', title) return title def video_top_menu(page, name): """ Display a menu of all the TV shows """ tvshows_url = KAN_URL + "/video/{}.aspx".format(name) main_page = read_url(tvshows_url) parsed = BeautifulSoup(main_page, "html.parser") anchors = parsed.find_all('a', class_="program_category_link w-inline-block") trace("got anchors: " + str(len(anchors))) for a in anchors: path = a.get('href') show_id = re.sub('.*=', '', path) #trace("Checking link to " + path) title = get_show_title(KAN_URL, path) url = page.build_url({'mode': 'show', 'id': show_id}) trace("Item: URL: {}, title: {}.".format(url, title.encode('utf8'))) li = xbmcgui.ListItem(title) page.add_directory_item(url=url, listitem=li, isFolder=True, totalItems=len(anchors)) page.end_directory() def show_menu(page): """ Display a menu of items in a specific show """ show_id = page.args['id'][0] show_url = KAN_URL + '/Program/?catId=' + show_id trace("URL for show {}: {}".format(show_id, show_url)) show_page = read_url(show_url) parsed = BeautifulSoup(show_page, "html.parser") items = parsed.find_all('li', class_="program_list_item w-clearfix") trace("got items: " + str(len(items))) for item in items: titles = item.find_all('h2') title = titles[0].string iframe = item.find_all('iframe')[0] youtube_url = iframe['src'] #trace("Youtube URL: {}.".format(youtube_url)) youtube_id = re.sub('.*/embed/([0-9A-Za-z]+)(\?.*)?', r'\1', youtube_url) trace("Add link for ID {} ({}).".format(youtube_id, title.encode('utf-8'))) url = 'plugin://plugin.video.youtube/play/?video_id={}'.format(youtube_id) li = xbmcgui.ListItem(title) li.setProperty('IsPlayable','true') page.add_directory_item(url=url, listitem=li, totalItems=len(items)) page.end_directory() def main_page(page): url = page.build_url({'mode': 'shows', 'name': 'programs'}) li = xbmcgui.ListItem(u'תוכניות טלוויזיה') page.add_directory_item(url=url, listitem=li, isFolder=True) url = page.build_url({'mode': 'shows', 'name': 'digital'}) li = xbmcgui.ListItem(u'תוכניות רשת') page.add_directory_item(url=url, listitem=li, isFolder=True) page.placeholder_item('new-items', u'קטעים חדשים') page.end_directory() def main(): page = Page(sys.argv) trace(' | '.join(sys.argv)) trace("{}".format(page)) if page.mode is not None: mode = page.mode[0] if page.mode is None: main_page(page) elif mode == 'shows': video_top_menu(page, page.args['name'][0]) elif mode == 'show': show_menu(page) elif mode == 'placeholder': name = page.args['name'][0] page.placeholder_folder(name) else: trace("No handler for mode '{}'".format(mode)) if __name__ == '__main__': main()