Skip to content

Commit

Permalink
Merge pull request #908 from MoojMidge/master
Browse files Browse the repository at this point in the history
v7.1.0+beta.5
  • Loading branch information
MoojMidge authored Sep 26, 2024
2 parents 6c14221 + 7540121 commit 5050e86
Show file tree
Hide file tree
Showing 12 changed files with 97 additions and 26 deletions.
2 changes: 1 addition & 1 deletion addon.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.youtube" name="YouTube" version="7.1.0+beta.4" provider-name="anxdpanic, bromix, MoojMidge">
<addon id="plugin.video.youtube" name="YouTube" version="7.1.0+beta.5" provider-name="anxdpanic, bromix, MoojMidge">
<requires>
<import addon="xbmc.python" version="3.0.0"/>
<import addon="script.module.requests" version="2.27.1"/>
Expand Down
12 changes: 12 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## v7.1.0+beta.5
### Fixed
- Fix default thumbnails not being updated if available

### Changed
- Remove revoked API credentials
- Improve handling of "forbidden - The caller does not have permission" errors

### New
- Preliminary support for /watch_videos YouTube urls
- Player client updates

## v7.1.0+beta.4
### Fixed
- Fix playback history related context menu items not being shown #904
Expand Down
10 changes: 5 additions & 5 deletions resources/lib/youtube_plugin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@

key_sets = {
'youtube-tv': {
'client_id': 'ODYxNTU2NzA4NDU0LWQ2ZGxtM2xoMDVpZGQ4bnBlazE4azZiZThiYTNvYzY4',
'api_key': 'QUl6YVN5QzZmdlpTSkhBN1Z6NWo4akNpS1J0N3RVSU9xakUyTjNn',
'client_secret': 'U2JvVmhvRzlzMHJOYWZpeENTR0dLWEFU'
'api_key': '',
'client_id': '',
'client_secret': '',
},
'provided': {
'0': {
'client_id': '',
'api_key': '',
'client_secret': ''
'client_id': '',
'client_secret': '',
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class AbstractContext(object):
'channel_ids',
'item_filter',
'playlist_ids',
'video_ids',
}
_STRING_PARAMS = {
'api_key',
Expand Down
15 changes: 13 additions & 2 deletions resources/lib/youtube_plugin/kodion/plugin/xbmc/xbmc_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
)
from ...exceptions import KodionException
from ...items import (
CommandItem,
directory_listitem,
image_listitem,
media_listitem,
Expand Down Expand Up @@ -179,10 +180,20 @@ def run(self, provider, context, focused=None):
))
ui.on_ok('Error in ContentProvider', exc.__str__())

items = None
items = isinstance(result, (list, tuple))
item_count = 0
if items:
if not result:
result = [
CommandItem(
context.localize('page.back'),
'Action(ParentDir)',
context,
image='DefaultFolderBack.png',
plot=context.localize('page.empty'),
)
]

if result and isinstance(result, (list, tuple)):
show_fanart = settings.fanart_selection()
items = [
self._LIST_ITEM_MAP[item.__class__.__name__](
Expand Down
33 changes: 31 additions & 2 deletions resources/lib/youtube_plugin/youtube/client/request_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class YouTubeRequestClient(BaseRequestsClass):
},
},
'thirdParty': {
'embedUrl': 'https://www.youtube.com/embed/{json[videoId]}',
'embedUrl': 'https://www.youtube.com/',
},
},
'headers': {
Expand Down Expand Up @@ -129,6 +129,9 @@ class YouTubeRequestClient(BaseRequestsClass):
'platform': 'MOBILE',
},
},
'thirdParty': {
'embedUrl': 'https://www.google.com/',
},
},
'headers': {
'User-Agent': ('com.google.android.apps.youtube.unplugged/'
Expand All @@ -139,6 +142,32 @@ class YouTubeRequestClient(BaseRequestsClass):
'X-YouTube-Client-Version': '{json[context][client][clientVersion]}',
},
},
'android_vr': {
'_id': 28,
'_query_subtitles': False,
'json': {
'context': {
'client': {
'clientName': 'ANDROID_VR',
'clientVersion': '1.57.29',
'deviceMake': 'Oculus',
'deviceModel': 'Quest 3',
'osName': 'Android',
'osVersion': '12L',
'androidSdkVersion': '32'
}
}
},
'header': {
'User-Agent': ('com.google.android.apps.youtube.vr.oculus/'
'{json[context][client][clientVersion]}'
' (Linux; U; {json[context][client][osName]}'
' {json[context][client][osVersion]};'
' eureka-user Build/SQ3A.220605.009.A1) gzip'),
'X-YouTube-Client-Name': '{_id}',
'X-YouTube-Client-Version': '{json[context][client][clientVersion]}',
},
},
'ios': {
'_id': 5,
'_os': {
Expand Down Expand Up @@ -197,7 +226,7 @@ class YouTubeRequestClient(BaseRequestsClass):
},
},
'thirdParty': {
'embedUrl': 'https://www.youtube.com',
'embedUrl': 'https://www.google.com/',
},
},
# Headers from a 2022 Samsung Tizen 6.5 based Smart TV
Expand Down
2 changes: 1 addition & 1 deletion resources/lib/youtube_plugin/youtube/client/youtube.py
Original file line number Diff line number Diff line change
Expand Up @@ -1982,7 +1982,7 @@ def _error_hook(self, **kwargs):
if getattr(exc, 'notify', True):
ok_dialog = False
timeout = 5000
if reason == 'accessNotConfigured':
if reason in {'accessNotConfigured', 'forbidden'}:
notification = self._context.localize('key.requirement')
ok_dialog = True
elif reason == 'keyInvalid' and message == 'Bad Request':
Expand Down
3 changes: 2 additions & 1 deletion resources/lib/youtube_plugin/youtube/helper/stream_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -711,8 +711,9 @@ def __init__(self,
),
# Will play most videos with subtitles at full resolution with HDR
# Some restricted videos require additional requests for subtitles
# Limited audio stream availability
# Limited audio stream availability with some clients
'mpd': (
'android_vr',
'android_youtube_tv',
'android_testsuite',
),
Expand Down
11 changes: 11 additions & 0 deletions resources/lib/youtube_plugin/youtube/helper/url_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,17 @@ def resolve(self, url, url_components, method='HEAD'):
})
return url_components._replace(query=urlencode(params)).geturl()

elif path == '/watch_videos':
params = dict(parse_qsl(url_components.query))
new_components = urlsplit(response.url)
new_params = dict(parse_qsl(new_components.query))
# add/overwrite all other params from original query string
new_params.update(params)
# build new URL from these components
return new_components._replace(
query=urlencode(new_params)
).geturl()

# we try to extract the channel id from the html content
# With the channel id we can construct a URL we already work with
# https://www.youtube.com/channel/<CHANNEL_ID>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def add_url(self, url, context):
('v', 'video_id', False),
('live', 'live', False),
('clip', 'clip', False),
('video_ids', 'video_ids', False),
)
if old in url_params
}
Expand All @@ -82,15 +83,26 @@ def add_url(self, url, context):
))
return

if 'video_id' in new_params:
if 'video_ids' in new_params:
for video_id in new_params['video_ids'].split(','):
video_item = VideoItem(
name='',
uri=context.create_uri(
(PATHS.PLAY,),
dict(new_params, video_id=video_id),
)
)
self._video_id_dict[video_id] = video_item

elif 'video_id' in new_params:
video_id = new_params['video_id']

video_item = VideoItem(
'', context.create_uri((PATHS.PLAY,), new_params)
)
self._video_id_dict[video_id] = video_item

elif 'playlist_id' in new_params:
if 'playlist_id' in new_params:
playlist_id = new_params['playlist_id']

if self._flatten:
Expand All @@ -102,7 +114,7 @@ def add_url(self, url, context):
)
self._playlist_id_dict[playlist_id] = playlist_item

elif 'channel_id' in new_params:
if 'channel_id' in new_params:
channel_id = new_params['channel_id']
live = new_params.get('live')

Expand Down
2 changes: 1 addition & 1 deletion resources/lib/youtube_plugin/youtube/helper/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@ def update_video_infos(provider, context, video_id_dict,

# try to find a better resolution for the image
image = media_item.get_image()
if not image:
if not image or image.startswith('Default'):
image = get_thumbnail(thumb_size, snippet.get('thumbnails'))
if image.endswith('_live.jpg'):
image = ''.join((image, '?ct=', thumb_stamp))
Expand Down
14 changes: 4 additions & 10 deletions resources/lib/youtube_plugin/youtube/helper/v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,7 @@ def _process_list_response(provider, context, json_data, item_filter):
yt_items = json_data.get('items', [])
if not yt_items:
context.log_warning('v3 response: Items list is empty')
return [
CommandItem(
context.localize('page.back'),
'Action(ParentDir)',
context,
image='DefaultFolderBack.png',
plot=context.localize('page.empty'),
)
]
return []

video_id_dict = {}
channel_id_dict = {}
Expand Down Expand Up @@ -455,6 +447,8 @@ def response_to_items(provider,
result = _process_list_response(
provider, context, json_data, item_filter
)
if not result:
return result
else:
raise KodionException('Unknown kind: %s' % kind)

Expand All @@ -465,7 +459,7 @@ def response_to_items(provider,
result.sort(key=sort, reverse=reverse)

# no processing of next page item
if not result or not process_next_page or params.get('hide_next_page'):
if not process_next_page or params.get('hide_next_page'):
return result

# next page
Expand Down

0 comments on commit 5050e86

Please sign in to comment.