[39680d]: plugin.video.newyorktimes / addon.py Maximize Restore History

Download this file

addon.py    129 lines (98 with data), 3.8 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/env python
'''
New York Times XBMC Addon
-------------------------
Watch video from The New York Times.
http://video.on.nytimes.com/
'''
import re
from urlparse import urljoin
from BeautifulSoup import BeautifulSoup as BS
from brightcove.api import Brightcove
from xbmcswift import Plugin, download_page
from resources.lib.brightcove import item_from_video
__author__ = 'Jonathan Beluch (jbel)'
__license__ = 'GPLv3'
__version__ = '0.1'
PLUGIN_NAME = 'New York Times'
PLUGIN_ID = 'plugin.video.newyorktimes'
plugin = Plugin(PLUGIN_NAME, PLUGIN_ID, __file__)
# NYT Brightcove read-only api token
TOKEN = 'cE97ArV7TzqBzkmeRVVhJ8O6GWME2iG_bRvjBTlNb4o.'
BASE_URL = 'http://video.nytimes.com/'
VIDEO_URL = 'http://video.nytimes.com/video'
def full_url(path):
'''Returns a full url for a given path.'''
return urljoin(BASE_URL, path)
def htmlify(url):
'''Returns a BeautifulSoup object for a given url.'''
return BS(download_page(url))
def parse_reference_id(url):
'''Returns the reference id for a give topic URL on the NYT
website.
Returns the first match of a string of digits between two forward
slashes.
>>> parse_reference_id('foo/23bar/456/789/')
456
'''
ptn = re.compile(r'/(\d+)/')
match = ptn.search(url)
if match:
return match.group(1)
return None
@plugin.route('/')
def show_topics():
'''Shows all topics found on the New York Times video page. This
includes subtopics. Subtopic lables will be prefixed with the
parent topic.
For example, if 'Asia' is a subtopic underneath 'World News', the
label will read 'World News: Asia'.
'''
def get_child_items(parent, sibling):
'''Return items for child topics.'''
def make_label(label, prefix):
'''Some subtopics already contain the parent label so in
this case just return as is.
'''
if label.startswith(prefix):
return label
return '%s: %s' % (prefix, label)
parent_label = parent.a.string
topics = sibling.findAll('li')
items = [{
'label': make_label(topic.a.string, parent_label),
'url': plugin.url_for('show_videos',
reference_id=parse_reference_id(topic.a['href'])),
} for topic in topics]
return items
html = htmlify(VIDEO_URL)
nav = html.find('td', {'id': 'leftNav'})
topics = nav.findAll('li', {'id': lambda _id: _id and
_id.startswith('leftNavParent')})
# Create items for all the parent topics
items = [{
'label': topic.a.string,
'url': plugin.url_for('show_videos',
reference_id=parse_reference_id(
topic.a['href'])),
} for topic in topics]
# In the NYT source, each of the child topics is not located inside
# the parent tag, instead it is the next sibling tag
for topic in topics:
if topic.findNextSibling('li')['id'].startswith('leftNavChild'):
items.extend(get_child_items(topic, topic.findNextSibling('li')))
# Sort the items alphabetically so the sub topics appear clustered
# with the parent topic
sorted_items = sorted(items, key=lambda i: i['label'])
return plugin.add_items(sorted_items)
@plugin.route('/videos/<reference_id>/')
def show_videos(reference_id):
'''Displays all videos available for a given playlist. The order is
the default order returned by the Brightcove API.
'''
brightcove = Brightcove(TOKEN)
playlist = brightcove.find_playlist_by_reference_id(reference_id)
items = [item_from_video(video) for video in playlist.videos]
return plugin.add_items(items)
if __name__ == '__main__':
plugin.run()