Skip to content

Commit

Permalink
Add ability to filter My Subscriptions by duration anxdpanic#984
Browse files Browse the repository at this point in the history
- "{duration}<operator><seconds>" to My Subscription filter
  - where <operator> can be >, >= (default), <, <=, =, ==, or !=
  - and where <seconds> is the desired duration criteria
  • Loading branch information
MoojMidge committed Nov 21, 2024
1 parent c62adc0 commit 5ba5b5d
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 22 deletions.
2 changes: 2 additions & 0 deletions resources/lib/youtube_plugin/kodion/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
rm_dir,
seconds_to_duration,
select_stream,
str_to_operator,
strip_html_from_text,
to_unicode,
validate_ip_address,
Expand All @@ -49,6 +50,7 @@
'rm_dir',
'seconds_to_duration',
'select_stream',
'str_to_operator',
'strip_html_from_text',
'to_unicode',
'validate_ip_address',
Expand Down
24 changes: 24 additions & 0 deletions resources/lib/youtube_plugin/kodion/utils/methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@
import shutil
from datetime import timedelta
from math import floor, log
from operator import (
eq as op_eq,
ne as op_ne,
gt as op_gt,
ge as op_ge,
lt as op_lt,
le as op_le,
)

from ..compatibility import byte_string_type, string_type, xbmc, xbmcvfs
from ..logger import Logger
Expand All @@ -36,6 +44,7 @@
'rm_dir',
'seconds_to_duration',
'select_stream',
'str_to_operator',
'strip_html_from_text',
'to_unicode',
'validate_ip_address',
Expand Down Expand Up @@ -325,3 +334,18 @@ def wait(timeout=None):

def redact_ip(url):
return re.sub(r'([?&/])ip([=/])[^?&/]+', r'\g<1>ip\g<2><redacted>', url)


_STR_OP_MAP = {
'=': op_eq,
'==': op_eq,
'!=': op_ne,
'>': op_gt,
'>=': op_ge,
'<': op_lt,
'<=': op_le,
}


def str_to_operator(op_str):
return _STR_OP_MAP.get(op_str, op_ge)
40 changes: 30 additions & 10 deletions resources/lib/youtube_plugin/youtube/client/youtube.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from functools import partial
from itertools import chain, islice
from random import randint
from re import split as re_split
from traceback import format_stack

from .login_client import LoginClient
Expand All @@ -25,6 +26,7 @@
from ...kodion.items import DirectoryItem
from ...kodion.utils import (
datetime_parser,
str_to_operator,
strip_html_from_text,
to_unicode,
)
Expand Down Expand Up @@ -1545,15 +1547,33 @@ def get_my_subscriptions(self,
'blacklist': settings.get_bool(
'youtube.filter.my_subscriptions_filtered.blacklist', False
),
'set': {
item.lower()
for item in settings.get_string(
'youtube.filter.my_subscriptions_filtered.list', ''
).replace(', ', ',').split(',')
},
'names': None,
'durations': None,
}
durations = []
subscription_filters['names'] = {
item.lower()
for item in settings.get_string(
'youtube.filter.my_subscriptions_filtered.list', ''
).replace(', ', ',').split(',')
if (not item.startswith(('{duration}', '{DURATION}'))
or durations.append(re_split(r'^(\D*)(\d*)$', item[10:])))
}
durations = {
op: int(duration)
for _, op, duration, _ in durations
if op and duration
}

def callback(item, criteria=durations):
duration = item.get_duration()
for op, value in criteria.items():
if not str_to_operator(op)(duration, value):
return False
return True
else:
subscription_filters = None
callback = None

page = page_token or 1
totals = {
Expand Down Expand Up @@ -1745,7 +1765,7 @@ def _parse_feeds(feeds,
else:
continue
if filters:
filtered = channel_name and channel_name in filters['set']
filtered = channel_name and channel_name in filters['names']
if filters['blacklist']:
if not filtered:
all_items[channel_id] = feed_items
Expand Down Expand Up @@ -1935,18 +1955,18 @@ def _threaded_fetch(kwargs,
progress_dialog=progress_dialog,
)
if not items:
return None
return None, None

if totals['num'] > totals['end']:
v3_response['nextPageToken'] = page + 1
if totals['num'] > totals['start']:
items = items[totals['start']:min(totals['num'], totals['end'])]
else:
return None
return None, None

v3_response['pageInfo']['totalResults'] = totals['num']
v3_response['items'] = items
return v3_response
return v3_response, callback

def get_saved_playlists(self, page_token, offset):
if not page_token:
Expand Down
18 changes: 10 additions & 8 deletions resources/lib/youtube_plugin/youtube/helper/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1274,16 +1274,18 @@ def filter_videos(items,
upcoming=True,
completed=True,
vod=True,
callback=None,
**_kwargs):
return [
item
for item in items
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)
or (upcoming_live and upcoming and item.upcoming and item.live)
or (vod and shorts and item.vod)
or (vod and not shorts and item.vod and not item.short)
))
if ((not item.callback or item.callback(item))
and (not callback or callback(item))
and (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)
or (upcoming_live and upcoming and item.upcoming and item.live)
or (vod and shorts and item.vod)
or (vod and not shorts and item.vod and not item.short))))
]
5 changes: 3 additions & 2 deletions resources/lib/youtube_plugin/youtube/helper/v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ def response_to_items(provider,
reverse=False,
process_next_page=True,
item_filter=None,
callback=None,
progress_dialog=None):
kind, is_youtube, is_plugin, kind_type = _parse_kind(json_data)
if not is_youtube and not is_plugin:
Expand Down Expand Up @@ -565,8 +566,8 @@ def response_to_items(provider,
else:
raise KodionException('Unknown kind: %s' % kind)

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

if sort is not None:
items.sort(key=sort, reverse=reverse)
Expand Down
3 changes: 2 additions & 1 deletion resources/lib/youtube_plugin/youtube/helper/yt_specials.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ def _process_my_subscriptions(provider, context, client, filtered=False):
),
) as progress_dialog:
params = context.get_params()
json_data = client.get_my_subscriptions(
json_data, callback = client.get_my_subscriptions(
page_token=params.get('page', 1),
logged_in=provider.is_logged_in(),
do_filter=filtered,
Expand All @@ -317,6 +317,7 @@ def _process_my_subscriptions(provider, context, client, filtered=False):
context,
json_data,
progress_dialog=progress_dialog,
callback=callback,
)


Expand Down
3 changes: 2 additions & 1 deletion resources/lib/youtube_plugin/youtube/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -1607,7 +1607,7 @@ def _update(new_item):
elif isinstance(old_item, BaseItem):
bookmark_timestamp = old_item.get_bookmark_timestamp()
else:
return
return True

if new_item.available:
new_item.bookmark_id = _id
Expand All @@ -1627,6 +1627,7 @@ def _update(new_item):
new_item.set_title(context.get_ui().color(
'AA808080', new_item.get_title()
))
return True

return _update

Expand Down

0 comments on commit 5ba5b5d

Please sign in to comment.