]>
code.delx.au - webdl/blob - iview.py
1 from common
import append_to_qs
, grab_json
, grab_text
, Node
, download_hls
9 BASE_URL
= "https://iview.abc.net.au"
10 API_URL
= "https://iview.abc.net.au/api"
12 def format_episode_title(series
, ep
):
14 return series
+ " " + ep
18 def add_episode(parent
, ep_info
):
19 video_key
= ep_info
["episodeHouseNumber"]
20 series_title
= ep_info
["seriesTitle"]
21 title
= ep_info
.get("title", None)
22 episode_title
= format_episode_title(series_title
, title
)
24 IviewEpisodeNode(episode_title
, parent
, video_key
)
26 class IviewEpisodeNode(Node
):
27 def __init__(self
, title
, parent
, video_key
):
28 Node
.__init
__(self
, title
, parent
)
29 self
.video_key
= video_key
30 self
.filename
= title
+ ".ts"
31 self
.can_download
= True
33 def find_hls_url(self
, playlist
):
34 for video
in playlist
:
35 if video
["type"] in ["program", "livestream"]:
36 streams
= video
["streams"]["hls"]
37 for quality
in ["720", "sd", "sd-low"]:
38 if quality
in streams
:
39 return streams
[quality
]
40 raise Exception("Missing program stream for " + self
.video_key
+ " -- " + self
.title
)
42 def get_auth_token(self
):
43 path
= "/auth/hls/sign?ts=%s&hn=%s&d=android-tablet" % (int(time
.time()), self
.video_key
)
44 sig
= hmac
.new(b
'android.content.res.Resources', path
.encode("utf-8"), hashlib
.sha256
).hexdigest()
45 auth_url
= BASE_URL
+ path
+ "&sig=" + sig
46 with requests_cache
.disabled():
47 auth_token
= grab_text(auth_url
)
51 info
= grab_json(API_URL
+ "/programs/" + self
.video_key
)
52 if "playlist" not in info
:
54 video_url
= self
.find_hls_url(info
["playlist"])
55 auth_token
= self
.get_auth_token()
56 video_url
= append_to_qs(video_url
, {"hdnea": auth_token
})
57 return download_hls(self
.filename
, video_url
)
60 class IviewIndexNode(Node
):
61 def __init__(self
, title
, parent
, url
):
62 Node
.__init
__(self
, title
, parent
)
64 self
.unique_series
= set()
66 def fill_children(self
):
67 info
= grab_json(self
.url
)
68 for key
in ["carousels", "collections", "index"]:
69 for collection_list
in info
.get(key
, None):
70 if isinstance(collection_list
, dict):
71 for ep_info
in collection_list
.get("episodes", []):
72 self
.add_series(ep_info
)
74 def add_series(self
, ep_info
):
75 title
= ep_info
["seriesTitle"]
76 if title
in self
.unique_series
:
78 self
.unique_series
.add(title
)
79 url
= API_URL
+ "/" + ep_info
["href"]
80 IviewSeriesNode(title
, self
, url
)
82 class IviewSeriesNode(Node
):
83 def __init__(self
, title
, parent
, url
):
84 Node
.__init
__(self
, title
, parent
)
87 def fill_children(self
):
88 ep_info
= grab_json(self
.url
)
89 series_slug
= ep_info
["href"].split("/")[1]
90 series_url
= API_URL
+ "/series/" + series_slug
+ "/" + ep_info
["seriesHouseNumber"]
91 info
= grab_json(series_url
)
92 for ep_info
in info
.get("episodes", []):
93 add_episode(self
, ep_info
)
95 class IviewFlatNode(Node
):
96 def __init__(self
, title
, parent
, url
):
97 Node
.__init
__(self
, title
, parent
)
100 def fill_children(self
):
101 info
= grab_json(self
.url
)
103 add_episode(self
, ep_info
)
106 class IviewRootNode(Node
):
107 def load_categories(self
):
108 by_category_node
= Node("By Category", self
)
110 data
= grab_json(API_URL
+ "/categories")
111 categories
= data
["categories"]
113 for category_data
in categories
:
114 category_title
= category_data
["title"]
115 category_title
= string
.capwords(category_title
)
117 category_href
= category_data
["href"]
119 IviewIndexNode(category_title
, by_category_node
, API_URL
+ "/" + category_href
)
121 def load_channels(self
):
122 by_channel_node
= Node("By Channel", self
)
124 data
= grab_json(API_URL
+ "/channel")
125 channels
= data
["channels"]
127 for channel_data
in channels
:
128 channel_id
= channel_data
["categoryID"]
133 "abc4kids": "ABC4Kids",
135 "abcarts": "ABC Arts",
136 }.get(channel_id
, channel_data
["title"])
138 channel_href
= channel_data
["href"]
140 IviewIndexNode(channel_title
, by_channel_node
, API_URL
+ "/" + channel_href
)
142 def load_featured(self
):
143 IviewFlatNode("Featured", self
, API_URL
+ "/featured")
145 def fill_children(self
):
146 self
.load_categories()
151 def fill_nodes(root_node
):
152 IviewRootNode("ABC iView", root_node
)