summaryrefslogtreecommitdiff
path: root/plugin.video.iplayerwww
diff options
context:
space:
mode:
authorCaptainTK <CaptainTK@users.noreply.github.com>2017-03-22 03:37:02 +0100
committerenen92 <enen92@users.noreply.github.com>2017-03-22 02:37:02 +0000
commitb89a149740c83b53d73a07042015498044bfe0a1 (patch)
tree38fd727b0ba2478361da831fdc91d5d82c914819 /plugin.video.iplayerwww
parentaefa7d3d72e3a461ec6db79fe305023395118cf1 (diff)
[plugin.video.iplayerwww] 3.0.1 (#1071)
Diffstat (limited to 'plugin.video.iplayerwww')
-rw-r--r--plugin.video.iplayerwww/addon.xml9
-rw-r--r--plugin.video.iplayerwww/default.py3
-rw-r--r--plugin.video.iplayerwww/resources/lib/ipwww_video.py237
-rw-r--r--plugin.video.iplayerwww/resources/settings.xml2
4 files changed, 241 insertions, 10 deletions
diff --git a/plugin.video.iplayerwww/addon.xml b/plugin.video.iplayerwww/addon.xml
index c5ac661..d96d770 100644
--- a/plugin.video.iplayerwww/addon.xml
+++ b/plugin.video.iplayerwww/addon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<addon id="plugin.video.iplayerwww" name="iPlayer WWW" version="3.0.0" provider-name="CaptainT, Cas, ihurst, primaeval">
+<addon id="plugin.video.iplayerwww" name="iPlayer WWW" version="3.0.1" provider-name="CaptainT, Cas, ihurst, primaeval">
<requires>
<import addon="xbmc.python" version="2.25.0"/>
<import addon="script.module.requests" version="2.7.0"/>
@@ -23,6 +23,13 @@
<fanart>resources/fanart.jpg</fanart>
</assets>
<news>
+v3.0.1
+Optimized selection of catchup CDN internally.
+COMPATIBILITY NOTE: Users need to set catchup source to "Any" when Autoplay is switched off
+to get a choice of all CDNs.
+Additional programme properties for better shortcut handling within Kodi.
+Fixed Channel A-Z.
+
v3.0.0
Initial release for Kodi Krypton.
Support for DASH streams if inputstream.adaptive add-on is available.
diff --git a/plugin.video.iplayerwww/default.py b/plugin.video.iplayerwww/default.py
index 47d3eb9..95264a8 100644
--- a/plugin.video.iplayerwww/default.py
+++ b/plugin.video.iplayerwww/default.py
@@ -196,6 +196,9 @@ elif mode == 132:
elif mode == 133:
Radio.AddAvailableLiveStreamsDirectory(name, url, iconimage)
+elif mode == 134:
+ Video.ScrapeAtoZEpisodes(url)
+
elif mode == 136:
Radio.GetPage(url)
diff --git a/plugin.video.iplayerwww/resources/lib/ipwww_video.py b/plugin.video.iplayerwww/resources/lib/ipwww_video.py
index b6dc3ac..31274c4 100644
--- a/plugin.video.iplayerwww/resources/lib/ipwww_video.py
+++ b/plugin.video.iplayerwww/resources/lib/ipwww_video.py
@@ -82,7 +82,7 @@ def ListRedButton():
('sport_stream_21b', 'BBC Red Button 21b'),
('sport_stream_22b', 'BBC Red Button 22b'),
('sport_stream_23b', 'BBC Red Button 23b'),
- ('sport_stream_24b', 'BBC Red Button 24b'),
+ ('sport_stream_24b', 'BBC Red Button 24b'),
]
iconimage = xbmc.translatePath('special://home/addons/plugin.video.iplayerwww/media/red_button.png')
for id, name in channel_list:
@@ -184,7 +184,7 @@ def ListChannelAtoZ():
iconimage = xbmc.translatePath(
os.path.join('special://home/addons/plugin.video.iplayerwww/media', img + '.png'))
url = "http://www.bbc.co.uk/%s/a-z" % id
- AddMenuEntry(name, url, 128, iconimage, '', '')
+ AddMenuEntry(name, url, 134, iconimage, '', '')
def GetAtoZPage(url):
@@ -444,6 +444,195 @@ def ScrapeEpisodes(page_url):
pDialog.close()
+def ScrapeAtoZEpisodes(page_url):
+ """Creates a list of programmes on one standard HTML page.
+
+ ScrapeEpisodes contains a number of special treatments, which are only needed for
+ specific pages, e.g. Search, but allows to use a single function for all kinds
+ of pages.
+ """
+
+ pDialog = xbmcgui.DialogProgressBG()
+ pDialog.create(translation(30319))
+
+ html = OpenURL(page_url)
+
+ total_pages = 1
+ current_page = 1
+ page_range = range(1)
+ paginate = re.search(r'<ul class="pagination.*?</ul>', html, re.DOTALL)
+ next_page = 1
+ if paginate:
+ page_base_url_match = re.search(r'(.+?)page=', page_url)
+ if page_base_url_match:
+ page_base_url = page_base_url_match.group(0)
+ else:
+ page_base_url = page_url+"?page="
+ if int(ADDON.getSetting('paginate_episodes')) == 0:
+ current_page_match = re.search(r'page=(\d*)', page_url)
+ if current_page_match:
+ current_page = int(current_page_match.group(1))
+ page_base_url_match = re.search(r'(.+?)page=', page_url)
+ if page_base_url_match:
+ page_base_url = page_base_url_match.group(0)
+ else:
+ page_base_url = page_url+"?page="
+ page_range = range(current_page, current_page+1)
+ next_page_match = re.search(r'pagination__item--next">\n.+?<a href="\?page=(.*?)"',
+ paginate.group(0),
+ re.DOTALL)
+ if next_page_match:
+ next_page = int(next_page_match.group(1))
+ else:
+ next_page = current_page
+ page_range = range(current_page, current_page+1)
+ else:
+ pages = re.findall(r'pagination__item--page">.+?<a href=".+?"',paginate.group(0),re.DOTALL)
+ if pages:
+ last = pages[-1]
+ last_page = re.search(r'<a href="\?page=(.*?)"',last)
+ total_pages = int(last_page.group(1))
+ page_range = range(1, total_pages+1)
+
+ for page in page_range:
+
+ if page > current_page:
+ page_url = page_base_url + str(page)
+ html = OpenURL(page_url)
+
+ # NOTE remove inner li to match outer li
+
+ # <li data-version-type="hd">
+ html = re.compile(r'<li data-version-type.*?</li>',
+ flags=(re.DOTALL | re.MULTILINE)).sub('', html)
+
+ # <li class="list-item programme" data-ip-id="p026f2t4">
+ list_items = re.findall(r'<li class="list-item.*?</li>', html, flags=(re.DOTALL | re.MULTILINE))
+
+ list_item_num = 1
+
+ for li in list_items:
+
+ search_group = False
+
+ main_url = None
+ # <a href="/iplayer/episode/b08jny1j/antiques-road-trip-series-13-reversions-episode-10"
+ # title="Antiques Road Trip, Series 13 Reversions: Episode 10" class="list-item__main-link">
+ url_match = re.search(
+ r'<a.*?href="(.*?)".*?list-item__main-link.*?>',
+ li, flags=(re.DOTALL | re.MULTILINE))
+ if url_match:
+ url = url_match.group(1)
+ if url:
+ main_url = 'http://www.bbc.co.uk' + url
+
+ name = ''
+ title = ''
+ #<h1 class="list-item__title typo typo--bold typo--goose">Antiques Road Trip</h1>
+ title_match = re.search(
+ r'<h1 class="list-item__title.+?">\s*(.*?)\s*</h1>',
+ li, flags=(re.DOTALL | re.MULTILINE))
+ if title_match:
+ title = title_match.group(1)
+ name = title
+
+ subtitle = None
+ # <h2 class="list-item__programme-info__subtitle typo typo--skylark">
+ # Series 39: 14. Burton Constable 2</h2>
+ subtitle_match = re.search(
+ r'<h2 class="list-item__programme-info__subtitle.+?">\s*(.*?)\s*</h2>',
+ li, flags=(re.DOTALL | re.MULTILINE))
+ if subtitle_match:
+ subtitle = subtitle_match.group(1)
+ if subtitle:
+ name = name + " - " + subtitle
+
+ icon = ''
+ # <source srcset="http://ichef.bbci.co.uk/images/ic/336x189/p04cd999.jpg"
+ icon_match = re.search(
+ r'<source.*?srcset="https://ichef.bbci.co.uk/images/ic/.*?/(.*?)\.jpg',
+ li, flags=(re.DOTALL | re.MULTILINE))
+ if icon_match:
+ image = icon_match.group(1)
+ if image:
+ icon = "https://ichef.bbci.co.uk/images/ic/832x468/" + image + ".jpg"
+
+
+ type = None
+ synopsis = ''
+ # <p class="list-item__programme-info__synopsis">
+ # Take an exclusive first look at this year’s candidates.
+ # </p>
+ synopsis_match = re.search(
+ r'<p class="list-item__programme-info__synopsis">\s*(.*?)\s*</p>',
+ li, flags=(re.DOTALL | re.MULTILINE))
+ if synopsis_match:
+ synopsis = synopsis_match.group(1)
+
+ aired = ''
+ # <p class="metadata__item typo typo--bullfinch">First shown: 10 Jun 2016</p>
+ release_match = re.search(
+ r'<p class="metadata__item.*?>First shown:\s*(.*?)</p>',
+ li, flags=(re.DOTALL | re.MULTILINE))
+ if release_match:
+ release = release_match.group(1)
+ if release:
+ aired = FirstShownToAired(release)
+
+ episodes = None
+ # <div class="list-item__episodes-button
+ # list-item__episodes-button--only-bp3 gel-layout__item">
+ # <a href="/iplayer/episodes/b07gx71q"
+ # class="button button--with-link button--left-align button--full-width ">
+ episodes_match = re.search(
+ r'<div class="list-item__episodes-button.+?href="(.*?)"',
+ li, flags=(re.DOTALL | re.MULTILINE))
+ if episodes_match:
+ episodes = episodes_match.group(1)
+
+ more = None
+ # <span class="button__text typo typo--bullfinch typo--bold">12 available episodes</span>
+ more_match = re.search(
+ r'<span class="button__text.+?">(.*?) available episodes</span>',
+ li, flags=(re.DOTALL | re.MULTILINE))
+ if more_match:
+ more = more_match.group(1)
+
+ if episodes:
+ episodes_url = 'http://www.bbc.co.uk' + episodes
+ if search_group:
+ AddMenuEntry('[B]%s[/B] - %s' % (title, translation(30318)),
+ episodes_url, 128, icon, '', '')
+ else:
+ AddMenuEntry('[B]%s[/B] - %s %s' % (title, more, translation(30313)),
+ episodes_url, 128, icon, '', '')
+ elif more:
+ AddMenuEntry('[B]%s[/B] - %s %s' % (title, more, translation(30313)),
+ main_url, 128, icon, '', '')
+
+ if type != "group":
+ CheckAutoplay(name , main_url, icon, synopsis, aired)
+
+ percent = int(100*(page+list_item_num/len(list_items))/total_pages)
+ pDialog.update(percent,translation(30319),name)
+
+ list_item_num += 1
+
+ percent = int(100*page/total_pages)
+ pDialog.update(percent,translation(30319))
+
+ if int(ADDON.getSetting('paginate_episodes')) == 0:
+ if current_page < next_page:
+ page_url = page_base_url + str(next_page)
+ AddMenuEntry(" [COLOR ffffa500]%s >>[/COLOR]" % translation(30320), page_url, 134, '', '', '')
+
+ xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE)
+ xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_DATE)
+ xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_UNSORTED)
+
+ pDialog.close()
+
+
def ScrapeMarkup(markup):
"""Creates a list of programmes of a markup response.
@@ -866,6 +1055,12 @@ def ListMostPopular():
def AddAvailableStreamItem(name, url, iconimage, description):
"""Play a streamm based on settings for preferred catchup source and bitrate."""
stream_ids = ScrapeAvailableStreams(url)
+ if stream_ids['name']:
+ name = stream_ids['name']
+ if not iconimage or iconimage == u"DefaultVideo.png" and stream_ids['image']:
+ iconimage = stream_ids['image']
+ if stream_ids['description']:
+ description = stream_ids['description']
if stream_ids['stream_id_ad']:
streams_all = ParseStreamsHLSDASH(stream_ids['stream_id_ad'])
elif stream_ids['stream_id_sl']:
@@ -927,6 +1122,12 @@ def GetAvailableStreams(name, url, iconimage, description):
"""Calls AddAvailableStreamsDirectory based on user settings"""
#print url
stream_ids = ScrapeAvailableStreams(url)
+ if stream_ids['name']:
+ name = stream_ids['name']
+ if stream_ids['image']:
+ iconimage = stream_ids['image']
+ if stream_ids['description']:
+ description = stream_ids['description']
AddAvailableStreamsDirectory(name, stream_ids['stream_id_st'], iconimage, description)
# If we searched for Audio Described programmes and they have been found, append them to the list.
if stream_ids['stream_id_ad']:
@@ -1095,6 +1296,9 @@ def PlayStream(name, url, iconimage, description, subtitles_url):
liz.setInfo(type='Video', infoLabels={'Title': name})
liz.setProperty("IsPlayable", "true")
liz.setPath(url)
+ if ADDON.getSetting('stream_protocol') == '0':
+ liz.setProperty('inputstreamaddon', 'inputstream.adaptive')
+ liz.setProperty('inputstream.adaptive.manifest_type', 'mpd')
if subtitles_url and ADDON.getSetting('subtitles') == 'true':
subtitles_file = download_subtitles(subtitles_url)
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)
@@ -1155,16 +1359,19 @@ def ParseStreams(stream_id):
match = re.compile(
'connection authExpires=".+?href="(.+?)".+?supplier="mf_(.+?)".+?transferFormat="(.+?)"'
).findall(html)
+ source = int(ADDON.getSetting('catchup_source'))
for m3u8_url, supplier, transfer_format in match:
tmp_sup = 0
tmp_br = 0
if transfer_format == 'hls':
- if supplier == 'akamai_uk_hls':
+ if supplier == 'akamai_uk_hls' and source in [0,1]:
tmp_sup = 1
- elif supplier == 'limelight_uk_hls':
+ elif supplier == 'limelight_uk_hls' and source in [0,2]:
tmp_sup = 2
- elif supplier == 'bidi_uk_hls':
+ elif supplier == 'bidi_uk_hls' and source in [0,3]:
tmp_sup = 3
+ else:
+ continue
m3u8_breakdown = re.compile('(.+?)iptv.+?m3u8(.+?)$').findall(m3u8_url)
#print m3u8_breakdown
# print m3u8_url
@@ -1197,10 +1404,12 @@ def ParseStreams(stream_id):
tmp_sup = 0
tmp_br = 0
if transfer_format == 'hls':
- if supplier == 'akamai_hls_open':
+ if supplier == 'akamai_hls_open' and source in [0,1]:
tmp_sup = 1
- elif supplier == 'limelight_hls_open':
+ elif supplier == 'limelight_hls_open' and source in [0,2]:
tmp_sup = 2
+ else:
+ continue
m3u8_breakdown = re.compile('.+?master.m3u8(.+?)$').findall(m3u8_url)
# print m3u8_url
# print m3u8_breakdown
@@ -1376,6 +1585,18 @@ def ParseLiveDASHStreams(channelname):
def ScrapeAvailableStreams(url):
# Open page and retrieve the stream ID
html = OpenURL(url)
+ name = None
+ match = re.search(r'<meta property="og:title" content="(.*?)"', html, re.DOTALL)
+ if match:
+ name = match.group(1)
+ image = None
+ match = re.search(r'<meta property="og:image" content="(.*?)"', html, re.DOTALL)
+ if match:
+ image = match.group(1)
+ description = None
+ match = re.search(r'<meta property="og:description" content="(.*?)"', html, re.DOTALL)
+ if match:
+ description = match.group(1)
# Search for standard programmes.
stream_id_st = re.compile('"vpid":"(.+?)"').findall(html)
# Optionally, Signed programmes can be searched for. These have a different ID.
@@ -1392,7 +1613,7 @@ def ScrapeAvailableStreams(url):
# print stream_id_ad
else:
stream_id_ad = []
- return {'stream_id_st': stream_id_st, 'stream_id_sl': stream_id_sl, 'stream_id_ad': stream_id_ad}
+ return {'stream_id_st': stream_id_st, 'stream_id_sl': stream_id_sl, 'stream_id_ad': stream_id_ad, 'name': name, 'image':image, 'description': description}
def CheckAutoplay(name, url, iconimage, plot, aired=None):
diff --git a/plugin.video.iplayerwww/resources/settings.xml b/plugin.video.iplayerwww/resources/settings.xml
index af3ed8b..7f2b970 100644
--- a/plugin.video.iplayerwww/resources/settings.xml
+++ b/plugin.video.iplayerwww/resources/settings.xml
@@ -44,7 +44,7 @@
<setting id="streams_autoplay" label="30205" type="bool" default="true" />
<setting label="30101" type="lsep" />
<setting id="stream_protocol" label="30212" type="enum" values="DASH|HLS" default="0" />
- <setting id="catchup_source" label="30210" type="enum" values="Any|Akamai|Limelight|Bidi" default="0" enable="eq(-3,true)" />
+ <setting id="catchup_source" label="30210" type="enum" values="Any|Akamai|Limelight|Bidi" default="0" enable="true" />
<setting id="catchup_bitrate" label="30211" type="enum" values="Highest|0.8 Mbps|1.0 Mbps|1.5 Mbps|1.8 Mbps|2.4 Mbps|3.1 Mbps|5.5 Mbps" default="0" enable="eq(-4,true) + eq(-2,1)" />
<setting id="live_source" label="30220" type="enum" values="Any|Akamai|Limelight" default="0" enable="eq(-5,true)" />
<setting id="live_bitrate" label="30230" type="enum" values="Highest|0.1 Mbps|0.2 Mbps|0.3 Mbps|0.6 Mbps|1.0 Mbps|1.8 Mbps|3.1 Mbps|5.5 Mbps" default="0" enable="eq(-6,true) + eq(-4,1)" />