Skip to content

Commit 523d543

Browse files
committed
allow overriding headers for usher and hidden api calls
1 parent db54fef commit 523d543

File tree

4 files changed

+61
-38
lines changed

4 files changed

+61
-38
lines changed

Diff for: addon.xml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<extension point="xbmc.addon.metadata">
1010
<platform>all</platform>
1111
<news>
12+
[upd] allow overriding headers for usher and hidden api calls
1213
[fix] decode byte responses in scraper
1314
[fix] usher/parser error handling
1415
</news>

Diff for: changelog.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
2.0.9
2+
[upd] allow overriding headers for usher and hidden api calls
23
[fix] decode byte responses in scraper
34
[fix] usher/parser error handling
45

Diff for: resources/lib/twitch/api/usher.py

+20-20
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ def valid_video_id(video_id):
3030

3131

3232
@query
33-
def channel_token(channel, platform=keys.WEB):
34-
q = HiddenApiQuery('channels/{channel}/access_token')
33+
def channel_token(channel, platform=keys.WEB, headers={}):
34+
q = HiddenApiQuery('channels/{channel}/access_token', headers=headers)
3535
q.add_urlkw(keys.CHANNEL, channel)
3636
q.add_param(keys.NEED_HTTPS, Boolean.TRUE)
3737
q.add_param(keys.PLATFORM, platform)
@@ -40,8 +40,8 @@ def channel_token(channel, platform=keys.WEB):
4040

4141

4242
@query
43-
def vod_token(video_id, platform=keys.WEB):
44-
q = HiddenApiQuery('vods/{vod}/access_token')
43+
def vod_token(video_id, platform=keys.WEB, headers={}):
44+
q = HiddenApiQuery('vods/{vod}/access_token', headers=headers)
4545
q.add_urlkw(keys.VOD, video_id)
4646
q.add_param(keys.NEED_HTTPS, Boolean.TRUE)
4747
q.add_param(keys.PLATFORM, platform)
@@ -56,12 +56,12 @@ def _legacy_video(video_id):
5656
return q
5757

5858

59-
def live_request(channel, platform=keys.WEB):
60-
token = channel_token(channel, platform=platform)
59+
def live_request(channel, platform=keys.WEB, headers={}):
60+
token = channel_token(channel, platform=platform, headers=headers)
6161
if keys.ERROR in token:
6262
return token
6363
else:
64-
q = UsherQuery('api/channel/hls/{channel}.m3u8')
64+
q = UsherQuery('api/channel/hls/{channel}.m3u8', headers=headers)
6565
q.add_urlkw(keys.CHANNEL, channel)
6666
q.add_param(keys.SIG, token[keys.SIG].encode('utf-8'))
6767
q.add_param(keys.TOKEN, token[keys.TOKEN].encode('utf-8'))
@@ -81,8 +81,8 @@ def live_request(channel, platform=keys.WEB):
8181

8282

8383
@query
84-
def _live(channel, token):
85-
q = UsherQuery('api/channel/hls/{channel}.m3u8')
84+
def _live(channel, token, headers={}):
85+
q = UsherQuery('api/channel/hls/{channel}.m3u8', headers=headers)
8686
q.add_urlkw(keys.CHANNEL, channel)
8787
q.add_param(keys.SIG, token[keys.SIG].encode('utf-8'))
8888
q.add_param(keys.TOKEN, token[keys.TOKEN].encode('utf-8'))
@@ -99,22 +99,22 @@ def _live(channel, token):
9999

100100

101101
@m3u8
102-
def live(channel, platform=keys.WEB):
103-
token = channel_token(channel, platform=platform)
102+
def live(channel, platform=keys.WEB, headers={}):
103+
token = channel_token(channel, platform=platform, headers=headers)
104104
if keys.ERROR in token:
105105
return token
106106
else:
107-
return _live(channel, token)
107+
return _live(channel, token, headers=headers)
108108

109109

110-
def video_request(video_id, platform=keys.WEB):
110+
def video_request(video_id, platform=keys.WEB, headers={}):
111111
video_id = valid_video_id(video_id)
112112
if video_id:
113-
token = vod_token(video_id, platform=platform)
113+
token = vod_token(video_id, platform=platform, headers=headers)
114114
if keys.ERROR in token:
115115
return token
116116
else:
117-
q = UsherQuery('vod/{id}')
117+
q = UsherQuery('vod/{id}', headers=headers)
118118
q.add_urlkw(keys.ID, video_id)
119119
q.add_param(keys.NAUTHSIG, token[keys.SIG].encode('utf-8'))
120120
q.add_param(keys.NAUTH, token[keys.TOKEN].encode('utf-8'))
@@ -137,8 +137,8 @@ def video_request(video_id, platform=keys.WEB):
137137

138138

139139
@query
140-
def _vod(video_id, token):
141-
q = UsherQuery('vod/{id}')
140+
def _vod(video_id, token, headers={}):
141+
q = UsherQuery('vod/{id}', headers=headers)
142142
q.add_urlkw(keys.ID, video_id)
143143
q.add_param(keys.NAUTHSIG, token[keys.SIG].encode('utf-8'))
144144
q.add_param(keys.NAUTH, token[keys.TOKEN].encode('utf-8'))
@@ -156,14 +156,14 @@ def _vod(video_id, token):
156156

157157

158158
@m3u8
159-
def video(video_id, platform=keys.WEB):
159+
def video(video_id, platform=keys.WEB, headers={}):
160160
video_id = valid_video_id(video_id)
161161
if video_id:
162-
token = vod_token(video_id, platform=platform)
162+
token = vod_token(video_id, platform=platform, headers=headers)
163163
if keys.ERROR in token:
164164
return token
165165
else:
166-
return _vod(video_id, token)
166+
return _vod(video_id, token, headers=headers)
167167
else:
168168
raise NotImplementedError('Unknown Video Type')
169169

Diff for: resources/lib/twitch/queries.py

+39-18
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
See LICENSES/GPL-3.0-only for more information.
1111
"""
1212

13+
from copy import deepcopy
14+
1315
from six.moves.urllib.parse import urljoin
1416

1517
from . import CLIENT_ID, OAUTH_TOKEN, APP_TOKEN
@@ -122,21 +124,23 @@ def execute(self):
122124

123125
class ApiQuery(JsonQuery):
124126
def __init__(self, path, headers={}, data={}, use_token=True, method=methods.GET):
125-
headers.setdefault('Client-ID', CLIENT_ID)
127+
_headers = deepcopy(headers)
128+
_headers.setdefault('Client-ID', CLIENT_ID)
126129
if use_token and OAUTH_TOKEN:
127-
headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN))
128-
super(ApiQuery, self).__init__(_kraken_baseurl, headers, data, method)
130+
_headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN))
131+
super(ApiQuery, self).__init__(_kraken_baseurl, _headers, data, method)
129132
self.add_path(path)
130133

131134

132135
class HelixApiQuery(HelixJsonQuery):
133136
def __init__(self, path, headers={}, data={}, use_app_token=False, method=methods.GET):
134-
headers.setdefault('Client-ID', CLIENT_ID)
137+
_headers = deepcopy(headers)
138+
_headers.setdefault('Client-ID', CLIENT_ID)
135139
if use_app_token and APP_TOKEN:
136-
headers.setdefault('Authorization', 'Bearer {access_token}'.format(access_token=APP_TOKEN))
140+
_headers.setdefault('Authorization', 'Bearer {access_token}'.format(access_token=APP_TOKEN))
137141
elif OAUTH_TOKEN:
138-
headers.setdefault('Authorization', 'Bearer {access_token}'.format(access_token=OAUTH_TOKEN))
139-
super(HelixApiQuery, self).__init__(_helix_baseurl, headers, data, method)
142+
_headers.setdefault('Authorization', 'Bearer {access_token}'.format(access_token=OAUTH_TOKEN))
143+
super(HelixApiQuery, self).__init__(_helix_baseurl, _headers, data, method)
140144
self._params = list()
141145
self.add_path(path)
142146

@@ -154,37 +158,54 @@ def add_param(self, key, value, default=None):
154158

155159
class HiddenApiQuery(JsonQuery):
156160
def __init__(self, path, headers={}, data={}, use_token=True, method=methods.GET):
157-
headers.setdefault('Client-ID', CLIENT_ID)
158-
if use_token and OAUTH_TOKEN:
159-
headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN))
160-
super(HiddenApiQuery, self).__init__(_hidden_baseurl, headers, data, method)
161+
_headers = deepcopy(headers)
162+
if 'Client-ID' not in _headers:
163+
_headers.setdefault('Client-ID', CLIENT_ID)
164+
if 'Client-ID' in _headers and not _headers.get('Client-ID'):
165+
del _headers['Client-ID']
166+
if 'Authorization' not in _headers:
167+
if use_token and OAUTH_TOKEN:
168+
_headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN))
169+
if 'Authorization' in _headers and not _headers.get('Authorization'):
170+
del _headers['Authorization']
171+
super(HiddenApiQuery, self).__init__(_hidden_baseurl, _headers, data, method)
161172
self.add_path(path)
162173

163174

164175
class UsherQuery(DownloadQuery):
165176
def __init__(self, path, headers={}, data={}, method=methods.GET):
166-
headers.setdefault('Client-ID', CLIENT_ID)
167-
if OAUTH_TOKEN:
168-
headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN))
169-
super(UsherQuery, self).__init__(_usher_baseurl, headers, data, method)
177+
_headers = deepcopy(headers)
178+
if 'Client-ID' not in _headers:
179+
_headers.setdefault('Client-ID', CLIENT_ID)
180+
if 'Client-ID' in _headers and not _headers.get('Client-ID'):
181+
del _headers['Client-ID']
182+
if 'Authorization' not in _headers:
183+
if OAUTH_TOKEN:
184+
_headers.setdefault('Authorization', 'OAuth {access_token}'.format(access_token=OAUTH_TOKEN))
185+
if 'Authorization' in _headers and not _headers.get('Authorization'):
186+
del _headers['Authorization']
187+
super(UsherQuery, self).__init__(_usher_baseurl, _headers, data, method)
170188
self.add_path(path)
171189

172190

173191
class OAuthQuery(JsonQuery):
174192
def __init__(self, path, headers={}, data={}, method=methods.GET):
175-
super(JsonQuery, self).__init__(_oauth_baseurl, headers, data, method)
193+
_headers = deepcopy(headers)
194+
super(JsonQuery, self).__init__(_oauth_baseurl, _headers, data, method)
176195
self.add_path(path)
177196

178197

179198
class ClipsQuery(DownloadQuery):
180199
def __init__(self, path, headers={}, data={}, method=methods.GET):
181-
super(ClipsQuery, self).__init__(_clips_baseurl, headers, data, method)
200+
_headers = deepcopy(headers)
201+
super(ClipsQuery, self).__init__(_clips_baseurl, _headers, data, method)
182202
self.add_path(path)
183203

184204

185205
class UploadsQuery(DownloadQuery):
186206
def __init__(self, path, headers={}, data={}, method=methods.PUT):
187-
super(UploadsQuery, self).__init__(_uploads_baseurl, headers, data, method)
207+
_headers = deepcopy(headers)
208+
super(UploadsQuery, self).__init__(_uploads_baseurl, _headers, data, method)
188209
self.add_path(path)
189210

190211

0 commit comments

Comments
 (0)