Skip to content

Commit

Permalink
Re-enable player request clients that require specific OAuth tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
MoojMidge committed Dec 7, 2024
1 parent 65496fe commit c9761e7
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 189 deletions.
34 changes: 15 additions & 19 deletions resources/lib/youtube_plugin/youtube/client/request_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class YouTubeRequestClient(BaseRequestsClass):
# Limited subtitle availability
'android_testsuite': {
'_id': 30,
'_disabled': True,
'_auth_required': 'tv',
'_query_subtitles': True,
'json': {
'params': _PLAYER_PARAMS['android_testsuite'],
Expand Down Expand Up @@ -117,7 +117,7 @@ class YouTubeRequestClient(BaseRequestsClass):
# Limited subtitle availability
'android_youtube_tv': {
'_id': 29,
'_disabled': True,
'_auth_required': 'tv',
'_query_subtitles': True,
'json': {
'params': _PLAYER_PARAMS['android'],
Expand Down Expand Up @@ -172,7 +172,6 @@ class YouTubeRequestClient(BaseRequestsClass):
},
'ios': {
'_id': 5,
'_auth_type': False,
'_os': {
'major': '17',
'minor': '5',
Expand Down Expand Up @@ -205,6 +204,7 @@ class YouTubeRequestClient(BaseRequestsClass):
},
'media_connect_frontend': {
'_id': 95,
'_auth_required': 'tv',
'_query_subtitles': True,
'json': {
'context': {
Expand Down Expand Up @@ -288,6 +288,8 @@ class YouTubeRequestClient(BaseRequestsClass):
'videoId': None,
},
'headers': {
'Origin': 'https://www.youtube.com',
'Referer': 'https://www.youtube.com/watch?v={json[videoId]}',
'Accept-Encoding': 'gzip, deflate',
'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'Accept': '*/*',
Expand Down Expand Up @@ -369,21 +371,19 @@ def json_traverse(cls, json_data, path, default=None):
def build_client(cls, client_name=None, data=None):
templates = {}

base_client = None
client = None
if client_name:
base_client = cls.CLIENTS.get(client_name)
if base_client and base_client.get('_disabled'):
client = cls.CLIENTS.get(client_name)
if client and client.get('_disabled'):
return None
if not base_client:
base_client = YouTubeRequestClient.CLIENTS['web']
base_client = base_client.copy()
if not client:
client = YouTubeRequestClient.CLIENTS['web']
client = client.copy()

if data:
client = merge_dicts(base_client, data)
client = merge_dicts(client, data)
client = merge_dicts(cls.CLIENTS['_common'], client, templates)
client['_name'] = client_name
if base_client.get('_auth_required'):
client['_auth_required'] = True

for values, template_id, template in templates.values():
if template_id in values:
Expand All @@ -393,16 +393,12 @@ def build_client(cls, client_name=None, data=None):
try:
params = client['params']
auth_required = client.get('_auth_required')
auth_requested = client.get('_auth_requested')
auth_type = client.get('_auth_type')
if auth_type == 'tv' and auth_requested != 'personal':
if auth_required == 'tv':
auth_token = client.get('_access_token_tv')
elif auth_type is not False:
auth_token = client.get('_access_token')
else:
auth_token = None
auth_token = client.get('_access_token')

if auth_token and (auth_required or auth_requested):
if auth_token:
headers = client['headers']
if 'Authorization' in headers:
headers = headers.copy()
Expand Down
95 changes: 45 additions & 50 deletions resources/lib/youtube_plugin/youtube/client/youtube.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

class YouTube(LoginClient):
CLIENTS = {
'v1': {
1: {
'url': 'https://www.youtube.com/youtubei/v1/{_endpoint}',
'method': None,
'json': {
Expand All @@ -47,8 +47,8 @@ class YouTube(LoginClient):
'Host': 'www.youtube.com',
},
},
'v3': {
'_auth_requested': True,
3: {
'_auth_required': True,
'url': 'https://www.googleapis.com/youtube/v3/{_endpoint}',
'method': None,
'headers': {
Expand Down Expand Up @@ -85,24 +85,6 @@ class YouTube(LoginClient):
'Host': 'www.youtube.com',
},
},
'watch_history': {
'_auth_required': True,
'_auth_type': 'personal',
'_video_id': None,
'headers': {
'Host': 's.youtube.com',
'Referer': 'https://www.youtube.com/watch?v={_video_id}',
},
'params': {
'referrer': 'https://accounts.google.com/',
'ns': 'yt',
'el': 'detailpage',
'ver': '2',
'fs': '0',
'volume': '100',
'muted': '0',
},
},
'_common': {
'_access_token': None,
'_access_token_tv': None,
Expand Down Expand Up @@ -173,13 +155,29 @@ def update_watch_history(self, context, video_id, url, status=None):
et=et,
state=state))

client_data = {
'_video_id': video_id,
'url': url,
'error_title': 'Failed to update watch history',
headers = {
'Host': 's.youtube.com',
'Connection': 'keep-alive',
'Accept-Encoding': 'gzip, deflate',
'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.5',
'DNT': '1',
'Referer': 'https://www.youtube.com/watch?v=' + video_id,
'User-Agent': ('Mozilla/5.0 (Linux; Android 10; SM-G981B)'
' AppleWebKit/537.36 (KHTML, like Gecko)'
' Chrome/80.0.3987.162 Mobile Safari/537.36'),
}
params = {
'docid': video_id,
'referrer': 'https://accounts.google.com/',
'ns': 'yt',
'el': 'detailpage',
'ver': '2',
'fs': '0',
'volume': '100',
'muted': '0',
}

params = {}
if cmt is not None:
params['cmt'] = format(cmt, '.3f')
if st is not None:
Expand All @@ -188,11 +186,11 @@ def update_watch_history(self, context, video_id, url, status=None):
params['et'] = format(et, '.3f')
if state is not None:
params['state'] = state
if self._access_token:
params['access_token'] = self._access_token

self.api_request(client='watch_history',
client_data=client_data,
params=params,
no_content=True)
self.request(url, params=params, headers=headers,
error_msg='Failed to update watch history')

def get_streams(self,
context,
Expand All @@ -202,7 +200,8 @@ def get_streams(self,
use_mpd=True):
return StreamInfo(
context,
access_token=(self._access_token or self._access_token_tv),
access_token=self._access_token,
access_token_tv=self._access_token_tv,
ask_for_quality=ask_for_quality,
audio_only=audio_only,
use_mpd=use_mpd,
Expand Down Expand Up @@ -328,7 +327,7 @@ def unsubscribe(self, subscription_id, **kwargs):

def unsubscribe_channel(self, channel_id, **kwargs):
post_data = {'channelIds': [channel_id]}
return self.api_request(client='v1',
return self.api_request(version=1,
method='POST',
path='subscription/unsubscribe',
post_data=post_data,
Expand Down Expand Up @@ -456,7 +455,7 @@ def get_recommended_for_home(self,
}
post_data['context'] = context

result = self.api_request(client='v1',
result = self.api_request(version=1,
method='POST',
path='browse',
post_data=post_data)
Expand Down Expand Up @@ -1070,9 +1069,8 @@ def get_related_videos(self,
if page_token:
post_data['continuation'] = page_token

result = self.api_request(client=('tv' if retry == 1 else
'tv_embed' if retry == 2 else
'v1'),
result = self.api_request(version=('tv' if retry == 1 else
'tv_embed' if retry == 2 else 1),
method='POST',
path='next',
post_data=post_data,
Expand Down Expand Up @@ -1976,7 +1974,7 @@ def _perform(_playlist_idx, _page_token, _offset, _result):
else:
_post_data['browseId'] = 'FEmy_youtube'

_json_data = self.api_request(client='v1',
_json_data = self.api_request(version=1,
method='POST',
path='browse',
post_data=_post_data)
Expand Down Expand Up @@ -2071,7 +2069,7 @@ def _perform(_playlist_idx, _page_token, _offset, _result):
}

playlist_index = None
json_data = self.api_request(client='v1',
json_data = self.api_request(version=1,
method='POST',
path='browse',
post_data=_en_post_data)
Expand Down Expand Up @@ -2171,20 +2169,18 @@ def _error_hook(self, **kwargs):
return '', info, details, data, False, exception

def api_request(self,
client='v3',
version=3,
method='GET',
client_data=None,
path=None,
params=None,
post_data=None,
headers=None,
no_login=False,
**kwargs):
if not client_data:
client_data = {}
client_data.setdefault('method', method)
if path:
client_data['_endpoint'] = path.strip('/')
client_data = {
'_endpoint': path.strip('/'),
'method': method,
}
if headers:
client_data['headers'] = headers
if method in {'POST', 'PUT'}:
Expand All @@ -2198,14 +2194,13 @@ def api_request(self,

abort = False
if not no_login:
client_data.setdefault('_auth_requested', True)
# a config can decide if a token is allowed
if self._access_token and self._config.get('token-allowed', True):
client_data['_access_token'] = self._access_token
if self._access_token_tv:
client_data['_access_token_tv'] = self._access_token_tv

client = self.build_client(client, client_data)
client = self.build_client(version, client_data)
if not client:
client = {}
abort = True
Expand Down Expand Up @@ -2249,13 +2244,13 @@ def api_request(self,

context = self._context
context.log_debug('API request:'
'\n\ttype: |{type}|'
'\n\tversion: |{version}|'
'\n\tmethod: |{method}|'
'\n\tpath: |{path}|'
'\n\tparams: |{params}|'
'\n\tpost_data: |{data}|'
'\n\theaders: |{headers}|'
.format(type=client.get('_name'),
.format(version=version,
method=method,
path=path,
params=log_params,
Expand Down
Loading

0 comments on commit c9761e7

Please sign in to comment.