• 1
  • 23
  • 24
  • 25
  • 26(current)
  • 27
PBS ThinkTV.org Video Addon
I think this addon is dead.
I think this addon is dead.  You are replying to a post that is over 3 months old.

[ apparently you cannot delete previous posts, hence the duplicate -- although in all honesty, I don't expect either this or the previous post to survive "moderator" censorship ]
Recently I located the Pull Request mentioned in post 369, applied the changes on a RPi3 with LibreELEC 8.2.5 (Kodi 17.6), and was able to play more shows than previously, but not all shows.  As far as I can tell the PR does not implement the new authentication method mentioned earlier in this thread.

Interested parties might try to manually duplicate the commits in the PR for proposed PBS ThinkTV.org 3.0.17.
(2019-07-16, 19:44)kodaksmith Wrote: YouRecently I located the Pull Request mentioned in post 369, applied the changes on a RPi3 with LibreELEC 8.2.5 (Kodi 17.6), and was able to play more shows than previously, but not all shows.  As far as I can tell the PR does not implement the new authentication method mentioned earlier in this thread.

Interested parties might try to manually duplicate the commits in the PR for proposed PBS ThinkTV.org 3.0.17.

You could try and fork it and start a split off the original. Just a thought.
(2019-07-28, 03:14)jdf76 Wrote:
(2019-07-16, 19:44)kodaksmith Wrote: YouRecently I located the Pull Request mentioned in post 369, applied the changes on a RPi3 with LibreELEC 8.2.5 (Kodi 17.6), and was able to play more shows than previously, but not all shows.  As far as I can tell the PR does not implement the new authentication method mentioned earlier in this thread.

Interested parties might try to manually duplicate the commits in the PR for proposed PBS ThinkTV.org 3.0.17.
You could try and fork it and start a split off the original. Just a thought. 

Thanks very much for your post.  I did what you suggest above, manually apply the changes from github, and the addon is back in a working state!  I've mostly checked NOVA, and almost all episodes seem to be available.
Only one quibble/question: the stream I get seems to be limited to 720p. No 1080. 
(2019-07-16, 19:44)kodaksmith Wrote: Recently I located the Pull Request mentioned in post 369, applied the changes on a RPi3 with LibreELEC 8.2.5 (Kodi 17.6), and was able to play more shows than previously, but not all shows.  As far as I can tell the PR does not implement the new authentication method mentioned earlier in this thread.

Interested parties might try to manually duplicate the commits in the PR for proposed PBS ThinkTV.org 3.0.17.

Any new developments on this? I tried the above and was able to get some shows working but not everything.
The code changes referred to in post 378 do not appear to include an authentication method.  As such my expectation is that these changes will only permit playing videos that can also be played in a web browser without authentication.  If you discover a video that plays in a web browser (without authentication), but does not play in the PBS ThinkTV video add-on then that might be an improvement opportunity.
I can play 'Sesame Street' from a browser of from the android app
But it has been removed from the main menu of the add-on. It used to work a few weeks ago
Regarding 'Sesame Street', when I do a search from the web site (KSPS Spokane) the show does not appear in the results.

https://www.pbs.org/shows/?search=sesame...dbae163c07

Perhaps it was removed from PBS, or is only available from some of the local PBS broadcasters.
Problem:

Recently I noticed that this add-on would display a reduced number of episodes for a show. The following patch fixes the problem.

How to Patch PBS ThinkTV Add-on:

NOTE: This post has been edited to remove content that is no longer valid.
Is this addon working at all anymore?

When I try to launch it it crashes immediately. 

There's a very good chance I'm just doing something stupid.

https://paste.kodi.tv/epojolehub
Edited 2019-11-10:  Enable more shows to play.  Fix seasons not listed.  Change clips and previous to specials, extras, and collections.

This patch enables playback of many shows, but not all shows.

How to Patch PBS ThinkTV Add-on:

The following steps assume that you have the PBS ThinkTV 3.0.16 video add-on already installed on your Kodi computer.

  1. Create a replacement plugin.video.thinktv/resources/lib/scraper.py file using the file contents listed lower in this post.

    IMPORTANT:  Use pop-up COPY button.  When copying the code below be sure to move the mouse pointer over the code and click the pop-up COPY button in the upper right-hand corner of the code section.  This will ensure that invisible URL encoded space characters (percent-two-zero, or %20) are copied to the clipboard.

    For example, open a text editor, copy the scraper.py file contents listed below (hover mouse over code and click the pop-up Copy button), paste into text editor, save the file with name scraper.py, and exit the text editor.

  2. Determine the location of the Kodi addons folder where plugin.video.thinktv is installed on your Kodi computer.

    For example:
    • /storage/.kodi/addons/plugin.video.thinktv/ for LibreELEC on Raspberry Pi.
    • ~/.kodi/addons/plugin.video.thinktv/ for Kodi on Ubuntu where ~ is your home directory.

    Note that the location of the addons folder should be similar to the userdata folder.

  3. Copy the new scraper.py file over top of the existing plugin.video.thinktv/resources/lib/scraper.py file.

    For example on a Raspberry Pi with LibreELEC 8.2.5 installed I used the following command:

    scp -p scraper.py [email protected]:/storage/.kodi/addons/plugin.video.thinktv/resources/lib/

    Note that you would need to substitute the IP address for your Raspberry Pi (see System -> System Info).

'Hope that helps.  :-)

----- Beginning of file -----
python:

# -*- coding: utf-8 -*-
# KodiAddon PBS ThinkTV
#
from t1mlib import t1mAddon
import json
import re
import os
import urllib
import urllib2
import cookielib
import xbmcplugin
import datetime
import xbmc
import xbmcgui
import HTMLParser
import sys
try:
from urllib import quote # Python 2.X
except ImportError:
from urllib.parse import quote # Python 3+

h = HTMLParser.HTMLParser()
UTF8 = 'utf-8'
showsPerPage = 24 # number of shows returned per page by PBS

class myAddon(t1mAddon):

def doPBSLogin(self):
return()


def getPBSCookie(self):
html = self.getRequest('https://localization.services.pbs.org/localize/auto/cookie/')
a = json.loads(html)
a = a['cookie']
b = re.compile('\["(.+?)".+?\["(.+?)"', re.DOTALL).search(a)
if b is not None:
station, station_id = b.groups()
cookie = 'pbsol.sta_extended=%s; pbsol.station=%s; pbsol.station_id=%s; pbskids.localized=%s' % (quote(a),station, station_id, station)
else:
cookie = ''
return(cookie)

def getAddonMenu(self,url,ilist):
addonLanguage = self.addon.getLocalizedString
self.doPBSLogin()
#xheaders = self.defaultHeaders.copy()
#xheaders["Referer"] = "http://www.pbs.org/shows/?genre=All&title=&station=false&alphabetically=true&layout=grid"
#xheaders["X-Requested-With"] = "XMLHttpRequest"
#html = self.getRequest('http://www.pbs.org/shows-page/0/?genre=&title=&callsign=&alphabetically=true', None, xheaders)
#xbmc.log("html: "+html, xbmc.LOGNOTICE)
#a = json.loads(html)
#for b in a['genres'][1:]:
#ilist = self.addMenuItem(b['title'],'GS', ilist, str(b['id'])+'|0', self.addonIcon, self.addonFanart, None, isFolder=True)
genres = [ ['Arts & Music', 'arts-and-music']
, ['Culture', 'culture']
, ['Drama', 'drama']
, ['Food', 'food']
, ['History', 'history']
, ['Home & How-To', 'home-and-howto']
, ['Indie Films', 'indie-films']
, ['News & Public Affairs', 'news-and-public-affairs']
, ['Science & Nature', 'science-and-nature']
]
url = 'https://www.pbs.org/shows/?search=culture&source=all-sources&sortBy=a-z&genre='
for a in range(len(genres)):
genrename = genres[a][0]
genreurl = url+genres[a][1]+'|0'
ilist = self.addMenuItem(genrename,'GS', ilist, genreurl, self.addonIcon, self.addonFanart, None, isFolder=True)
if self.addon.getSetting('enable_login') == 'true':
pbsol = self.addon.getSetting('pbsol')
if pbsol != '':
xheaders = self.defaultHeaders.copy()
xheaders['X-Requested-With'] = 'XMLHttpRequest'
html = self.getRequest('http://www.pbs.org/shows-page/0/?genre=&title=&callsign=%s&alphabetically=true' % pbsol, None, xheaders)
if len(html) > 0:
a = json.loads(html)
if len(a['results']['content']) > 0:
ilist = self.addMenuItem(addonLanguage(30048) ,'GS', ilist, 'localpbs' , self.addonIcon, self.addonFanart, None, isFolder=True)
html = self.getRequest('https://www.pbs.org/favorite-shows-page/1/')
if len(html) > 0:
a = json.loads(html)
if a['totalResults'] > 0:
ilist = self.addMenuItem(addonLanguage(30004),'GS', ilist, 'favorites' , self.addonIcon, self.addonFanart, None, isFolder=True)
xheaders = self.defaultHeaders.copy()
xheaders['X-Requested-With'] = 'XMLHttpRequest'
html = self.getRequest('https://www.pbs.org/watchlist/page/1/', None, xheaders)
if len(html) > 0:
a = json.loads(html)
if a.get('videos') is not None:
if len(a['videos']) > 0:
ilist = self.addMenuItem(addonLanguage(30005) ,'GM', ilist, 'pbswatchlist' , self.addonIcon, self.addonFanart, None, isFolder=True)
ilist = self.addMenuItem(addonLanguage(30051) ,'GS', ilist, 'pbssearch' , self.addonIcon, self.addonFanart, None, isFolder=True)
return ilist


def getAddonShows(self,url,ilist):
pgNum = ''
addonLanguage = self.addon.getLocalizedString
self.doPBSLogin()
gsurl = url
if gsurl == 'favorites':
html = self.getRequest('http://www.pbs.org/favorite-shows-page/1/')
a = json.loads(html)
cats = a['content']
elif gsurl == 'localpbs':
xheaders = self.defaultHeaders.copy()
xheaders['X-Requested-With'] = 'XMLHttpRequest'
pbsol = self.addon.getSetting('pbsol')
html = self.getRequest('http://www.pbs.org/shows-page/0/?genre=&title=&callsign=%s&alphabetically=true' % (pbsol), None, xheaders)
a = json.loads(html)
cats = a['results']['content']
elif gsurl == 'pbssearch':
keyb = xbmc.Keyboard(self.addon.getSetting('last_search'), addonLanguage(30051))
keyb.doModal()
if (keyb.isConfirmed()):
answer = keyb.getText()
if len(answer) == 0:
return (ilist)
self.addon.setSetting('last_search', answer)
answer = answer.replace(' ','+')
xheaders = self.defaultHeaders.copy()
xheaders['X-Requested-With'] = 'XMLHttpRequest'
html = self.getRequest('http://www.pbs.org/search-videos/?callsign=WNET&page=1&q=%s&rank=relevance' % (answer), None, xheaders)
a = json.loads(html)
cats = a['results']['articles']
else:
genreUrl, pgNum = url.split('|',1)
xheaders = self.defaultHeaders.copy()
xheaders['X-Requested-With'] = 'XMLHttpRequest'
html = self.getRequest('http://www.pbs.org/shows-page/%s/?genre=%s&title=&callsign=&alphabetically=true' % (pgNum, genreUrl), None, xheaders)
a = json.loads(html)
cats = a['results']['content']
for i, (b) in list(enumerate(cats, start=1)):
if gsurl == 'pbssearch':
url = b['url']
else:
url = b.get('url')
if url is None:
url = b['id']
name = b['title']
thumb = b['image']
if thumb == None :
thumb = self.addonIcon
fanart = b['image']
if fanart == None:
fanart = self.addonFanart
infoList = {}
infoList['TVShowTitle'] = name
infoList['Title'] = name
infoList['Studio'] = b.get('producer')
genres = b.get('genre_titles')
if genres != [] and genres is not None:
infoList['Genre'] = genres[0]
infoList['Episode'] = b.get('video_count')
infoList['Plot'] = b.get('description')
if self.addon.getSetting('enable_login') == 'true':
if gsurl == 'favorites':
contextMenu = [(addonLanguage(30006),'XBMC.Container.Update(%s?mode=DF&url=RF%s)' % (sys.argv[0], url))]
else:
contextMenu = [(addonLanguage(30007),'XBMC.RunPlugin(%s?mode=DF&url=AF%s)' % (sys.argv[0], url))]
else:
contextMenu = None
if gsurl == 'pbssearch':
infoList['mediatype'] = 'episode'
ilist = self.addMenuItem(name,'GV', ilist, url, thumb, fanart, infoList, isFolder=False)
else:
infoList['mediatype'] = 'tvshow'
ilist = self.addMenuItem(name,'GC', ilist, url, thumb, fanart, infoList, isFolder=True, cm=contextMenu)
if pgNum != '':
ilist = self.addMenuItem('[COLOR blue]%s[/COLOR]' % addonLanguage(30050),'GS', ilist, genreUrl+'|'+str(int(pgNum)+1), self.addonIcon, self.addonFanart, None, isFolder=True)
return(ilist)


def getAddonCats(self,url,ilist):
addonLanguage = self.addon.getLocalizedString
self.doPBSLogin()
thumb = xbmc.getInfoLabel('ListItem.Art(thumb)')
fanart = xbmc.getInfoLabel('ListItem.Art(fanart)')
infoList = {}
infoList['TVShowTitle'] = xbmc.getInfoLabel('ListItem.TVShowTitle')
infoList['Title'] = infoList['TVShowTitle']
infoList['mediatype'] = 'tvshow'
xheaders = self.defaultHeaders.copy()
xheaders['Cookie'] = self.getPBSCookie()
html = self.getRequest('https://www.pbs.org%s' % url, None, xheaders)
seasons = re.compile('"name": " Season (.+?)"', re.DOTALL).findall(html)
if not seasons:
ilist = self.addMenuItem('%s' % (addonLanguage(30045)),'GE', ilist, '%s|%s|1' %(url, 'episodes'), thumb, fanart, infoList, isFolder=True)
else:
for season in seasons:
season = season.strip()
surl = 'episodes/season/'+season
ilist = self.addMenuItem('Season %s' % season,'GE', ilist, '%s|%s|1' %(url, surl), thumb, fanart, infoList, isFolder=True)
ilist = self.addMenuItem('Specials','GE', ilist, '%s|%s|1' %(url, 'specials'), thumb, fanart, infoList, isFolder=True)
ilist = self.addMenuItem('Extras','GE', ilist, '%s|%s|1' %(url, 'extras'), thumb, fanart, infoList, isFolder=True)
ilist = self.addMenuItem('Collections','GE', ilist, '%s|%s|1' %(url, 'collections'), thumb, fanart, infoList, isFolder=True)
return(ilist)


def getAddonEpisodes(self,url,ilist):
self.doPBSLogin()
addonLanguage = self.addon.getLocalizedString
url, stype, pageNum = url.split('|',2)
sname = url
xheaders = self.defaultHeaders.copy()
xheaders['Cookie'] = self.getPBSCookie()
html = self.getRequest('https://www.pbs.org%s%s/?page=%s' % (url, stype, pageNum), None, xheaders)
epis = re.compile('<article class="video-summary">.+?data-srcset="(.+?)".+?alt="(.+?)".+?class="description">(.+?)<.+?data-video-slug="(.+?)"',re.DOTALL).findall(html)
if not epis:
epis = re.compile('<div class="video-summary".+?data-video-slug="(.+?)".+?data-srcset="(.+?)".+?alt="(.+?)".+?class="description">(.+?)<',re.DOTALL).findall(html)
for i, (url, imgs, name, plot) in list(enumerate(epis, start=1)):
name = h.unescape(name.decode(UTF8))
name = name.replace('Video thumbnail: ','',1)
plot=plot.strip()
infoList = {}
imgs = imgs.split(',')
thumb = '%s.jpg' % (imgs[2].split('.jpg',1)[0].strip())
fanart = '%s.jpg' % (imgs[len(imgs)-1].split('.jpg',1)[0].strip())
infoList['Title'] = name
infoList['Plot'] = h.unescape(plot.decode(UTF8))
infoList['mediatype'] = 'episode'
infoList['TVShowTitle'] = xbmc.getInfoLabel('ListItem.TVShowTitle')
if self.addon.getSetting('enable_login') == 'true':
contextMenu = [(addonLanguage(30008),'XBMC.RunPlugin(%s?mode=DF&url=AW%s)' % (sys.argv[0], url))]
else:
contextMenu = None
ilist = self.addMenuItem(name,'GV', ilist, url, thumb, fanart, infoList, isFolder=False, cm=contextMenu)
if i >= showsPerPage:
ilist = self.addMenuItem('[COLOR blue]%s[/COLOR]' % addonLanguage(30050),'GE', ilist, '%s|%s|%s' %(sname, stype, str(int(pageNum)+1)), self.addonIcon, self.addonFanart, None, isFolder=True)
return(ilist)


def getAddonMovies(self,url,ilist):
addonLanguage = self.addon.getLocalizedString
xbmcplugin.setContent(int(sys.argv[1]), 'episodes')
self.doPBSLogin()
xheaders = self.defaultHeaders.copy()
xheaders['X-Requested-With'] = 'XMLHttpRequest'
html = self.getRequest('https://www.pbs.org/watchlist/page/1/', None, xheaders)
a = json.loads(html)
epis = a['videos']
for i, b in list(enumerate(epis, start=1)):
infoList = {}
name = b['title']
plot = b['description']
duration = b['duration']
t = 0
for dur in duration.split(':'):
if dur.strip().isdigit():
t = t*60 + int(dur.strip())
if t != 0:
infoList['duration'] = t
thumb = b['image']
fanart = b['image']
infoList['TVShowTitle'] = b['show']['title']
infoList['Title'] = name
infoList['Plot'] = plot
infoList['mediatype'] = 'episode'
url = str(b['id'])
contextMenu = [(addonLanguage(30009),'XBMC.Container.Update(%s?mode=DF&url=RW%s)' % (sys.argv[0], url))]
ilist = self.addMenuItem(name,'GV', ilist, url, thumb, fanart, infoList, isFolder=False, cm=contextMenu)
return(ilist)

def doFunction(self, url):
self.doPBSLogin()
func = url[0:2]
url = url[2:]
if func == 'AW':
html = self.getRequest('http://www.pbs.org/profile/addFavoriteVideo/%s/' % url)
elif func == 'AF':
html = self.getRequest('http://www.pbs.org/profile/addFavoriteProgram/%s/' % url)
elif func == 'RW':
html = self.getRequest('http://www.pbs.org/profile/removeFavoriteVideo/%s/' % url)
elif func == 'RF':
html = self.getRequest('http://www.pbs.org/profile/removeFavoriteProgram/%s/' % url)
try:
a = json.loads(html)
xbmc.executebuiltin('XBMC.Notification("%s", "%s", %s)' % ( self.addonName, a['errorMessage'] , 4000) )
except: pass


def getAddonVideo(self,url):
xheaders = self.defaultHeaders.copy()
xheaders['X-Requested-With'] = 'XMLHttpRequest'
if not url.startswith('/video'):
html = self.getRequest('http://www.pbs.org/video/%s/' % (url), None, xheaders)
else:
html = self.getRequest('http://www.pbs.org%s' % (url), None, xheaders)
url = re.compile("id: '(.+?)'", re.DOTALL).search(html).group(1)
addonLanguage = self.addon.getLocalizedString
pbs_uid = self.addon.getSetting('pbs_uid')
pg = self.getRequest('https://player.pbs.org/viralplayer/%s/?uid=%s' % (url, pbs_uid))
pg = re.compile('window.videoBridge = (.+?);\n', re.DOTALL).search(pg).group(1)
a = json.loads(pg)
if not a is None:
# url = a['recommended_encoding']['url']
suburl = a['cc'].get('SRT')
urls = a['encodings']
url = ''
for xurl in urls:
pg = self.getRequest('%s?format=json' % xurl)
xurl = json.loads(pg)['url']
if xurl.endswith('.m3u8'):
if url.endswith('800k.m3u8') or url.endswith('.mp4'):
url = xurl
break
else:
url = xurl
else:
if not url.endswith('.m3u8'):
url = xurl
else:
xbmc.executebuiltin('XBMC.Notification("%s", "%s", %s)' % ( self.addonName, addonLanguage(30049) , 4000) )
return

# if 'mp4:' in url:
# url = 'http://ga.video.cdn.pbs.org/%s' % url.split('mp4:',1)[1]
liz = xbmcgui.ListItem(path = url)
if not suburl is None:
subfile = self.procConvertSubtitles(suburl)
liz.setSubtitles([(subfile)])
if ('.m3u8' in url):
liz.setProperty('inputstreamaddon','inputstream.adaptive')
liz.setProperty('inputstream.adaptive.manifest_type','hls')
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, liz)

----- End of file -----
Good stuff kodaksmith - works for me ...
Thanks, but I couldn't get it to work with 3.1.0 (leia). Libreelec on an Intel NUC. Is there anything you would want from me?
(2020-08-06, 19:30)KidShelleen Wrote: Thanks, but I couldn't get it to work with 3.1.0 (leia). Libreelec on an Intel NUC. Is there anything you would want from me?

I couldn't edit my reply. Libreelec 9.2.3
  • 1
  • 23
  • 24
  • 25
  • 26(current)
  • 27

Logout Mark Read Team Forum Stats Members Help
PBS ThinkTV.org Video Addon6