Skip to content

Commit

Permalink
Improve updating of bookmarks and displaying unavailable bookmarked v…
Browse files Browse the repository at this point in the history
…ideos
  • Loading branch information
MoojMidge committed Oct 12, 2024
1 parent d539d9e commit 0739682
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 32 deletions.
34 changes: 34 additions & 0 deletions resources/lib/youtube_plugin/kodion/items/base_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ def __init__(self, name, uri, image=None, fanart=None):
self.set_name(name)

self._uri = uri
self._available = True
self._callback = None

self._image = ''
if image:
Expand All @@ -42,6 +44,7 @@ def __init__(self, name, uri, image=None, fanart=None):
if fanart:
self.set_fanart(fanart)

self._bookmark_id = None
self._bookmark_timestamp = None
self._context_menu = None
self._added_utc = None
Expand Down Expand Up @@ -144,6 +147,22 @@ def get_uri(self):
"""
return self._uri

@property
def available(self):
return self._available

@available.setter
def available(self, value):
self._available = value

@property
def callback(self):
return self._callback

@callback.setter
def callback(self, value):
self._callback = value

def set_image(self, image):
if not image:
return
Expand Down Expand Up @@ -238,6 +257,14 @@ def get_count(self):
def set_count(self, count):
self._count = int(count or 0)

@property
def bookmark_id(self):
return self._bookmark_id

@bookmark_id.setter
def bookmark_id(self, value):
self._bookmark_id = value

def set_bookmark_timestamp(self, timestamp):
self._bookmark_timestamp = timestamp

Expand All @@ -248,6 +275,10 @@ def get_bookmark_timestamp(self):
def playable(self):
return self._playable

@playable.setter
def playable(self, value):
self._playable = value

def add_artist(self, artist):
if artist:
if self._artists is None:
Expand Down Expand Up @@ -337,3 +368,6 @@ def encode(self, obj, nested=False):
if nested:
return output
return super(_Encoder, self).encode(output)

def default(self, obj):
pass
15 changes: 12 additions & 3 deletions resources/lib/youtube_plugin/kodion/items/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,17 @@ def from_json(json_data, *args):
:param json_data:
:return:
"""
timestamp = args[0][1] if args and args[0] and len(args[0]) == 4 else None
if args and args[0] and len(args[0]) == 4:
bookmark_id = args[0][0]
bookmark_timestamp = args[0][1]
else:
bookmark_id = None
bookmark_timestamp = None

if isinstance(json_data, string_type):
if json_data == to_str(None):
# Channel bookmark that will be updated. Store timestamp for update
return timestamp
return bookmark_timestamp
json_data = json.loads(json_data, object_hook=_decoder)

item_type = json_data.get('type')
Expand All @@ -69,6 +74,10 @@ def from_json(json_data, *args):
for key, value in json_data.get('data', {}).items():
if hasattr(item, key):
setattr(item, key, value)
item.set_bookmark_timestamp(timestamp)

if bookmark_id:
item.bookmark_id = bookmark_id
if bookmark_timestamp:
item.set_bookmark_timestamp(bookmark_timestamp)

return item
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,8 @@ def get_videos(self,
for yt_item in batch.get('items', [])
if yt_item
}
new_data = dict(dict.fromkeys(to_update, {}), **new_data)
new_data = dict(dict.fromkeys(to_update, {'_unavailable': True}),
**new_data)
result.update(new_data)
self.cache_data(new_data, defer=defer_cache)

Expand Down
15 changes: 12 additions & 3 deletions resources/lib/youtube_plugin/youtube/helper/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,11 +571,20 @@ def update_video_infos(provider, context, video_id_dict,
playlist_match = __RE_PLAYLIST.match(path)

for video_id, yt_item in data.items():
if not yt_item or 'snippet' not in yt_item:
if not yt_item:
continue

media_item = video_id_dict.get(video_id)
if not media_item:
continue

if 'snippet' not in yt_item:
if yt_item.get('_unavailable'):
media_item.playable = False
media_item.available = False
continue
snippet = yt_item['snippet']

media_item = video_id_dict[video_id]
media_item.set_mediatype(
CONTENT.AUDIO_TYPE
if isinstance(media_item, AudioItem) else
Expand Down Expand Up @@ -1232,7 +1241,7 @@ def filter_videos(items,
return [
item
for item in items
if (not item.playable or (
if ((item.callback and item.callback(item)) or not item.playable or (
(completed and item.completed)
or (live and item.live and not item.upcoming)
or (premieres and upcoming and item.upcoming and not item.live)
Expand Down
37 changes: 21 additions & 16 deletions resources/lib/youtube_plugin/youtube/helper/v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,16 @@ 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 []
return None

video_id_dict = {}
channel_id_dict = {}
playlist_id_dict = {}
playlist_item_id_dict = {}
subscription_id_dict = {}

result = []
items = []
do_callbacks = False

new_params = {}
params = context.get_params()
Expand Down Expand Up @@ -81,7 +82,6 @@ def _process_list_response(provider, context, json_data, item_filter):
description = strip_html_from_text(localised_info.get('description')
or snippet.get('description')
or '')
# context.log_debug(f'***********\n{item_id = }, {title = }\n{yt_item = }\n***************')

thumbnails = snippet.get('thumbnails')
if not thumbnails:
Expand Down Expand Up @@ -273,13 +273,14 @@ def _process_list_response(provider, context, json_data, item_filter):
if isinstance(item, VideoItem):
# Set track number from playlist, or set to current list length to
# match "Default" (unsorted) sort order
position = snippet.get('position') or len(result)
position = snippet.get('position') or len(items)
item.set_track_number(position + 1)

if '_callback' in yt_item:
yt_item['_callback'](item)
item.callback = yt_item['_callback']
do_callbacks = True

result.append(item)
items.append(item)

# this will also update the channel_id_dict with the correct channel_id
# for each video.
Expand Down Expand Up @@ -437,7 +438,7 @@ def _fetch(resource):
resource['thread'] = new_thread
new_thread.start()

return result
return items, do_callbacks


_KNOWN_RESPONSE_KINDS = {
Expand Down Expand Up @@ -479,19 +480,23 @@ def response_to_items(provider,
provider, context, json_data, item_filter
)
if not result:
return result
return []

items, do_callbacks = result
if not items:
return items
else:
raise KodionException('Unknown kind: %s' % kind)

if item_filter:
result = filter_videos(result, **item_filter)
if item_filter or do_callbacks:
items = filter_videos(items, **item_filter)

if sort is not None:
result.sort(key=sort, reverse=reverse)
items.sort(key=sort, reverse=reverse)

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

# next page
"""
Expand All @@ -516,7 +521,7 @@ def response_to_items(provider,
elif current_page:
new_params['page_token'] = ''
else:
return result
return items

page_info = json_data.get('pageInfo', {})
yt_total_results = int(page_info.get('totalResults', 0))
Expand All @@ -531,7 +536,7 @@ def response_to_items(provider,
next_page = 1
new_params['page'] = 1
else:
return result
return items

yt_visitor_data = json_data.get('visitorData')
if yt_visitor_data:
Expand All @@ -547,9 +552,9 @@ def response_to_items(provider,
new_params['offset'] = offset

next_page_item = NextPageItem(context, new_params)
result.append(next_page_item)
items.append(next_page_item)

return result
return items


def _parse_kind(item):
Expand Down
38 changes: 29 additions & 9 deletions resources/lib/youtube_plugin/youtube/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -1424,21 +1424,43 @@ def on_bookmarks(provider, context, re_match):
'items': []
}

def _update_bookmark(_id, timestamp):
def _update_bookmark(context, _id, old_item):
def _update(new_item):
new_item.set_bookmark_timestamp(timestamp)
bookmarks_list.update_item(_id, repr(new_item), timestamp)
if isinstance(old_item, float):
bookmark_timestamp = old_item
elif isinstance(old_item, BaseItem):
bookmark_timestamp = old_item.get_bookmark_timestamp()
else:
return

if new_item.available:
new_item.bookmark_id = _id
new_item.set_bookmark_timestamp(bookmark_timestamp)
new_item.callback = None
bookmarks_list.update_item(
_id,
repr(new_item),
bookmark_timestamp,
)
else:
new_item.__dict__.update(old_item.__dict__)
new_item.bookmark_id = _id
new_item.set_bookmark_timestamp(bookmark_timestamp)
new_item.available = False
new_item.playable = False
new_item.set_title(context.get_ui().color(
'AA808080', new_item.get_title()
))

return _update

for item_id, item in items.items():
callback = _update_bookmark(context, item_id, item)
if isinstance(item, float):
kind = 'youtube#channel'
yt_id = item_id
callback = _update_bookmark(item_id, item)
partial = True
elif isinstance(item, BaseItem):
callback = None
partial = False

if isinstance(item, VideoItem):
Expand All @@ -1452,7 +1474,9 @@ def _update(new_item):
kind = 'youtube#channel'
yt_id = getattr(item, 'channel_id', None)
else:
kind = None
yt_id = None
partial = False

if not yt_id:
if isinstance(item, BaseItem):
Expand All @@ -1467,10 +1491,6 @@ def _update(new_item):
continue
kind = 'youtube#' + kind
partial = True
callback = _update_bookmark(
item_id,
item.get_bookmark_timestamp(),
)
break
else:
if to_delete:
Expand Down

0 comments on commit 0739682

Please sign in to comment.