]>
code.delx.au - webdl/blob - iview.py
1 from common
import grab_json
, grab_xml
, Node
, download_hls
5 API_URL
= "http://iview.abc.net.au/api"
6 AUTH_URL
= "http://iview.abc.net.au/auth"
8 def format_episode_title(series
, ep
):
10 return series
+ " " + ep
14 class IviewEpisodeNode(Node
):
15 def __init__(self
, title
, parent
, video_key
):
16 Node
.__init
__(self
, title
, parent
)
17 self
.video_key
= video_key
18 self
.filename
= title
+ ".ts"
19 self
.can_download
= True
21 def find_hls_url(self
, playlist
):
22 for video
in playlist
:
23 if video
["type"] == "program":
24 return video
["hls-high"].replace("http:", "https:")
25 raise Exception("Missing hls-high program stream for " + self
.video_key
)
27 def get_auth_details(self
):
28 with requests_cache
.disabled():
29 auth_doc
= grab_xml(AUTH_URL
)
31 "auth": "http://www.abc.net.au/iView/Services/iViewHandshaker",
33 token
= auth_doc
.xpath("//auth:tokenhd/text()", namespaces
=NS
)[0]
34 token_url
= auth_doc
.xpath("//auth:server/text()", namespaces
=NS
)[0]
35 token_hostname
= urllib
.parse
.urlparse(token_url
).netloc
36 return token
, token_hostname
38 def add_auth_token_to_url(self
, video_url
, token
, token_hostname
):
39 parsed_url
= urllib
.parse
.urlparse(video_url
)
40 hacked_url
= parsed_url
._replace
(netloc
=token_hostname
, query
="hdnea=" + token
)
41 video_url
= urllib
.parse
.urlunparse(hacked_url
)
45 info
= grab_json(API_URL
+ "/programs/" + self
.video_key
)
46 video_url
= self
.find_hls_url(info
["playlist"])
47 token
, token_hostname
= self
.get_auth_details()
48 video_url
= self
.add_auth_token_to_url(video_url
, token
, token_hostname
)
49 return download_hls(self
.filename
, video_url
)
52 class IviewIndexNode(Node
):
53 def __init__(self
, title
, parent
, url
):
54 Node
.__init
__(self
, title
, parent
)
58 def add_episode(self
, ep_info
):
59 video_key
= ep_info
["episodeHouseNumber"]
60 series_title
= ep_info
["seriesTitle"]
61 title
= ep_info
.get("title", None)
62 episode_title
= format_episode_title(series_title
, title
)
64 series_node
= self
.series_map
.get(series_title
, None)
66 series_node
= Node(series_title
, self
)
67 self
.series_map
[series_title
] = series_node
69 IviewEpisodeNode(episode_title
, series_node
, video_key
)
71 def fill_children(self
):
72 info
= grab_json(self
.url
)
73 for index_list
in info
["index"]:
74 for ep_info
in index_list
["episodes"]:
75 self
.add_episode(ep_info
)
77 class IviewFlatNode(Node
):
78 def __init__(self
, title
, parent
, url
):
79 Node
.__init
__(self
, title
, parent
)
82 def add_episode(self
, ep_info
):
83 video_key
= ep_info
["episodeHouseNumber"]
84 series_title
= ep_info
["seriesTitle"]
85 title
= ep_info
.get("title", None)
86 episode_title
= format_episode_title(series_title
, title
)
88 IviewEpisodeNode(episode_title
, self
, video_key
)
90 def fill_children(self
):
91 info
= grab_json(self
.url
)
93 self
.add_episode(ep_info
)
96 class IviewRootNode(Node
):
97 def load_categories(self
):
98 by_category_node
= Node("By Category", self
)
99 def category(name
, slug
):
100 IviewIndexNode(name
, by_category_node
, API_URL
+ "/category/" + slug
)
102 category("Arts & Culture", "arts")
103 category("Comedy", "comedy")
104 category("Documentary", "docs")
105 category("Drama", "drama")
106 category("Education", "education")
107 category("Lifestyle", "lifestyle")
108 category("News & Current Affairs", "news")
109 category("Panel & Discussion", "panel")
110 category("Sport", "sport")
112 def load_channels(self
):
113 by_channel_node
= Node("By Channel", self
)
114 def channel(name
, slug
):
115 IviewIndexNode(name
, by_channel_node
, API_URL
+ "/channel/" + slug
)
117 channel("ABC1", "abc1")
118 channel("ABC2", "abc2")
119 channel("ABC3", "abc3")
120 channel("ABC4Kids", "abc4kids")
121 channel("iView Exclusives", "iview")
123 def load_featured(self
):
124 IviewFlatNode("Featured", self
, API_URL
+ "/featured")
126 def fill_children(self
):
127 self
.load_categories()
132 def fill_nodes(root_node
):
133 IviewRootNode("ABC iView", root_node
)