Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 26 additions & 57 deletions ABCiView.bundle/Contents/Code/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,15 @@
ART = 'art-default.jpg'
ICON = 'icon-default.jpg'


def Start():
HTTP.RandomizeUserAgent(browser='Safari')
Plugin.AddViewGroup('List', viewMode='List', mediaType='items')
Plugin.AddViewGroup('InfoList', viewMode='InfoList', mediaType='items')


@handler('/video/aubciview', 'Australian ABC iView', art=ART, thumb=ICON)
@handler('/video/iview', 'ABC iView', art=ART, thumb=ICON)
def MainMenu():

oc = ObjectContainer(view_group='List', title2='ABC iView')


#oc.add(VideoClipObject(key = RTMPVideoURL(url = 'rtmp://203.18.195.10/ondemand' + '?auth=7B8F0402DD370FF9299E', clip = 'mp4:comedy/madashell_02_08', swf_url = 'http://www.abc.net.au/iview/images/iview.jpg'), rating_key = '123',title = 'TEST'))

cats = iView_Config.List_Categories()

for key in cats:
Expand All @@ -25,88 +21,61 @@ def MainMenu():
))

oc.objects.sort(key=lambda obj: obj.title)

return oc


@route('/video/aubciview/category/{category}')
@route('/video/iview/category/{category}')
def GetSeriesByCaegory(category):

cat = iView_Category(category)

oc = ObjectContainer(view_group='List', title2=cat.title)

series = cat.series_list

for item in series:
oc.add(DirectoryObject(
key=Callback(GetEpisodesBySeries, series=item[0]),
title=item[1]
title=item[1],
thumb=Callback(GetSeriesThumb, seriesID=item[0])
))

oc.objects.sort(key=lambda obj: obj.title)

return oc


@route('/video/aubciview/series/{series}')
def GetSeriesThumb(seriesID):
show = iView_Series(seriesID)
return show.img

@route('/video/iview/series/{series}')
def GetEpisodesBySeries(series):
show = iView_Series(series)
oc = ObjectContainer(view_group='InfoList', title2=show.title, no_cache=True)

episodes = show.episodes

rtmp_url = iView_Config.RTMP_URL()


for item in episodes:
dur = item[5] * 1000
oc.add(Play_iView(item[1], item[2], item[3], item[4], dur, rtmp_url, item[6]))
oc.add(Play_iView(item['id'], item['title'], item['description'], item['url'], item['thumb'], item['duration'] ))

oc.objects.sort(key=lambda obj: obj.title)

return oc


@route('/video/aubciview/episode/play')
def Play_iView(iView_Title, iView_Summary, iView_Path, iView_Thumb, iView_Duration, video_url, iView_live=0,
include_container=False):
@route('/video/iview/episode/play')
def Play_iView(video_id, iView_Title, iView_Summary, iView_Path, iView_Thumb, iView_Duration):

HTTP.ClearCache()

iView_live = int(iView_live)

call_args = {
"iView_Title": iView_Title,
"iView_Summary": iView_Summary,
"iView_Path": iView_Path,
"iView_Thumb": iView_Thumb,
"iView_Duration": int(iView_Duration),
"video_url": video_url,
"iView_live": iView_live,
"include_container": True,
}

if iView_live == 1:
rtmpVid = RTMPVideoURL(url=video_url, clip=iView_Path, swf_url=iView_Config.SWF_URL, live=True)
else:
rtmpVid = RTMPVideoURL(url=video_url, clip=iView_Config.CLIP_PATH() + iView_Path, swf_url=iView_Config.SWF_URL)

Log('==== Video ====')
Log('Title: ' + iView_Title)
Log('Video Path: ' + iView_Path)
Log('==== End Video ====')

vco = VideoClipObject(
key=Callback(Play_iView, **call_args),
url= 'http://abc.net.au/iview/#/view/' + video_id,
rating_key=iView_Path,
title=iView_Title,
summary=iView_Summary,
thumb=iView_Thumb,
duration=int(iView_Duration),
items=[
MediaObject(
parts=[
PartObject(
key=rtmpVid
)
]
)
]
duration=iView_Duration,
)

if include_container:
return ObjectContainer(objects=[vco])
else:
return vco
return vco
77 changes: 42 additions & 35 deletions ABCiView.bundle/Contents/Code/iview_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,27 @@ class iView_Config():
SERIES_URL = API_URL + 'seriesIndex'
SERIES_JSON = JSON.ObjectFromURL(SERIES_URL)
category_list = {}

FALLBACK_PATH = 'rtmp://cp53909.edgefcs.net/ondemand'

@classmethod
def RTMP_URL(self):

xml = XML.ElementFromURL(url=self.AUTH_URL)
token = xml.xpath('//a:token/text()', namespaces={'a': 'http://www.abc.net.au/iView/Services/iViewHandshaker'})[
0]
return xml.xpath('//a:server/text()', namespaces={'a': 'http://www.abc.net.au/iView/Services/iViewHandshaker'})[
0] + '?auth=' + token

xml = XML.ElementFromURL(url=self.AUTH_URL)
token = xml.xpath('//a:token/text()', namespaces={'a': 'http://www.abc.net.au/iView/Services/iViewHandshaker'})[0]
server = xml.xpath('//a:server/text()', namespaces={'a': 'http://www.abc.net.au/iView/Services/iViewHandshaker'})[0]

if 'http' in server:
return self.FALLBACK_PATH + '?auth=' + token
else:
return server + '?auth=' + token


@classmethod
def CLIP_PATH(self):
xml = XML.ElementFromURL(self.AUTH_URL)
return 'mp4:flash/playback/_definst_/'

xml = XML.ElementFromURL(self.AUTH_URL)
path = xml.xpath('//a:path/text()', namespaces={'a': 'http://www.abc.net.au/iView/Services/iViewHandshaker'})
if not path:
return 'mp4:'
Expand All @@ -51,45 +59,44 @@ def List_Categories(self):
class iView_Series(object):
def __init__(self, key):
self.id = key
json = JSON.ObjectFromURL(iView_Config.API_URL + 'series=' + key)

self.title = json[0]['b']
self.description = json[0]['c']
self.category = json[0]['e']
self.img = json[0]['d']
self.episode_count = len(json[0]['f'])
self.episodes = self.Episodes(json[0]['f'])
Log('Getting iView series info for:' + iView_Config.API_URL + 'series=' + key)
json = JSON.ObjectFromURL(iView_Config.API_URL + 'series=' + key)
for result in json:
Log('Checking series ID ' + str(key) + ' against results ' + str(result['a']) )
if str(result['a']) == str(key):
Log('Got match for series ID')
self.title = result['b']
self.description = result['c']
self.category = result['e']
self.img = result['d']
self.episode_count = len(result['f'])
self.episodes = self.Episodes(result['f'])
else:
Log('rejected series ID match')

def Episodes(self, json):
eps = []
for ep in json:
id = ep['a']
title = ep['b']
description = ep['d']
episode = {}
episode['id'] = ep['a']
episode['title'] = ep['b']
episode['description'] = ep['d']

live = 0
episode['live'] = 0
if 'n' in ep:
url = ep['n'][:-4]
episode['url'] = ep['n'][:-4]
else:
url = ep['r']
live = 1
episode['url'] = ep['r']
episode['live'] = 1

thumb = ep['s']
episode['thumb'] = ep['s']

if 'j' in ep:
duration = int(ep['j'])
episode['duration'] = int(ep['j']) * 1000
else:
duration = 0

tmp = []
tmp.append(id)
tmp.append(title)
tmp.append(description)
tmp.append(url)
tmp.append(thumb)
tmp.append(duration)
tmp.append(live)
eps.append(tmp)
episode['duration'] = 0

eps.append(episode)

return eps

Expand Down
2 changes: 1 addition & 1 deletion ABCiView.bundle/Contents/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.plexapp.plugins.aubciview</string>
<string>com.plexapp.plugins.iview</string>
<key>PlexClientPlatforms</key>
<string>*</string>
<key>PlexFrameworkVersion</key>
Expand Down
22 changes: 22 additions & 0 deletions ABCiView.bundle/Contents/Services/ServiceInfo.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>URL</key>
<dict>
<key>iview</key>
<dict>
<key>Identifier</key>
<string>com.plexapp.plugins.iview</string>
<key>URLPatterns</key>
<array>
<string>http://abc.net.au/iview/.+</string>
</array>
</dict>
</dict>
<key>PlexFrameworkFlags</key>
<array>
<string>UseRealRTMP</string>
</array>
</dict>
</plist>
107 changes: 107 additions & 0 deletions ABCiView.bundle/Contents/Services/URL/iview/ServiceCode.pys
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# getSeries: http://iview.abc.net.au/api/legacy/flash/?series=$ID
# getAllSeries: http://iview.abc.net.au/api/legacy/flash/?series=all

def MetadataObjectForURL(url):

#TODO get normalised url
RE_PLAYLIST = Regex('([0-9]+)$', Regex.DOTALL)
ID = RE_PLAYLIST.search(url).group(0)
data = JSON.ObjectFromURL('http://iview.abc.net.au/api/legacy/flash/?series='+ID)

for result in data:
Log('Checking for ID:' + str(ID) + ' and got ' + str(result['a']) )
Log('matched ID so getting episodes data')
episodes = result['f']
show = result['b']
RE_EPISODE = Regex('^'+show+' (.*)$')

for episode in episodes:
if episode['a'] == ID:
title = RE_EPISODE.search(episode['b']).group(1)
summary = episode['d']
thumb = episode['s']
duration = int(episode['j'])*1000
content_rating = episode['m']
try:
season = int(episode['u'])
except:
season = None

try:
absolute_index = int(episode['v'])
except:
absolute_index = None
expires_on = episode['g']
aired = Datetime.ParseDate(episode['f'])
summary = summary + '\n\nExpires: ' + expires_on

return EpisodeObject(
title=title,
summary=summary,
thumb=thumb,
duration=duration,
show = show,
season = season,
absolute_index = absolute_index,
originally_available_at = aired
)

def MediaObjectsForURL(url):

container = Container.MP4
video_codec = VideoCodec.H264
audio_codec = AudioCodec.AAC
audio_channels = 2

return [
MediaObject(
protocol='rtmp',
video_resolution='576',
audio_channels=2,
parts=[PartObject(key=Callback(PlayVideo, url=url))],
),
]

@indirect
def PlayVideo(url):
BASE_URL = 'http://www.abc.net.au/iview/'
CFG_URL = BASE_URL + 'xml/config.xml'
CFG_XML = XML.ElementFromURL(CFG_URL)
AUTH_URL = CFG_XML.xpath('/config/param[@name="auth"]')[0].get("value")
FALLBACK_PATH = 'rtmp://cp53909.edgefcs.net/ondemand'
xml = XML.ElementFromURL(url=AUTH_URL)
token = xml.xpath('//a:token/text()', namespaces={'a': 'http://www.abc.net.au/iView/Services/iViewHandshaker'})[0]
server = xml.xpath('//a:server/text()', namespaces={'a': 'http://www.abc.net.au/iView/Services/iViewHandshaker'})[0]

if 'http' in server:
rtmpURL = FALLBACK_PATH + '?auth=' + token
else:
rtmpURL = server + '?auth=' + token

RE_ID = Regex('([0-9]+)$', Regex.DOTALL)
ID = RE_ID.search(url).group(0)
#TODO: handle if URL is of different format (ie .scrape page and get same share liknk)
API_URL = CFG_XML.xpath('/config/param[@name="api"]')[0].get("value")

#API returns series even if querying with episode ID
data = JSON.ObjectFromURL(API_URL + 'series=' + str(ID))

for results in data:
episodes = results['f']
for episode in episodes:
if episode['a'] == ID:
live = 0
if 'n' in episode:
video_url = episode['n'][:-4]
else:
video_url = episode['r']
live = 1

SWF_URL = 'http://www.abc.net.au/iview/images/iview.jpg'
CLIP = 'mp4:flash/playback/_definst_/'
if live == 1:
rtmpVid = RTMPVideoURL(url=rtmpURL, clip=video_url, swf_url=SWF_URL, live=True)
else:
rtmpVid = RTMPVideoURL(url=rtmpURL, clip=CLIP + video_url, swf_url=SWF_URL)

return IndirectResponse(VideoClipObject, key=rtmpVid)