The branch, dharma has been updated
via 4eb7d99a37e97cd8af1c3be4eb872f6bbb203f95 (commit)
from 6a4741b07c332ba564bcb6b407ec836fab7c93c9 (commit)
- Log -----------------------------------------------------------------
http://xbmc.git.sourceforge.net/git/gitweb.cgi?p=xbmc/plugins;a=commit;h=4eb7d99a37e97cd8af1c3be4eb872f6bbb203f95
commit 4eb7d99a37e97cd8af1c3be4eb872f6bbb203f95
Author: spiff <[email protected]>
Date: Fri Feb 24 14:30:58 2012 +0100
[plugin.video.ted.talks] updated to version 2.3.1
diff --git a/plugin.video.ted.talks/addon.xml b/plugin.video.ted.talks/addon.xml
index acda7f1..bf33f86 100644
--- a/plugin.video.ted.talks/addon.xml
+++ b/plugin.video.ted.talks/addon.xml
@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.ted.talks"
name="TED Talks"
- version="2.2.6"
- provider-name="rwparris2">
+ version="2.3.1"
+ provider-name="rwparris2, moreginger">
<requires>
<import addon="xbmc.python" version="1.0"/>
<import addon="script.module.simplejson" version="2.0.10"/>
<import addon="script.module.beautifulsoup" version="3.0.8"/>
+ <import addon="script.module.elementtree" version="1.2.7"/>
</requires>
<extension point="xbmc.python.pluginsource"
library="default.py">
diff --git a/plugin.video.ted.talks/changelog.txt
b/plugin.video.ted.talks/changelog.txt
index 0f7105f..e0295f0 100644
--- a/plugin.video.ted.talks/changelog.txt
+++ b/plugin.video.ted.talks/changelog.txt
@@ -1,3 +1,17 @@
+[B]Version 2.3.1[/B]
+Works on Dharma again
+Newest Talks now work on Eden+Win32
+Remove duplicates of some themes
+
+[B]Version 2.3.0[/B]
+Get new talks from RSS feeds
+Update themes scraper to cope with website changes
+Icons for themes
+Log correct version number for plugin on startup
+
+[B]Version 2.2.6[/B]
+Fix for problem introduced in 2.2.5 where certain talks could not be played.
+
[B]Version 2.2.5[/B]
Fixed playback of certain videos would fail (thanks to moreginger)
diff --git a/plugin.video.ted.talks/default.py
b/plugin.video.ted.talks/default.py
index ef7443d..87e21f7 100644
--- a/plugin.video.ted.talks/default.py
+++ b/plugin.video.ted.talks/default.py
@@ -3,27 +3,15 @@
rwparris2
"""
import sys
+import resources.lib.plugin as plugin
+import resources.lib.model.arguments as arguments
-#plugin constants
-__plugin__ = "TED Talks"
-__author__ = "rwparris2"
-__url__ = "http://code.google.com/p/xbmc-addons/"
-__svn_url__ =
"http://xbmc-addons.googlecode.com/svn/trunk/plugins/video/TED%20Talks"
-__version__ = "2.2.2"
-
-print "[PLUGIN] '%s: version %s' initialized!" % (__plugin__, __version__)
if __name__ == "__main__":
+ plugin.init()
import resources.lib.ted_talks as ted_talks
- if not sys.argv[2]:
- ted_talks.Main()
- elif sys.argv[2].startswith('?addToFavorites'):
-
ted_talks.Main(checkMode=False).addToFavorites(sys.argv[2].split('=')[-1])
- elif sys.argv[2].startswith('?removeFromFavorites'):
-
ted_talks.Main(checkMode=False).removeFromFavorites(sys.argv[2].split('=')[-1])
- elif sys.argv[2].startswith('?downloadVideo'):
- ted_talks.Main(checkMode=False).downloadVid(sys.argv[2].split('=')[-1])
- else:
- ted_talks.Main()
+
+ args_map = arguments.parse_arguments(sys.argv[2])
+ ted_talks.Main(logger = plugin.log, args_map = args_map).run()
sys.modules.clear()
diff --git a/plugin.video.ted.talks/resources/language/English/strings.xml
b/plugin.video.ted.talks/resources/language/English/strings.xml
index 05fbbf8..436a0b9 100644
--- a/plugin.video.ted.talks/resources/language/English/strings.xml
+++ b/plugin.video.ted.talks/resources/language/English/strings.xml
@@ -38,12 +38,12 @@
<string id="30074">Always Ask for Download Location</string>
<!--Context Menu-->
- <!--<string id="13347">Queue item</string>from system-->
<string id="30090">Add to TED.com favorites</string>
<string id="30091">Add to favorites successful</string>
<string id="30092">Add to favorites failed</string>
<string id="30093">Remove from TED.com favorites</string>
<string id="30094">Remove from favorites successful</string>
<string id="30095">Remove from favorites failed</string>
- <string id="30096">Download Video</string>
+ <string id="30096">Download video</string>
+ <string id="30097">Queue</string><!-- Was 13347 from system, but no longer
available. -->
</strings>
\ No newline at end of file
diff --git a/plugin.video.ted.talks/resources/lib/talkDownloader.py
b/plugin.video.ted.talks/resources/lib/talkDownloader.py
index c3e766d..8f829c6 100644
--- a/plugin.video.ted.talks/resources/lib/talkDownloader.py
+++ b/plugin.video.ted.talks/resources/lib/talkDownloader.py
@@ -1,15 +1,14 @@
import urllib
import os.path
-import sys
import xbmc
import xbmcgui
#enable localization
import xbmcaddon
+import plugin
__settings__ = xbmcaddon.Addon(id='plugin.video.ted.talks')
getLS = __settings__.getLocalizedString
-pluginName = sys.modules['__main__'].__plugin__
class Download:
@@ -24,12 +23,12 @@ class Download:
#unicode causes problems here, convert to standard str
self.filename = self.getLegalFilename(self.title.title().replace(' ',
'') + '.mp4')
self.fullDownloadPath = os.path.join(downloadPath, self.filename)
- print '[%s] %s : Attempting to download\n%s --> %s' % (pluginName,
__name__, self.url, self.fullDownloadPath)
+ print '[%s] %s : Attempting to download\n%s --> %s' %
(plugin.__plugin__, __name__, self.url, self.fullDownloadPath)
if self.checkPath(downloadPath, self.filename):
try:
re = urllib.urlretrieve(self.url, self.fullDownloadPath,
reporthook = self.showdlProgress)
- print '[%s] Download Success!' % (pluginName)
+ print '[%s] Download Success!' % (plugin.__plugin__)
except IOError, e:
print e
self.pDialog.close()
diff --git a/plugin.video.ted.talks/resources/lib/ted_talks.py
b/plugin.video.ted.talks/resources/lib/ted_talks.py
index 85d9e88..7e5d0b5 100644
--- a/plugin.video.ted.talks/resources/lib/ted_talks.py
+++ b/plugin.video.ted.talks/resources/lib/ted_talks.py
@@ -1,34 +1,37 @@
import sys
import urllib
import ted_talks_scraper
+from talkDownloader import Download
+from model.fetcher import Fetcher
+from model.user import User
+from model.rss_scraper import NewTalksRss
+from model.favorites_scraper import Favorites
+import menu_util
import xbmc
import xbmcplugin
import xbmcgui
-from talkDownloader import Download
import xbmcaddon
__settings__ = xbmcaddon.Addon(id='plugin.video.ted.talks')
getLS = __settings__.getLocalizedString
-#getLS = xbmc.getLocalizedString
-TedTalks = ted_talks_scraper.TedTalks()
-
-class updateArgs:
-
- def __init__(self, *args, **kwargs):
- for key, value in kwargs.iteritems():
- if value == 'None':
- kwargs[key] = None
- else:
- kwargs[key] = urllib.unquote_plus(kwargs[key])
- self.__dict__.update(kwargs)
+def login(user_scraper, username, password):
+ user_details = user_scraper.login(username, password)
+ if not user_scraper:
+ xbmcgui.Dialog().ok(getLS(30050), getLS(30051))
+ return user_details
class UI:
- def __init__(self):
- self.main = Main(checkMode = False)
+ def __init__(self, logger, get_HTML, ted_talks, user, settings, args):
+ self.logger = logger
+ self.get_HTML = get_HTML
+ self.ted_talks = ted_talks
+ self.user = user
+ self.settings = settings
+ self.args = args
xbmcplugin.setContent(int(sys.argv[1]), 'movies')
def endofdirectory(self, sortMethod = 'title'):
@@ -39,57 +42,48 @@ class UI:
sortMethod = xbmcplugin.SORT_METHOD_DATE
#Sort methods are required in library mode.
xbmcplugin.addSortMethod(int(sys.argv[1]), sortMethod)
- #If name is next or previous, then the script arrived here from a
navItem, and won't to add to the heirarchy
- if self.main.args.name in [getLS(30020), getLS(30021)]:
- dontAddToHierarchy = True
- else:
- dontAddToHierarchy = False
#let xbmc know the script is done adding items to the list.
- xbmcplugin.endOfDirectory(handle = int(sys.argv[1]), updateListing =
dontAddToHierarchy)
+ xbmcplugin.endOfDirectory(handle = int(sys.argv[1]), updateListing =
False)
- def addItem(self, info, isFolder=True):
+ def addItem(self, info, isFolder = True):
#Defaults in dict. Use 'None' instead of None so it is compatible for
quote_plus in parseArgs
+ #create params for xbmcplugin module
+ args = {}
+ for key1, key2 in {'url': 'url', 'mode': 'mode', 'Title': 'name',
'Thumb': 'icon'}.iteritems():
+ if key1 in info:
+ if info[key1] is None:
+ self.logger("'None' in item dict: " + info)
+ else:
+ args[key2] = urllib.quote_plus(info[key1].encode('ascii',
'ignore'))
+
+ u = sys.argv[0] + '?' + "&".join(key + '=' + value for key, value in
args.iteritems())
+
info.setdefault('url', 'None')
info.setdefault('Thumb', 'None')
info.setdefault('Icon', info['Thumb'])
- #create params for xbmcplugin module
- u = sys.argv[0]+\
- '?url='+urllib.quote_plus(info['url'])+\
- '&mode='+urllib.quote_plus(info['mode'])+\
-
'&name='+urllib.quote_plus(info['Title'].encode('ascii','ignore'))+\
- '&icon='+urllib.quote_plus(info['Thumb'])
#create list item
if info['Title'].startswith(" "):
- title = info['Title'][1:]
+ title = info['Title'][1:]
else:
- title = info['Title']
- li=xbmcgui.ListItem(label = title, iconImage = info['Icon'],
thumbnailImage = info['Thumb'])
- li.setInfo(type='Video', infoLabels=info)
+ title = info['Title']
+ li = xbmcgui.ListItem(label = title, iconImage = info['Icon'],
thumbnailImage = info['Thumb'])
+ li.setInfo(type='Video', infoLabels = info)
#for videos, replace context menu with queue and add to favorites
if not isFolder:
li.setProperty("IsPlayable", "true")#let xbmc know this can be
played, unlike a folder.
- #add context menu items to non-folder items.
- contextmenu = [(getLS(13347), 'Action(Queue)')]
- contextmenu += [(getLS(30096), 'RunPlugin(%s?downloadVideo=%s)' %
(sys.argv[0], info['url']))]
- #only add add to favorites context menu if the user has a username
& isn't already looking at favorites.
- if self.main.settings['username']:
- if self.main.args.mode == 'favorites':
- contextmenu += [(getLS(30093),
'RunPlugin(%s?removeFromFavorites=%s)' % (sys.argv[0], info['url']))]
- else:
- contextmenu += [(getLS(30090),
'RunPlugin(%s?addToFavorites=%s)' % (sys.argv[0], info['url']))]
- #replaceItems=True replaces the useless one with the two defined
above.
- li.addContextMenuItems(contextmenu, replaceItems=True)
- #for folders, completely remove contextmenu, as it is totally useless.
+ context_menu = menu_util.create_context_menu(getLS = getLS)
+ li.addContextMenuItems(context_menu, replaceItems = True)
else:
- li.addContextMenuItems([], replaceItems=True)
+ #for folders, completely remove contextmenu, as it is totally
useless.
+ li.addContextMenuItems([], replaceItems = True)
#add item to list
- ok=xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=u,
listitem=li, isFolder=isFolder)
+ xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=u,
listitem=li, isFolder=isFolder)
def playVideo(self):
- video = TedTalks.getVideoDetails(self.main.args.url)
+ video = self.ted_talks.getVideoDetails(self.args['url'])
li=xbmcgui.ListItem(video['Title'],
- iconImage = self.main.args.icon,
- thumbnailImage = self.main.args.icon,
+ iconImage = self.args['icon'],
+ thumbnailImage = self.args['icon'],
path = video['url'])
li.setInfo(type='Video', infoLabels=video)
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, li)
@@ -101,41 +95,43 @@ class UI:
self.addItem({'Title': getLS(30021), 'url':navItems['previous'],
'mode':mode})
def showCategories(self):
- self.addItem({'Title':getLS(30001), 'mode':'newTalks',
'Plot':getLS(30031)})#new
+ self.addItem({'Title':getLS(30001), 'mode':'newTalksRss',
'Plot':getLS(30031)})#new RSS
self.addItem({'Title':getLS(30002), 'mode':'speakers',
'Plot':getLS(30032)})#speakers
self.addItem({'Title':getLS(30003), 'mode':'themes',
'Plot':getLS(30033)})#themes
#self.addItem({'Title':getLS(30004), 'mode':'search',
'Plot':getLS(30034)})#search
- if self.main.settings['username']:
+ if self.settings['username']:
self.addItem({'Title':getLS(30005), 'mode':'favorites',
'Plot':getLS(30035)})#favorites
self.endofdirectory()
-
- def newTalks(self):
- newMode = 'playVideo'
- newTalks = TedTalks.NewTalks(self.main.args.url)
- #add talks to the list
- for talk in newTalks.getNewTalks():
- talk['mode'] = newMode
- self.addItem(talk, isFolder = False)
- #add nav items to the list
- self.navItems(newTalks.navItems, self.main.args.mode)
- #end the list
+
+ def newTalksRss(self):
+ newTalks = NewTalksRss(self.logger)
+ for talk in newTalks.get_new_talks():
+ li = xbmcgui.ListItem(label = talk['title'], iconImage =
talk['thumb'], thumbnailImage = talk['thumb'])
+ li.setProperty("IsPlayable", "true")
+ li.setInfo('video', {'date':talk['date'],
'duration':talk['duration'], 'plot':talk['plot']})
+ favorites_action = None
+ if self.settings['username'] != None:
+ favorites_action = "add"
+ context_menu = menu_util.create_context_menu(getLS = getLS, url =
talk['link'], favorites_action = favorites_action, talkID = talk['id'])
+ li.addContextMenuItems(context_menu, replaceItems = True)
+ xbmcplugin.addDirectoryItem(handle = int(sys.argv[1]), url =
talk['link'], listitem = li)
self.endofdirectory(sortMethod = 'date')
def speakers(self):
newMode = 'speakerVids'
- speakers = TedTalks.Speakers(self.main.args.url)
+ speakers = self.ted_talks.Speakers(self.get_HTML, self.args.get('url'))
#add speakers to the list
for speaker in speakers.getAllSpeakers():
speaker['mode'] = newMode
self.addItem(speaker, isFolder = True)
#add nav items to the list
- self.navItems(speakers.navItems, self.main.args.mode)
+ self.navItems(speakers.navItems, self.args['mode'])
#end the list
self.endofdirectory()
def speakerVids(self):
newMode = 'playVideo'
- speakers = TedTalks.Speakers(self.main.args.url)
+ speakers = self.ted_talks.Speakers(self.get_HTML, self.args.get('url'))
for talk in speakers.getTalks():
talk['mode'] = newMode
self.addItem(talk, isFolder = False)
@@ -144,7 +140,7 @@ class UI:
def themes(self):
newMode = 'themeVids'
- themes = TedTalks.Themes(self.main.args.url)
+ themes = self.ted_talks.Themes(self.get_HTML, self.args.get('url'))
#add themes to the list
for theme in themes.getThemes():
theme['mode'] = newMode
@@ -154,7 +150,7 @@ class UI:
def themeVids(self):
newMode = 'playVideo'
- themes = TedTalks.Themes(self.main.args.url)
+ themes = self.ted_talks.Themes(self.get_HTML, self.args.get('url'))
for talk in themes.getTalks():
talk['mode'] = newMode
self.addItem(talk, isFolder = False)
@@ -163,9 +159,9 @@ class UI:
def favorites(self):
newMode = 'playVideo'
#attempt to login
- if self.main.isValidUser():
- favorites = TedTalks.Favorites()
- for talk in favorites.getFavoriteTalks(self.main.user):
+ userID, realname = login(self.user, self.settings['username'],
self.settings['password'])
+ if userID:
+ for talk in Favorites(self.logger,
self.get_HTML).getFavoriteTalks(userID):
talk['mode'] = newMode
self.addItem(talk, isFolder = False)
self.endofdirectory()
@@ -173,22 +169,13 @@ class UI:
class Main:
- def __init__(self, checkMode = True):
- self.user = None
- self.parseArgs()
+ def __init__(self, logger, args_map):
+ self.logger = logger
+ self.args_map = args_map
self.getSettings()
- if checkMode:
- self.checkMode()
-
- def parseArgs(self):
- # call updateArgs() with our formatted argv to create the self.args
object
- if (sys.argv[2]):
- exec "self.args = updateArgs(%s')" % (sys.argv[2][1:].replace('&',
"',").replace('=', "='"))
- else:
- # updateArgs will turn the 'None' into None.
- # Don't simply define it as None because unquote_plus in
updateArgs will throw an exception.
- # This is a pretty ugly solution, but fuck it :(
- self.args = updateArgs(mode = 'None', url = 'None', name = 'None')
+ self.get_HTML = Fetcher(logger, xbmc.translatePath).getHTML
+ self.user = User(self.get_HTML)
+ self.ted_talks = ted_talks_scraper.TedTalks(self.get_HTML)
def getSettings(self):
self.settings = dict()
@@ -197,32 +184,23 @@ class Main:
self.settings['downloadMode'] = __settings__.getSetting('downloadMode')
self.settings['downloadPath'] = __settings__.getSetting('downloadPath')
- def isValidUser(self):
- self.user = TedTalks.User(self.settings['username'],
self.settings['password'])
- if self.user:
- return True
- else:
- xbmcgui.Dialog().ok(getLS(30050), getLS(30051))
- return False
-
- def addToFavorites(self, url):
- if self.isValidUser():
- successful = TedTalks.Favorites().addToFavorites(self.user, url)
- if successful:
- xbmc.executebuiltin('Notification(%s,%s,)' % (getLS(30000),
getLS(30091)))
+ def set_favorite(self, talkID, is_favorite):
+ """
+ talkID ID for the talk.
+ is_favorite True to set as a favorite, False to unset.
+ """
+ if login(self.user, self.settings['username'],
self.settings['password']):
+ favorites = Favorites(self.logger, self.fetcher.getHTML)
+ if is_favorite:
+ successful = favorites.addToFavorites(talkID)
else:
- xbmc.executebuiltin('Notification(%s,%s,)' % (getLS(30000),
getLS(30092)))
-
- def removeFromFavorites(self, url):
- if self.isValidUser():
- successful = TedTalks.Favorites().removeFromFavorites(self.user,
url)
- if successful:
- xbmc.executebuiltin('Notification(%s,%s,)' % (getLS(30000),
getLS(30094)))
- else:
- xbmc.executebuiltin('Notification(%s,%s,)' % (getLS(30000),
getLS(30095)))
+ successful = favorites.removeFromFavorites(talkID)
+ notification_messages = {(True, True): 30091, (True, False):
30092, (False, True): 30094, (False, False): 30095}
+ notification_message = notification_messages[(is_favorite,
successful)]
+ xbmc.executebuiltin('Notification(%s,%s,)' % (getLS(30000),
getLS(notification_message)))
def downloadVid(self, url):
- video = TedTalks.getVideoDetails(url)
+ video = self.ted_talks.getVideoDetails(url)
if self.settings['downloadMode'] == 'true':
downloadPath = xbmcgui.Dialog().browse(3, getLS(30096), 'files')
else:
@@ -230,21 +208,31 @@ class Main:
if downloadPath:
Download(video['Title'], video['url'], downloadPath)
- def checkMode(self):
- mode = self.args.mode
- if mode is None:
- UI().showCategories()
- elif mode == 'playVideo':
- UI().playVideo()
- elif mode == 'newTalks':
- UI().newTalks()
- elif mode == 'speakers':
- UI().speakers()
- elif mode == 'speakerVids':
- UI().speakerVids()
- elif mode == 'themes':
- UI().themes()
- elif mode == 'themeVids':
- UI().themeVids()
- elif mode == 'favorites':
- UI().favorites()
+ def run(self):
+ # TODO Make these all modes for consistency
+ if 'addToFavorites' in self.args_map:
+ self.set_favorite(self.args_map['addToFavorites'], True)
+ if 'removeFromFavorites' in self.args_map:
+ self.set_favorite(self.args_map['removeFromFavorites'], False)
+ if 'downloadVideo' in self.args_map:
+ self.downloadVid(self.args_map('downloadVideo'))
+
+ ui = UI(self.logger, self.get_HTML, self.ted_talks, self.user,
self.settings, self.args_map)
+ if 'mode' not in self.args_map:
+ ui.showCategories()
+ else:
+ mode = self.args_map['mode']
+ if mode == 'playVideo':
+ ui.playVideo()
+ elif mode == 'newTalksRss':
+ ui.newTalksRss()
+ elif mode == 'speakers':
+ ui.speakers()
+ elif mode == 'speakerVids':
+ ui.speakerVids()
+ elif mode == 'themes':
+ ui.themes()
+ elif mode == 'themeVids':
+ ui.themeVids()
+ elif mode == 'favorites':
+ ui.favorites()
diff --git a/plugin.video.ted.talks/resources/lib/ted_talks_scraper.py
b/plugin.video.ted.talks/resources/lib/ted_talks_scraper.py
index 3cc31da..cc04336 100644
--- a/plugin.video.ted.talks/resources/lib/ted_talks_scraper.py
+++ b/plugin.video.ted.talks/resources/lib/ted_talks_scraper.py
@@ -1,46 +1,73 @@
import re
-import sys
-from ClientForm import ParseResponse
-from util import getHTML, getUrllib2ResponseObject, cleanHTML, resizeImage
+from model.util import cleanHTML, resizeImage
from BeautifulSoup import SoupStrainer, MinimalSoup as BeautifulSoup
+from model.url_constants import URLTED
#MAIN URLS
-URLTED = 'http://www.ted.com'
URLTHEMES = 'http://www.ted.com/themes/atoz/page/'
URLSPEAKERS = 'http://www.ted.com/speakers/atoz/page/'
-URLNEW = 'http://www.ted.com/talks/list/page/'
URLSEARCH = 'http://www.ted.com/search?q=%s/page/'
-URLLOGIN = 'http://www.ted.com/users/signin/'
-URLPROFILE = 'http://www.ted.com/profiles/'
-URLFAVORITES = 'http://www.ted.com/profiles/favorites/id/'
-URLADDFAV ='http://www.ted.com/profiles/addfavorites?id=%s&modulename=talks'
-URLREMFAV ='http://www.ted.com/profiles/removefavorites?id=%s&modulename=talks'
-pluginName = sys.modules['__main__'].__plugin__
+def getNavItems(html):
+ """self.navItems={'next':url, 'previous':url,
'selected':pagenumberasaninteger}"""
+ navItems = {'next':None, 'previous':None, 'selected':1}
+ paginationContainer = SoupStrainer(attrs =
{'class':re.compile('pagination')})
+ for liTag in BeautifulSoup(html, parseOnlyThese =
paginationContainer).findAll('li'):
+ if liTag.has_key('class'):
+ if liTag['class'] == 'next':
+ navItems['next'] = URLTED+liTag.a['href']
+ elif liTag['class'] == 'prev':
+ navItems['previous'] = URLTED+liTag.a['href']
+ elif liTag['class'] == 'selected':
+ navItems['selected'] = int(liTag.a.string)
+ return navItems
+
+
+class NewTalks:
+ """
+ Fetches new talks!
+ """
+
+ def __init__(self, getHTML, getLS):
+ """
+ getHTML method to getHTML from a URL
+ getLS method to get localized string from an integer code
+ """
+ self.getHTML = getHTML
+ self.getLS = getLS
+
+ def getNewTalks(self, url = None):
+ """
+ Returns 2-tuples, first value is whether this is a folder, second is
attributes dict
+ """
+ if url == None:
+ url = 'http://www.ted.com/talks/list/page/'
+ html = self.getHTML(url)
+
+ # Forward/backwards
+ navItems = getNavItems(html)
+ if navItems['next']:
+ yield True, {'mode':'newTalks', 'Title': self.getLS(30020),
'url':navItems['next']}
+ if navItems['previous']:
+ yield True, {'mode':'newTalks', 'Title': self.getLS(30021),
'url':navItems['previous']}
+
+ talkContainers = SoupStrainer(attrs =
{'class':re.compile('talkMedallion')})
+ for talk in BeautifulSoup(html, parseOnlyThese = talkContainers):
+ link = URLTED+talk.dt.a['href']
+ title = cleanHTML(talk.dt.a['title'])
+ pic = resizeImage(talk.find('img', attrs =
{'src':re.compile('.+?\.jpg')})['src'])
+ yield False, {'mode':'playVideo', 'url':link, 'Title':title,
'Thumb':pic}
class TedTalks:
- def getNavItems(self, html):
- """self.navItems={'next':url, 'previous':url,
'selected':pagenumberasaninteger}"""
- navItems = {'next':None, 'previous':None, 'selected':1}
- paginationContainer = SoupStrainer(attrs =
{'class':re.compile('pagination')})
- for liTag in BeautifulSoup(html, parseOnlyThese =
paginationContainer).findAll('li'):
- if liTag.has_key('class'):
- if liTag['class'] == 'next':
- navItems['next'] = URLTED+liTag.a['href']
- elif liTag['class'] == 'prev':
- navItems['previous'] = URLTED+liTag.a['href']
- elif liTag['class'] == 'selected':
- navItems['selected'] = int(liTag.a.string)
- else: #no class attrib found.
- print '[%s] %s no pagination found.' % (pluginName, __name__)
- return navItems
+ def __init__(self, getHTML):
+ self.getHTML = getHTML
def getVideoDetails(self, url):
"""self.videoDetails={Title, Director, Genre, Plot, id, url}"""
#TODO: get 'related tags' and list them under genre
- html = getHTML(url)
+ html = self.getHTML(url)
url = ""
soup = BeautifulSoup(html)
#get title
@@ -63,77 +90,26 @@ class TedTalks:
break
if url == "":
- # look for utub link
- utublinks =
re.compile('http://(?:www.)?youtube.com/v/([^\&]*)\&').findall(html)
- for link in utublinks:
- url =
'plugin://plugin.video.youtube/?action=play_video&videoid=%s' %(link)
+ # look for utub link
+ utublinks =
re.compile('http://(?:www.)?youtube.com/v/([^\&]*)\&').findall(html)
+ for link in utublinks:
+ url =
'plugin://plugin.video.youtube/?action=play_video&videoid=%s' %(link)
#get id from url
id = url.split('/')[-1]
return {'Title':title, 'Director':speaker, 'Genre':'TED', 'Plot':plot,
'PlotOutline':plot, 'id':id, 'url':url}
- class User:
- """makes a user object"""
-
- def __init__(self, username = None, password = None):
- self.username = username
- self.password = password
- if username and password:
- self.id, self.realName = self.getUserDetails()
- else:
- self.id = self.realName = None
-
- def getUserDetails(self):
- html = self.getLoginResponse()
- userContainer = SoupStrainer(attrs =
{'class':re.compile('notices')})
- for aTag in BeautifulSoup(html, parseOnlyThese =
userContainer).findAll('a'):
- if aTag['href'].startswith(URLPROFILE):
- id = aTag['href'].split('/')[-1]
- realName = aTag.string.strip()
- break
- else:
- id = realName = None
- return id, realName
-
- def getLoginResponse(self, url = URLLOGIN):
- #clientform doesn't like HTML, and I don't want to monkey patch
it, so getUrllib2ResponseObject was born.
- response = getUrllib2ResponseObject(url)
- forms = ParseResponse(response, backwards_compat=False)
- response.close()
- #set username & password in the signin form
- form = forms[1]
- form["users[username]"] = self.username
- form["users[password]"] = self.password
- form["users[rememberme]"] = ["on"]
- #click submit
- return getHTML(form.click())
-
- class NewTalks:
- """self.videos=[{'link':link,'Title':title,'pic':pic},...]"""
-
- def __init__(self, url=None):
- if url is None:
- url = URLNEW
- self.html = getHTML(url)
- self.navItems = TedTalks().getNavItems(self.html)
-
- def getNewTalks(self):
- talkContainers = SoupStrainer(attrs =
{'class':re.compile('talkMedallion')})
- for talk in BeautifulSoup(self.html, parseOnlyThese =
talkContainers):
- link = URLTED+talk.dt.a['href']
- title = cleanHTML(talk.dt.a['title'])
- pic = resizeImage(talk.find('img', attrs =
{'src':re.compile('.+?\.jpg')})['src'])
- yield {'url':link, 'Title':title, 'Thumb':pic}
class Speakers:
- def __init__(self, url=None):
+ def __init__(self, get_HTML, url):
# adding 9999 to the url takes the script to the very last page of
the list, providing the total # of pages.
- if url == None:
- url = URLSPEAKERS+'9999'
- self.html = getHTML(url)
+ if url is None:
+ url = URLSPEAKERS + '9999'
+ self.get_HTML = get_HTML
+ self.html = self.get_HTML(url)
# only bother with navItems where they have a chance to appear.
if URLSPEAKERS in url:
- self.navItems = TedTalks().getNavItems(self.html)
+ self.navItems = getNavItems(self.html)
def getSpeakers(self):
# use getAllSpeakers instead... just leaving this function here
for educational purposes.
@@ -148,7 +124,7 @@ class TedTalks:
for i in range(self.navItems['selected']):
# don't parse the last page twice.
if i is not 8:
- html = getHTML(URLSPEAKERS+str(i+1))
+ html = self.get_HTML(URLSPEAKERS+str(i+1))
else:
html = self.html
for speaker in BeautifulSoup(html, parseOnlyThese =
speakerContainers):
@@ -166,20 +142,25 @@ class TedTalks:
class Themes:
- def __init__(self, url=None):
+ def __init__(self, get_HTML, url=None):
if url == None:
url = URLTHEMES
- self.html = getHTML(url)
+ self.get_HTML = get_HTML
+ self.html = self.get_HTML(url)
# a-z themes don't yet have navItems, so the check can be skipped
for now.
# self.navItems = TedTalks().getNavItems(html)
def getThemes(self):
- themes = list()
- themeContainers = SoupStrainer(attrs =
{'href':re.compile('/themes/\S.+?.html')})
+ themeContainers = SoupStrainer(name = 'a', attrs =
{'href':re.compile('/themes/\S.+?.html')})
+ seen_titles = set()
for theme in BeautifulSoup(self.html, parseOnlyThese =
themeContainers):
- title = theme.string
- link = URLTED+theme['href']
- yield {'url':link, 'Title':title}
+ if theme.img:
+ title = theme['title']
+ if title not in seen_titles:
+ seen_titles.add(title)
+ link = URLTED + theme['href']
+ thumb = theme.img['src']
+ yield {'url':link, 'Title':title, 'Thumb':thumb}
def getTalks(self):
# themes loaded with a json call. Why are they not more consistant?
@@ -187,7 +168,7 @@ class TedTalks:
# search HTML for the link to tedtalk's "api". It is easier to
use regex here than BS.
jsonUrl = URLTED+re.findall('DataSource\("(.+?)"', self.html)[0]
# make a dict from the json formatted string from above url
- talksMarkup = loads(getHTML(jsonUrl))
+ talksMarkup = loads(self.get_HTML(jsonUrl))
# parse through said dict for all the metadata
for markup in talksMarkup['resultSet']['result']:
talk = BeautifulSoup(markup['markup'])
@@ -196,44 +177,6 @@ class TedTalks:
pic = resizeImage(talk.find('img', attrs =
{'src':re.compile('.+?\.jpg')})['src'])
yield {'url':link, 'Title':title, 'Thumb':pic}
- class Favorites:
-
- def getFavoriteTalks(self, user, url = URLFAVORITES):
- """user must be TedTalks().User object with .id attribute"""
- if user.id is not None:
- html = getHTML(url+user.id)
- talkContainer = SoupStrainer(attrs = {'class':re.compile('box
clearfix')})
- for talk in BeautifulSoup(html, parseOnlyThese =
talkContainer):
- title = talk.ul.a.string
- link = URLTED+talk.dt.a['href']
- pic = resizeImage(talk.find('img', attrs =
{'src':re.compile('.+?\.jpg')})['src'])
- yield {'url':link, 'Title':title, 'Thumb':pic}
- else:
- print '[%s] %s invalid user object' % (pluginName, __name__)
-
- def addToFavorites(self, user, url):
- """user must be TedTalks().User object with .id attribute"""
- if user.id is not None:
- id = TedTalks().getVideoDetails(url)['id']
- print id
- response = getHTML(URLADDFAV % (id))
- if response:
- print '[%s] %s addToFavorites success' % (pluginName,
__name__)
- return True
- else:
- print '[%s] %s invalid user object' % (pluginName, __name__)
-
- def removeFromFavorites(self, user, url):
- """user must be TedTalks().User object with .id attribute"""
- if user.id is not None:
- id = TedTalks().getVideoDetails(url)['id']
- print id
- response = getHTML(URLREMFAV % (id))
- if response:
- print '[%s] %s removeFromFavorites success' % (pluginName,
__name__)
- return True
- else:
- print '[%s] %s invalid user object' % (pluginName, __name__)
class Search:
pass
-----------------------------------------------------------------------
Summary of changes:
plugin.video.ted.talks/.gitignore | 3 +
plugin.video.ted.talks/addon.xml | 5 +-
plugin.video.ted.talks/changelog.txt | 14 ++
plugin.video.ted.talks/default.py | 24 +--
.../resources/language/English/strings.xml | 4 +-
plugin.video.ted.talks/resources/lib/menu_util.py | 12 +
.../resources/lib/menu_util_test.py | 29 +++
.../resources/lib/model}/ClientForm.py | 0
.../resources/lib/model}/__init__.py | 0
.../resources/lib/model/arguments.py | 11 +
.../resources/lib/model/arguments_test.py | 9 +
.../resources/lib/model/favorites_scraper.py | 34 +++
.../resources/lib/model/fetcher.py | 44 ++++
.../resources/lib/model/rss_scraper.py | 106 +++++++++
.../resources/lib/model/rss_scraper_test.py | 63 +++++
.../resources/lib/model/url_constants.py | 5 +
plugin.video.ted.talks/resources/lib/model/user.py | 52 +++++
.../resources/lib/model/user_test.py | 46 ++++
plugin.video.ted.talks/resources/lib/model/util.py | 32 +++
plugin.video.ted.talks/resources/lib/plugin.py | 19 ++
.../resources/lib/talkDownloader.py | 7 +-
plugin.video.ted.talks/resources/lib/ted_talks.py | 240 +++++++++----------
.../resources/lib/ted_talks_scraper.py | 213 +++++++-----------
.../resources/lib/ted_talks_scraper_test.py | 53 +++++
24 files changed, 738 insertions(+), 287 deletions(-)
create mode 100644 plugin.video.ted.talks/.gitignore
create mode 100644 plugin.video.ted.talks/resources/lib/menu_util.py
create mode 100644 plugin.video.ted.talks/resources/lib/menu_util_test.py
copy {plugin.video.arretsurimages/resources/lib =>
plugin.video.ted.talks/resources/lib/model}/ClientForm.py (100%)
copy {plugin.program.executor/resources =>
plugin.video.ted.talks/resources/lib/model}/__init__.py (100%)
create mode 100644 plugin.video.ted.talks/resources/lib/model/arguments.py
create mode 100644 plugin.video.ted.talks/resources/lib/model/arguments_test.py
create mode 100644
plugin.video.ted.talks/resources/lib/model/favorites_scraper.py
create mode 100644 plugin.video.ted.talks/resources/lib/model/fetcher.py
create mode 100644 plugin.video.ted.talks/resources/lib/model/rss_scraper.py
create mode 100644
plugin.video.ted.talks/resources/lib/model/rss_scraper_test.py
create mode 100644 plugin.video.ted.talks/resources/lib/model/url_constants.py
create mode 100644 plugin.video.ted.talks/resources/lib/model/user.py
create mode 100644 plugin.video.ted.talks/resources/lib/model/user_test.py
create mode 100644 plugin.video.ted.talks/resources/lib/model/util.py
create mode 100644 plugin.video.ted.talks/resources/lib/plugin.py
create mode 100644
plugin.video.ted.talks/resources/lib/ted_talks_scraper_test.py
hooks/post-receive
--
Plugins
------------------------------------------------------------------------------
Virtualization & Cloud Management Using Capacity Planning
Cloud computing makes use of virtualization - but cloud computing
also focuses on allowing computing to be delivered as a service.
http://www.accelacomm.com/jaw/sfnl/114/51521223/
_______________________________________________
Xbmc-addons mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xbmc-addons