diff options
author | Martijn Kaijser <martijn@xbmc.org> | 2017-10-20 22:52:50 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-20 22:52:50 +0200 |
commit | c27e128dd18ff1e009f08809246196c0ac0c9176 (patch) | |
tree | 55cb4e1227a17239011e9ae3161fc0a4374ca4ed | |
parent | c84ee3ed9364f8ab40f6bca301c8269f7cc671d6 (diff) | |
parent | 96bf332f738f87dcca3b2869ccb4b32495a0a42b (diff) |
Merge pull request #1458 from LS80/krypton-ecbtv-0-2-0
[plugin.video.ecbtv] 0.3.0
-rw-r--r-- | plugin.video.ecbtv/LICENSE | 21 | ||||
-rw-r--r-- | plugin.video.ecbtv/addon.py | 86 | ||||
-rw-r--r-- | plugin.video.ecbtv/addon.xml | 25 | ||||
-rw-r--r-- | plugin.video.ecbtv/resources/__init__.py | 0 | ||||
-rw-r--r-- | plugin.video.ecbtv/resources/fanart.jpg | bin | 0 -> 293139 bytes | |||
-rw-r--r-- | plugin.video.ecbtv/resources/icon.png | bin | 0 -> 48179 bytes | |||
-rw-r--r-- | plugin.video.ecbtv/resources/language/resource.language.en_gb/strings.po | 21 | ||||
-rw-r--r-- | plugin.video.ecbtv/resources/lib/__init__.py | 0 | ||||
-rw-r--r-- | plugin.video.ecbtv/resources/lib/api.py | 157 |
9 files changed, 310 insertions, 0 deletions
diff --git a/plugin.video.ecbtv/LICENSE b/plugin.video.ecbtv/LICENSE new file mode 100644 index 0000000..b5d48b2 --- /dev/null +++ b/plugin.video.ecbtv/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Lee Smith + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugin.video.ecbtv/addon.py b/plugin.video.ecbtv/addon.py new file mode 100644 index 0000000..fc87873 --- /dev/null +++ b/plugin.video.ecbtv/addon.py @@ -0,0 +1,86 @@ +############################################################################### +# +# MIT License +# +# Copyright (c) 2017 Lee Smith +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +############################################################################### + +from kodiswift import Plugin + +from resources.lib import api + + +plugin = Plugin() + + +def items(videos): + for video in videos: + yield { + 'thumbnail': video.thumbnail, + 'path': video.url, + 'info': { + 'title': video.title, + 'date': video.date.strftime('%d.%m.%Y'), + 'duration': video.duration + }, + 'is_playable': True + } + + +def categories(): + yield {'label': "[B]{}[/B]".format(plugin.get_string(30001)), + 'path': plugin.url_for('search')} + for title, path in api.categories(): + yield {'label': title, 'path': plugin.url_for('show_videos', path=path)} + + +@plugin.route('/') +def index(): + return plugin.finish(categories()) + + +@plugin.route('/category/<path>') +def show_videos(path): + return plugin.finish( + items(api.videos(path)), + sort_methods=['playlist_order', 'date', 'title', 'duration'] + ) + + +@plugin.route('/search') +def search(): + query = plugin.keyboard(heading=plugin.get_string(30001)) + if query: + url = plugin.url_for('search_result', query=query) + plugin.redirect(url) + + +@plugin.route('/search/<query>') +def search_result(query): + return plugin.finish( + items(api.search_results(query, size=11)), + sort_methods=['playlist_order', 'date', 'title', 'duration'] + ) + + +if __name__ == '__main__': + plugin.run() diff --git a/plugin.video.ecbtv/addon.xml b/plugin.video.ecbtv/addon.xml new file mode 100644 index 0000000..d9a66c6 --- /dev/null +++ b/plugin.video.ecbtv/addon.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<addon id="plugin.video.ecbtv" name="ECB TV" version="0.3.0" provider-name="Leopold"> + <requires> + <import addon="xbmc.python" version="2.25.0"/> + <import addon="script.module.kodiswift" version="0.0.8" optional="false"/> + <import addon="script.module.beautifulsoup4" version="4.3.1" optional="false"/> + <import addon="script.module.requests" version="2.4.3" optional="false"/> + </requires> + <extension point="xbmc.python.pluginsource" library="addon.py"> + <provides>video</provides> + </extension> + <extension point="xbmc.addon.metadata"> + <platform>all</platform> + <language>en</language> + <summary lang="en_gb">Watch videos from ECB TV</summary> + <description lang="en_gb">This video plugin provides access to the videos from the official site of the England and Wales Cricket Board.</description> + <website>http://www.ecb.co.uk</website> + <source>https://github.com/LS80/plugin.video.ecbtv.git</source> + <license>MIT</license> + <assets> + <icon>resources/icon.png</icon> + <fanart>resources/fanart.jpg</fanart> + </assets> + </extension> +</addon> diff --git a/plugin.video.ecbtv/resources/__init__.py b/plugin.video.ecbtv/resources/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/plugin.video.ecbtv/resources/__init__.py diff --git a/plugin.video.ecbtv/resources/fanart.jpg b/plugin.video.ecbtv/resources/fanart.jpg Binary files differnew file mode 100644 index 0000000..0016d16 --- /dev/null +++ b/plugin.video.ecbtv/resources/fanart.jpg diff --git a/plugin.video.ecbtv/resources/icon.png b/plugin.video.ecbtv/resources/icon.png Binary files differnew file mode 100644 index 0000000..5a85c2b --- /dev/null +++ b/plugin.video.ecbtv/resources/icon.png diff --git a/plugin.video.ecbtv/resources/language/resource.language.en_gb/strings.po b/plugin.video.ecbtv/resources/language/resource.language.en_gb/strings.po new file mode 100644 index 0000000..f7b1d15 --- /dev/null +++ b/plugin.video.ecbtv/resources/language/resource.language.en_gb/strings.po @@ -0,0 +1,21 @@ +# Kodi Media Center language file +# Addon Name: ECB TV +# Addon id: plugin.video.ecbtv +# Addon Provider: Leopold +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: English (http://www.transifex.com/projects/p/xbmc-addons/language/en/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30001" +msgid "Search" +msgstr "" diff --git a/plugin.video.ecbtv/resources/lib/__init__.py b/plugin.video.ecbtv/resources/lib/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/plugin.video.ecbtv/resources/lib/__init__.py diff --git a/plugin.video.ecbtv/resources/lib/api.py b/plugin.video.ecbtv/resources/lib/api.py new file mode 100644 index 0000000..6f57dcd --- /dev/null +++ b/plugin.video.ecbtv/resources/lib/api.py @@ -0,0 +1,157 @@ +############################################################################### +# +# MIT License +# +# Copyright (c) 2017 Lee Smith +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +############################################################################### + +''' +Module for extracting video links from the England and Wales Cricket Board website +''' + +import json +import os +from urlparse import urljoin, urlparse, urlunparse +from urllib import urlencode +from datetime import datetime +import time +from collections import namedtuple + +import requests +from bs4 import BeautifulSoup + +HOST = 'http://www.ecb.co.uk' +BASE_URL = urljoin(HOST, 'tv/') + +HLS_HOST = 'https://secure.brightcove.com/' +HLS_URL_FMT = urljoin(HLS_HOST, 'services/mobile/streaming/index/master.m3u8?videoId={}') + +SEARCH_URL = 'https://content-ecb.pulselive.com/search/ecb/' + + +Video = namedtuple('Video', 'title url thumbnail date duration') + + +def _search_url(term, start, size): + '''Returns a URL for the JSON search api''' + url_parts = list(urlparse(SEARCH_URL)) + query_params = dict( + type='VIDEO', + fullObjectResponse=True, + terms=term, + size=size, + start=start + ) + url_parts[4] = urlencode(query_params) + return urlunparse(url_parts) + + +def _soup(path=''): + '''Returns a BeautifulSoup tree for the specified path''' + url = urljoin(BASE_URL, path) + response = requests.get(url) + return BeautifulSoup(response.text, 'html.parser') + + +def _date_from_str(date_str, fmt='%d %B %Y'): + '''Returns a data object from a string. + datetime.strptime is avoided due to a Python issue in Kodi''' + return datetime(*(time.strptime(date_str, fmt)[0:6])).date() + + +def _date(media_item): + '''Returns a date object from the HTML media item.''' + date_str = media_item.find('time', 'media__sub-meta').string + return _date_from_str(date_str) + + +def _date_json(json_item): + '''Returns a date object from the JSON item. + The date can be one of two formats''' + date_str = json_item['date'] + for fmt in ['%Y-%m-%dT%H:%M', '%d/%m/%Y %H:%M']: + try: + date = _date_from_str(date_str.strip(), fmt=fmt) + except ValueError as exc: + continue + else: + return date + raise exc + + +def categories(): + '''Generator for category names and links, excluding all that appear before Home''' + start = False + for submenu_link in _soup()('a', 'submenu__link'): + title = submenu_link.string.strip() + if start and title != 'All Categories': + yield title, os.path.basename(submenu_link['href']) + if title == 'Home': + start = True + + +def videos(path): + '''Generator for all videos from a particular page''' + for media_item in _soup(path)('a', 'media__item'): + video = json.loads(media_item['data-ui-args']) + yield Video( + title=media_item.find('span', 'media__title').string, + url=HLS_URL_FMT.format(video['mediaId']), + thumbnail=media_item.picture.img['data-highres-img'], + date=_date(media_item), + duration=int(video['duration'].replace(',', '')) + ) + + +def search_results(term, start=0, size=10): + '''Generator for videos matching a search term''' + results = requests.get(_search_url(term, start, size)).json()['hits']['hit'] + for result in results: + video = result['response'] + yield Video( + title=video['title'], + url=HLS_URL_FMT.format(video['mediaId']), + thumbnail=video['imageUrl'], + date=_date_json(video), + duration=video['duration'] + ) + + +def _print_all_videos(): + '''Test function to print all categories and videos''' + for title, path in categories(): + print '{} ({})'.format(title, path) + for video in videos(path): + print '\t', video.title + + +def _print_search_results(term): + '''Test function to print search results''' + print 'Search: {}'.format(term) + for video in search_results(term): + print '\t', video.title + + +if __name__ == '__main__': + _print_all_videos() + print + _print_search_results('test cricket') |