From 2d135991305aa3050b1f3a8e80f5839b2444aa6c Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Mon, 16 Sep 2024 05:31:17 +1000 Subject: [PATCH 01/10] Fix timing issues with wait_for parameter of XbmcContext.execute --- .../kodion/constants/__init__.py | 4 ++-- .../kodion/context/abstract_context.py | 3 +-- .../kodion/context/xbmc/xbmc_context.py | 19 ++++++++++++------- .../youtube_plugin/kodion/script_actions.py | 5 ++--- .../youtube/helper/yt_setup_wizard.py | 10 +++++----- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/resources/lib/youtube_plugin/kodion/constants/__init__.py b/resources/lib/youtube_plugin/kodion/constants/__init__.py index eaf286868..ba16a54bb 100644 --- a/resources/lib/youtube_plugin/kodion/constants/__init__.py +++ b/resources/lib/youtube_plugin/kodion/constants/__init__.py @@ -37,7 +37,7 @@ # Flags ABORT_FLAG = 'abort_requested' BUSY_FLAG = 'busy' -WAIT_FLAG = 'builtin_running' +WAIT_END_FLAG = 'builtin_completed' # ListItem Properties CHANNEL_ID = 'channel_id' @@ -97,7 +97,7 @@ # Flags 'ABORT_FLAG', 'BUSY_FLAG', - 'WAIT_FLAG', + 'WAIT_END_FLAG', # ListItem properties 'CHANNEL_ID', diff --git a/resources/lib/youtube_plugin/kodion/context/abstract_context.py b/resources/lib/youtube_plugin/kodion/context/abstract_context.py index 3473e2468..edeb0bdba 100644 --- a/resources/lib/youtube_plugin/kodion/context/abstract_context.py +++ b/resources/lib/youtube_plugin/kodion/context/abstract_context.py @@ -449,8 +449,7 @@ def log_info(self, text): def clone(self, new_path=None, new_params=None): raise NotImplementedError() - @staticmethod - def execute(command): + def execute(self, command, wait=False, wait_for=None): raise NotImplementedError() @staticmethod diff --git a/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py b/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py index ece6ea1b6..b29e3e105 100644 --- a/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py +++ b/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py @@ -582,14 +582,19 @@ def clone(self, new_path=None, new_params=None): return new_context def execute(self, command, wait=False, wait_for=None): + if not wait_for: + xbmc.executebuiltin(command, wait) + return + + ui = self.get_ui() + ui.clear_property(wait_for) + pop_property = ui.pop_property + waitForAbort = xbmc.Monitor().waitForAbort + xbmc.executebuiltin(command, wait) - if wait_for: - ui = self.get_ui() - monitor = xbmc.Monitor() - while not monitor.abortRequested(): - monitor.waitForAbort(1) - if not ui.get_property(wait_for): - break + + while not pop_property(wait_for) and not waitForAbort(1): + pass @staticmethod def sleep(timeout=None): diff --git a/resources/lib/youtube_plugin/kodion/script_actions.py b/resources/lib/youtube_plugin/kodion/script_actions.py index 88c85a3f3..62dbaad47 100644 --- a/resources/lib/youtube_plugin/kodion/script_actions.py +++ b/resources/lib/youtube_plugin/kodion/script_actions.py @@ -17,7 +17,7 @@ DATA_PATH, RELOAD_ACCESS_MANAGER, TEMP_PATH, - WAIT_FLAG, + WAIT_END_FLAG, ) from .context import XbmcContext from .network import get_client_ip_address, httpd_status @@ -364,7 +364,6 @@ def switch_to_user(user): def run(argv): context = XbmcContext() ui = context.get_ui() - ui.set_property(WAIT_FLAG) try: category = action = params = None args = argv[1:] @@ -398,4 +397,4 @@ def run(argv): _user_actions(context, action, params) return finally: - ui.clear_property(WAIT_FLAG) + ui.set_property(WAIT_END_FLAG) diff --git a/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py b/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py index 0758b3230..7c8975f09 100644 --- a/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py +++ b/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py @@ -13,7 +13,7 @@ import os from ...kodion.compatibility import urlencode, xbmcvfs -from ...kodion.constants import ADDON_ID, DATA_PATH, WAIT_FLAG +from ...kodion.constants import ADDON_ID, DATA_PATH, WAIT_END_FLAG from ...kodion.network import Locator, httpd_status from ...kodion.sql_store import PlaybackHistory, SearchHistory from ...kodion.utils import current_system_version, to_unicode @@ -444,7 +444,7 @@ def process_subtitles(context, step, steps, **_kwargs): ): context.execute('RunScript({addon_id},config/subtitles)'.format( addon_id=ADDON_ID - ), wait_for=WAIT_FLAG) + ), wait_for=WAIT_END_FLAG) context.get_settings(refresh=True) return step @@ -485,7 +485,7 @@ def _convert_old_search_item(value, item): action='delete', query=urlencode({'target': 'other_file', 'path': search_db_path})), - wait_for=WAIT_FLAG, + wait_for=WAIT_END_FLAG, ) return step @@ -531,7 +531,7 @@ def _convert_old_history_item(value, item): action='delete', query=urlencode({'target': 'other_file', 'path': history_db_path})), - wait_for=WAIT_FLAG, + wait_for=WAIT_END_FLAG, ) return step @@ -550,7 +550,7 @@ def process_refresh_settings(context, step, steps, **_kwargs): .format(addon=ADDON_ID, action='refresh', query='target=settings_xml'), - wait_for=WAIT_FLAG, + wait_for=WAIT_END_FLAG, ) context.get_settings(refresh=True) return step From 65dd52eed69d5176640c0af60ff33dfad62d36a8 Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Mon, 16 Sep 2024 05:46:42 +1000 Subject: [PATCH 02/10] Add hide_next_page query parameter to hide plugin Next page item #896 --- resources/lib/youtube_plugin/kodion/context/abstract_context.py | 1 + resources/lib/youtube_plugin/youtube/helper/v3.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/lib/youtube_plugin/kodion/context/abstract_context.py b/resources/lib/youtube_plugin/kodion/context/abstract_context.py index edeb0bdba..f12ce7acb 100644 --- a/resources/lib/youtube_plugin/kodion/context/abstract_context.py +++ b/resources/lib/youtube_plugin/kodion/context/abstract_context.py @@ -52,6 +52,7 @@ class AbstractContext(object): 'enable', 'hide_folders', 'hide_live', + 'hide_next_page', 'hide_playlists', 'hide_search', 'incognito', diff --git a/resources/lib/youtube_plugin/youtube/helper/v3.py b/resources/lib/youtube_plugin/youtube/helper/v3.py index d80a1365d..a747a6892 100644 --- a/resources/lib/youtube_plugin/youtube/helper/v3.py +++ b/resources/lib/youtube_plugin/youtube/helper/v3.py @@ -471,7 +471,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: + if not result or not process_next_page or params.get('hide_next_page'): return result # next page From a259d21958b36a14f6b765f5b09f3366a228e454 Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Mon, 16 Sep 2024 06:09:23 +1000 Subject: [PATCH 03/10] Move IP location lookup to script and add to settings dialog --- .../lib/youtube_plugin/kodion/script_actions.py | 11 ++++++++++- .../youtube/helper/yt_setup_wizard.py | 16 ++++++++-------- resources/settings.xml | 10 ++++++++++ 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/resources/lib/youtube_plugin/kodion/script_actions.py b/resources/lib/youtube_plugin/kodion/script_actions.py index 62dbaad47..37cb391dc 100644 --- a/resources/lib/youtube_plugin/kodion/script_actions.py +++ b/resources/lib/youtube_plugin/kodion/script_actions.py @@ -20,7 +20,7 @@ WAIT_END_FLAG, ) from .context import XbmcContext -from .network import get_client_ip_address, httpd_status +from .network import Locator, get_client_ip_address, httpd_status from .utils import current_system_version, rm_dir, validate_ip_address @@ -126,6 +126,15 @@ def _config_actions(context, action, *_args): else: ui.show_notification(context.localize('httpd.not.running')) + elif action == 'geo_location': + locator = Locator(context) + locator.locate_requester() + coords = locator.coordinates() + if coords: + context.get_settings().set_location( + '{0[lat]},{0[lon]}'.format(coords) + ) + def _maintenance_actions(context, action, params): target = params.get('target') diff --git a/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py b/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py index 7c8975f09..363dbc440 100644 --- a/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py +++ b/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py @@ -14,7 +14,7 @@ from ...kodion.compatibility import urlencode, xbmcvfs from ...kodion.constants import ADDON_ID, DATA_PATH, WAIT_END_FLAG -from ...kodion.network import Locator, httpd_status +from ...kodion.network import httpd_status from ...kodion.sql_store import PlaybackHistory, SearchHistory from ...kodion.utils import current_system_version, to_unicode from ...kodion.utils.datetime_parser import strptime @@ -296,13 +296,13 @@ def process_geo_location(context, step, steps, **_kwargs): (localize('setup_wizard.prompt') % localize('setup_wizard.prompt.my_location')) ): - locator = Locator(context) - locator.locate_requester() - coords = locator.coordinates() - if coords: - context.get_settings().set_location( - '{0[lat]},{0[lon]}'.format(coords) - ) + context.execute( + 'RunScript({addon_id},config/geo_location)'.format( + addon_id=ADDON_ID, + ), + wait_for=WAIT_END_FLAG, + ) + context.get_settings(refresh=True) return step diff --git a/resources/settings.xml b/resources/settings.xml index d9c846891..140b5503f 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -874,6 +874,16 @@ 30550 + + 0 + + true + + RunScript($ID,config/geo_location) + + true + + 0 From 77d135b5a599b3ae94375bcc65b24d103e26586b Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Mon, 16 Sep 2024 08:38:24 +1000 Subject: [PATCH 04/10] Add new input_prompt command for search endpoint to bypass Kodi window caching --- resources/lib/youtube_plugin/kodion/abstract_provider.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/resources/lib/youtube_plugin/kodion/abstract_provider.py b/resources/lib/youtube_plugin/kodion/abstract_provider.py index 5998d686d..75ba41897 100644 --- a/resources/lib/youtube_plugin/kodion/abstract_provider.py +++ b/resources/lib/youtube_plugin/kodion/abstract_provider.py @@ -80,7 +80,7 @@ def __init__(self): self.register_path(r''.join(( '^', '(', PATHS.SEARCH, '|', PATHS.EXTERNAL_SEARCH, ')', - '/(?Pinput|query|list|remove|clear|rename)?/?$' + '/(?Pinput|input_prompt|query|list|remove|clear|rename)?/?$' )), self.on_search) self.register_path(r''.join(( @@ -341,7 +341,7 @@ def on_search(provider, context, re_match): ui.refresh_container() return True - if command == 'input': + if command.startswith('input'): query = None # came from page 1 of search query by '..'/back # user doesn't want to input on this path @@ -366,7 +366,10 @@ def on_search(provider, context, re_match): return False context.set_path(PATHS.SEARCH, 'query') - return provider.on_search_run(context=context, search_text=query) + return ( + provider.on_search_run(context=context, search_text=query), + {provider.RESULT_CACHE_TO_DISC: command != 'input_prompt'}, + ) context.set_content(CONTENT.LIST_CONTENT) result = [] From 59f89c5a50c5f7fbc788121a87e94afeb2cfdfc5 Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Tue, 17 Sep 2024 06:31:17 +1000 Subject: [PATCH 05/10] Disable cacheToDisc when refreshing --- resources/lib/youtube_plugin/kodion/abstract_provider.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/lib/youtube_plugin/kodion/abstract_provider.py b/resources/lib/youtube_plugin/kodion/abstract_provider.py index 75ba41897..162b29cec 100644 --- a/resources/lib/youtube_plugin/kodion/abstract_provider.py +++ b/resources/lib/youtube_plugin/kodion/abstract_provider.py @@ -166,9 +166,9 @@ def navigate(self, context): result, new_options = result options.update(new_options) - refresh = context.get_param('refresh') - if refresh is not None: - options[self.RESULT_UPDATE_LISTING] = bool(refresh) + if context.get_param('refresh'): + options[self.RESULT_CACHE_TO_DISC] = False + options[self.RESULT_UPDATE_LISTING] = True return result, options From 73497d5ae25ba2aff01760cdb45ee0eae286f959 Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:15:18 +1000 Subject: [PATCH 06/10] Make CHECK_SETTINGS notifications part of a WAKEUP event - Need to ensure that the monitor service handling the notification is in sync with plugin execution --- .../kodion/abstract_provider.py | 12 ++++++++++-- .../kodion/context/xbmc/xbmc_context.py | 4 +++- .../kodion/monitors/service_monitor.py | 19 +++++++++---------- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/resources/lib/youtube_plugin/kodion/abstract_provider.py b/resources/lib/youtube_plugin/kodion/abstract_provider.py index 162b29cec..c79f2c392 100644 --- a/resources/lib/youtube_plugin/kodion/abstract_provider.py +++ b/resources/lib/youtube_plugin/kodion/abstract_provider.py @@ -120,7 +120,11 @@ def run_wizard(self, context): settings = context.get_settings() ui = context.get_ui() - context.send_notification(CHECK_SETTINGS, 'defer') + context.wakeup( + CHECK_SETTINGS, + timeout=5, + payload={'state': 'defer'}, + ) wizard_steps = self.get_wizard_steps() @@ -143,7 +147,11 @@ def run_wizard(self, context): step += 1 finally: settings.setup_wizard_enabled(False) - context.send_notification(CHECK_SETTINGS, 'process') + context.wakeup( + CHECK_SETTINGS, + timeout=5, + payload={'state': 'process'}, + ) @staticmethod def get_wizard_steps(): diff --git a/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py b/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py index b29e3e105..cb540d190 100644 --- a/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py +++ b/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py @@ -756,8 +756,10 @@ def tear_down(self): except AttributeError: pass - def wakeup(self, target, timeout=None): + def wakeup(self, target, timeout=None, payload=None): data = {'target': target, 'response_required': bool(timeout)} + if payload: + data.update(payload) self.send_notification(WAKEUP, data) if not timeout: return diff --git a/resources/lib/youtube_plugin/kodion/monitors/service_monitor.py b/resources/lib/youtube_plugin/kodion/monitors/service_monitor.py index 5c920ed42..ecc2b6a84 100644 --- a/resources/lib/youtube_plugin/kodion/monitors/service_monitor.py +++ b/resources/lib/youtube_plugin/kodion/monitors/service_monitor.py @@ -88,16 +88,7 @@ def onNotification(self, sender, method, data): if sender != ADDON_ID: return group, separator, event = method.partition('.') - if event == CHECK_SETTINGS: - if data: - data = json.loads(data) - if data == 'defer': - self._settings_state = data - elif data == 'process': - self._settings_state = data - self.onSettingsChanged() - self._settings_state = None - elif event == WAKEUP: + if event == WAKEUP: if not isinstance(data, dict): data = json.loads(data) if not data: @@ -110,6 +101,14 @@ def onNotification(self, sender, method, data): self.start_httpd() if self.httpd_sleep_allowed: self.httpd_sleep_allowed = None + elif target == CHECK_SETTINGS: + state = data.get('state') + if state == 'defer': + self._settings_state = state + elif state == 'process': + self._settings_state = state + self.onSettingsChanged() + self._settings_state = None if data.get('response_required'): self.set_property(WAKEUP, target) elif event == REFRESH_CONTAINER: From 0047cff161eda2feb3c03daae39ebd9436a99b34 Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:16:33 +1000 Subject: [PATCH 07/10] Ensure that plugin settings instance is refreshed after entire Setup Wizard is completed --- resources/lib/youtube_plugin/kodion/abstract_provider.py | 1 + resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lib/youtube_plugin/kodion/abstract_provider.py b/resources/lib/youtube_plugin/kodion/abstract_provider.py index c79f2c392..f97e6d9ef 100644 --- a/resources/lib/youtube_plugin/kodion/abstract_provider.py +++ b/resources/lib/youtube_plugin/kodion/abstract_provider.py @@ -146,6 +146,7 @@ def run_wizard(self, context): else: step += 1 finally: + settings = context.get_settings(refresh=True) settings.setup_wizard_enabled(False) context.wakeup( CHECK_SETTINGS, diff --git a/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py b/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py index 363dbc440..2bbbe4cb2 100644 --- a/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py +++ b/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py @@ -552,5 +552,4 @@ def process_refresh_settings(context, step, steps, **_kwargs): query='target=settings_xml'), wait_for=WAIT_END_FLAG, ) - context.get_settings(refresh=True) return step From eb0f81c84d4a06d2d283fd1d79b62f9cb662c1f8 Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Mon, 16 Sep 2024 05:32:09 +1000 Subject: [PATCH 08/10] Misc tidy ups --- .../kodion/abstract_provider.py | 17 ++----- .../youtube/helper/yt_setup_wizard.py | 47 +++++++++++-------- .../youtube/helper/yt_specials.py | 6 +-- 3 files changed, 35 insertions(+), 35 deletions(-) diff --git a/resources/lib/youtube_plugin/kodion/abstract_provider.py b/resources/lib/youtube_plugin/kodion/abstract_provider.py index f97e6d9ef..0ed725e62 100644 --- a/resources/lib/youtube_plugin/kodion/abstract_provider.py +++ b/resources/lib/youtube_plugin/kodion/abstract_provider.py @@ -117,9 +117,6 @@ def wrapper(method): return wrapper def run_wizard(self, context): - settings = context.get_settings() - ui = context.get_ui() - context.wakeup( CHECK_SETTINGS, timeout=5, @@ -132,7 +129,7 @@ def run_wizard(self, context): steps = len(wizard_steps) try: - if wizard_steps and ui.on_yes_no_input( + if wizard_steps and context.get_ui().on_yes_no_input( context.localize('setup_wizard'), (context.localize('setup_wizard.prompt') % context.localize('setup_wizard.prompt.settings')) @@ -258,16 +255,12 @@ def reroute(self, context, path=None, params=None, uri=None): if not path: return False - do_refresh = 'refresh' in params - - if path == current_path and params == current_params: - if not do_refresh: - return False - params['refresh'] += 1 - - if do_refresh: + if 'refresh' in params: container = context.get_infolabel('System.CurrentControlId') position = context.get_infolabel('Container.CurrentItem') + params['refresh'] += 1 + elif path == current_path and params == current_params: + return False else: container = None position = None diff --git a/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py b/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py index 2bbbe4cb2..f7405445a 100644 --- a/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py +++ b/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py @@ -442,9 +442,12 @@ def process_subtitles(context, step, steps, **_kwargs): (localize('setup_wizard.prompt') % localize('setup_wizard.prompt.subtitles')) ): - context.execute('RunScript({addon_id},config/subtitles)'.format( - addon_id=ADDON_ID - ), wait_for=WAIT_END_FLAG) + context.execute( + 'RunScript({addon_id},config/subtitles)'.format( + addon_id=ADDON_ID, + ), + wait_for=WAIT_END_FLAG, + ) context.get_settings(refresh=True) return step @@ -480,11 +483,14 @@ def _convert_old_search_item(value, item): ui.show_notification(localize('succeeded')) context.execute( - 'RunScript({addon},maintenance/{action}?{query})' - .format(addon=ADDON_ID, - action='delete', - query=urlencode({'target': 'other_file', - 'path': search_db_path})), + 'RunScript({addon},maintenance/{action}?{query})'.format( + addon=ADDON_ID, + action='delete', + query=urlencode({ + 'target': 'other_file', + 'path': search_db_path, + }), + ), wait_for=WAIT_END_FLAG, ) return step @@ -526,11 +532,14 @@ def _convert_old_history_item(value, item): ui.show_notification(localize('succeeded')) context.execute( - 'RunScript({addon},maintenance/{action}?{query})' - .format(addon=ADDON_ID, - action='delete', - query=urlencode({'target': 'other_file', - 'path': history_db_path})), + 'RunScript({addon},maintenance/{action}?{query})'.format( + addon=ADDON_ID, + action='delete', + query=urlencode({ + 'target': 'other_file', + 'path': history_db_path, + }), + ), wait_for=WAIT_END_FLAG, ) return step @@ -542,14 +551,14 @@ def process_refresh_settings(context, step, steps, **_kwargs): step += 1 if context.get_ui().on_yes_no_input( localize('setup_wizard') + ' ({0}/{1})'.format(step, steps), - (localize('setup_wizard.prompt') - % localize('setup_wizard.prompt.settings.refresh')) + localize('setup_wizard.prompt.settings.refresh'), ): context.execute( - 'RunScript({addon},maintenance/{action}?{query})' - .format(addon=ADDON_ID, - action='refresh', - query='target=settings_xml'), + 'RunScript({addon},maintenance/{action}?{query})'.format( + addon=ADDON_ID, + action='refresh', + query='target=settings_xml', + ), wait_for=WAIT_END_FLAG, ) return step diff --git a/resources/lib/youtube_plugin/youtube/helper/yt_specials.py b/resources/lib/youtube_plugin/youtube/helper/yt_specials.py index df9518094..52dda63e8 100644 --- a/resources/lib/youtube_plugin/youtube/helper/yt_specials.py +++ b/resources/lib/youtube_plugin/youtube/helper/yt_specials.py @@ -23,7 +23,7 @@ def _process_related_videos(provider, context, client): function_cache = context.get_function_cache() params = context.get_params() - video_id = params.get('video_id', '') + video_id = params.get('video_id') refresh = params.get('refresh') if video_id: json_data = function_cache.run( @@ -298,13 +298,11 @@ def _process_my_subscriptions(provider, context, client, filtered=False): context.set_content(CONTENT.VIDEO_CONTENT) params = context.get_params() - refresh = params.get('refresh') - json_data = client.get_my_subscriptions( page_token=params.get('page', 1), logged_in=provider.is_logged_in(), do_filter=filtered, - refresh=refresh, + refresh=params.get('refresh'), ) if not json_data: From 13624bd4c2878c429ca0b41ffb15aa132120b935 Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Thu, 19 Sep 2024 07:25:39 +1000 Subject: [PATCH 09/10] Move language and region selection to script and add to settings dialog --- .../youtube_plugin/kodion/script_actions.py | 256 +++++++++++++++++ .../youtube/helper/yt_setup_wizard.py | 263 +----------------- resources/settings.xml | 12 +- 3 files changed, 275 insertions(+), 256 deletions(-) diff --git a/resources/lib/youtube_plugin/kodion/script_actions.py b/resources/lib/youtube_plugin/kodion/script_actions.py index 37cb391dc..cd4bffd34 100644 --- a/resources/lib/youtube_plugin/kodion/script_actions.py +++ b/resources/lib/youtube_plugin/kodion/script_actions.py @@ -22,6 +22,179 @@ from .context import XbmcContext from .network import Locator, get_client_ip_address, httpd_status from .utils import current_system_version, rm_dir, validate_ip_address +from ..youtube import Provider + + +DEFAULT_LANGUAGES = {'items': [ + {'snippet': {'name': 'Afrikaans', 'hl': 'af'}, 'id': 'af'}, + {'snippet': {'name': 'Azerbaijani', 'hl': 'az'}, 'id': 'az'}, + {'snippet': {'name': 'Indonesian', 'hl': 'id'}, 'id': 'id'}, + {'snippet': {'name': 'Malay', 'hl': 'ms'}, 'id': 'ms'}, + {'snippet': {'name': 'Catalan', 'hl': 'ca'}, 'id': 'ca'}, + {'snippet': {'name': 'Czech', 'hl': 'cs'}, 'id': 'cs'}, + {'snippet': {'name': 'Danish', 'hl': 'da'}, 'id': 'da'}, + {'snippet': {'name': 'German', 'hl': 'de'}, 'id': 'de'}, + {'snippet': {'name': 'Estonian', 'hl': 'et'}, 'id': 'et'}, + {'snippet': {'name': 'English (United Kingdom)', 'hl': 'en-GB'}, 'id': 'en-GB'}, + {'snippet': {'name': 'English', 'hl': 'en'}, 'id': 'en'}, + {'snippet': {'name': 'Spanish (Spain)', 'hl': 'es'}, 'id': 'es'}, + {'snippet': {'name': 'Spanish (Latin America)', 'hl': 'es-419'}, 'id': 'es-419'}, + {'snippet': {'name': 'Basque', 'hl': 'eu'}, 'id': 'eu'}, + {'snippet': {'name': 'Filipino', 'hl': 'fil'}, 'id': 'fil'}, + {'snippet': {'name': 'French', 'hl': 'fr'}, 'id': 'fr'}, + {'snippet': {'name': 'French (Canada)', 'hl': 'fr-CA'}, 'id': 'fr-CA'}, + {'snippet': {'name': 'Galician', 'hl': 'gl'}, 'id': 'gl'}, + {'snippet': {'name': 'Croatian', 'hl': 'hr'}, 'id': 'hr'}, + {'snippet': {'name': 'Zulu', 'hl': 'zu'}, 'id': 'zu'}, + {'snippet': {'name': 'Icelandic', 'hl': 'is'}, 'id': 'is'}, + {'snippet': {'name': 'Italian', 'hl': 'it'}, 'id': 'it'}, + {'snippet': {'name': 'Swahili', 'hl': 'sw'}, 'id': 'sw'}, + {'snippet': {'name': 'Latvian', 'hl': 'lv'}, 'id': 'lv'}, + {'snippet': {'name': 'Lithuanian', 'hl': 'lt'}, 'id': 'lt'}, + {'snippet': {'name': 'Hungarian', 'hl': 'hu'}, 'id': 'hu'}, + {'snippet': {'name': 'Dutch', 'hl': 'nl'}, 'id': 'nl'}, + {'snippet': {'name': 'Norwegian', 'hl': 'no'}, 'id': 'no'}, + {'snippet': {'name': 'Uzbek', 'hl': 'uz'}, 'id': 'uz'}, + {'snippet': {'name': 'Polish', 'hl': 'pl'}, 'id': 'pl'}, + {'snippet': {'name': 'Portuguese (Portugal)', 'hl': 'pt-PT'}, 'id': 'pt-PT'}, + {'snippet': {'name': 'Portuguese (Brazil)', 'hl': 'pt'}, 'id': 'pt'}, + {'snippet': {'name': 'Romanian', 'hl': 'ro'}, 'id': 'ro'}, + {'snippet': {'name': 'Albanian', 'hl': 'sq'}, 'id': 'sq'}, + {'snippet': {'name': 'Slovak', 'hl': 'sk'}, 'id': 'sk'}, + {'snippet': {'name': 'Slovenian', 'hl': 'sl'}, 'id': 'sl'}, + {'snippet': {'name': 'Finnish', 'hl': 'fi'}, 'id': 'fi'}, + {'snippet': {'name': 'Swedish', 'hl': 'sv'}, 'id': 'sv'}, + {'snippet': {'name': 'Vietnamese', 'hl': 'vi'}, 'id': 'vi'}, + {'snippet': {'name': 'Turkish', 'hl': 'tr'}, 'id': 'tr'}, + {'snippet': {'name': 'Bulgarian', 'hl': 'bg'}, 'id': 'bg'}, + {'snippet': {'name': 'Kyrgyz', 'hl': 'ky'}, 'id': 'ky'}, + {'snippet': {'name': 'Kazakh', 'hl': 'kk'}, 'id': 'kk'}, + {'snippet': {'name': 'Macedonian', 'hl': 'mk'}, 'id': 'mk'}, + {'snippet': {'name': 'Mongolian', 'hl': 'mn'}, 'id': 'mn'}, + {'snippet': {'name': 'Russian', 'hl': 'ru'}, 'id': 'ru'}, + {'snippet': {'name': 'Serbian', 'hl': 'sr'}, 'id': 'sr'}, + {'snippet': {'name': 'Ukrainian', 'hl': 'uk'}, 'id': 'uk'}, + {'snippet': {'name': 'Greek', 'hl': 'el'}, 'id': 'el'}, + {'snippet': {'name': 'Armenian', 'hl': 'hy'}, 'id': 'hy'}, + {'snippet': {'name': 'Hebrew', 'hl': 'iw'}, 'id': 'iw'}, + {'snippet': {'name': 'Urdu', 'hl': 'ur'}, 'id': 'ur'}, + {'snippet': {'name': 'Arabic', 'hl': 'ar'}, 'id': 'ar'}, + {'snippet': {'name': 'Persian', 'hl': 'fa'}, 'id': 'fa'}, + {'snippet': {'name': 'Nepali', 'hl': 'ne'}, 'id': 'ne'}, + {'snippet': {'name': 'Marathi', 'hl': 'mr'}, 'id': 'mr'}, + {'snippet': {'name': 'Hindi', 'hl': 'hi'}, 'id': 'hi'}, + {'snippet': {'name': 'Bengali', 'hl': 'bn'}, 'id': 'bn'}, + {'snippet': {'name': 'Punjabi', 'hl': 'pa'}, 'id': 'pa'}, + {'snippet': {'name': 'Gujarati', 'hl': 'gu'}, 'id': 'gu'}, + {'snippet': {'name': 'Tamil', 'hl': 'ta'}, 'id': 'ta'}, + {'snippet': {'name': 'Telugu', 'hl': 'te'}, 'id': 'te'}, + {'snippet': {'name': 'Kannada', 'hl': 'kn'}, 'id': 'kn'}, + {'snippet': {'name': 'Malayalam', 'hl': 'ml'}, 'id': 'ml'}, + {'snippet': {'name': 'Sinhala', 'hl': 'si'}, 'id': 'si'}, + {'snippet': {'name': 'Thai', 'hl': 'th'}, 'id': 'th'}, + {'snippet': {'name': 'Lao', 'hl': 'lo'}, 'id': 'lo'}, + {'snippet': {'name': 'Myanmar (Burmese)', 'hl': 'my'}, 'id': 'my'}, + {'snippet': {'name': 'Georgian', 'hl': 'ka'}, 'id': 'ka'}, + {'snippet': {'name': 'Amharic', 'hl': 'am'}, 'id': 'am'}, + {'snippet': {'name': 'Khmer', 'hl': 'km'}, 'id': 'km'}, + {'snippet': {'name': 'Chinese', 'hl': 'zh-CN'}, 'id': 'zh-CN'}, + {'snippet': {'name': 'Chinese (Taiwan)', 'hl': 'zh-TW'}, 'id': 'zh-TW'}, + {'snippet': {'name': 'Chinese (Hong Kong)', 'hl': 'zh-HK'}, 'id': 'zh-HK'}, + {'snippet': {'name': 'Japanese', 'hl': 'ja'}, 'id': 'ja'}, + {'snippet': {'name': 'Korean', 'hl': 'ko'}, 'id': 'ko'}, +]} +DEFAULT_REGIONS = {'items': [ + {'snippet': {'gl': 'DZ', 'name': 'Algeria'}, 'id': 'DZ'}, + {'snippet': {'gl': 'AR', 'name': 'Argentina'}, 'id': 'AR'}, + {'snippet': {'gl': 'AU', 'name': 'Australia'}, 'id': 'AU'}, + {'snippet': {'gl': 'AT', 'name': 'Austria'}, 'id': 'AT'}, + {'snippet': {'gl': 'AZ', 'name': 'Azerbaijan'}, 'id': 'AZ'}, + {'snippet': {'gl': 'BH', 'name': 'Bahrain'}, 'id': 'BH'}, + {'snippet': {'gl': 'BY', 'name': 'Belarus'}, 'id': 'BY'}, + {'snippet': {'gl': 'BE', 'name': 'Belgium'}, 'id': 'BE'}, + {'snippet': {'gl': 'BA', 'name': 'Bosnia and Herzegovina'}, 'id': 'BA'}, + {'snippet': {'gl': 'BR', 'name': 'Brazil'}, 'id': 'BR'}, + {'snippet': {'gl': 'BG', 'name': 'Bulgaria'}, 'id': 'BG'}, + {'snippet': {'gl': 'CA', 'name': 'Canada'}, 'id': 'CA'}, + {'snippet': {'gl': 'CL', 'name': 'Chile'}, 'id': 'CL'}, + {'snippet': {'gl': 'CO', 'name': 'Colombia'}, 'id': 'CO'}, + {'snippet': {'gl': 'HR', 'name': 'Croatia'}, 'id': 'HR'}, + {'snippet': {'gl': 'CZ', 'name': 'Czech Republic'}, 'id': 'CZ'}, + {'snippet': {'gl': 'DK', 'name': 'Denmark'}, 'id': 'DK'}, + {'snippet': {'gl': 'EG', 'name': 'Egypt'}, 'id': 'EG'}, + {'snippet': {'gl': 'EE', 'name': 'Estonia'}, 'id': 'EE'}, + {'snippet': {'gl': 'FI', 'name': 'Finland'}, 'id': 'FI'}, + {'snippet': {'gl': 'FR', 'name': 'France'}, 'id': 'FR'}, + {'snippet': {'gl': 'GE', 'name': 'Georgia'}, 'id': 'GE'}, + {'snippet': {'gl': 'DE', 'name': 'Germany'}, 'id': 'DE'}, + {'snippet': {'gl': 'GH', 'name': 'Ghana'}, 'id': 'GH'}, + {'snippet': {'gl': 'GR', 'name': 'Greece'}, 'id': 'GR'}, + {'snippet': {'gl': 'HK', 'name': 'Hong Kong'}, 'id': 'HK'}, + {'snippet': {'gl': 'HU', 'name': 'Hungary'}, 'id': 'HU'}, + {'snippet': {'gl': 'IS', 'name': 'Iceland'}, 'id': 'IS'}, + {'snippet': {'gl': 'IN', 'name': 'India'}, 'id': 'IN'}, + {'snippet': {'gl': 'ID', 'name': 'Indonesia'}, 'id': 'ID'}, + {'snippet': {'gl': 'IQ', 'name': 'Iraq'}, 'id': 'IQ'}, + {'snippet': {'gl': 'IE', 'name': 'Ireland'}, 'id': 'IE'}, + {'snippet': {'gl': 'IL', 'name': 'Israel'}, 'id': 'IL'}, + {'snippet': {'gl': 'IT', 'name': 'Italy'}, 'id': 'IT'}, + {'snippet': {'gl': 'JM', 'name': 'Jamaica'}, 'id': 'JM'}, + {'snippet': {'gl': 'JP', 'name': 'Japan'}, 'id': 'JP'}, + {'snippet': {'gl': 'JO', 'name': 'Jordan'}, 'id': 'JO'}, + {'snippet': {'gl': 'KZ', 'name': 'Kazakhstan'}, 'id': 'KZ'}, + {'snippet': {'gl': 'KE', 'name': 'Kenya'}, 'id': 'KE'}, + {'snippet': {'gl': 'KW', 'name': 'Kuwait'}, 'id': 'KW'}, + {'snippet': {'gl': 'LV', 'name': 'Latvia'}, 'id': 'LV'}, + {'snippet': {'gl': 'LB', 'name': 'Lebanon'}, 'id': 'LB'}, + {'snippet': {'gl': 'LY', 'name': 'Libya'}, 'id': 'LY'}, + {'snippet': {'gl': 'LT', 'name': 'Lithuania'}, 'id': 'LT'}, + {'snippet': {'gl': 'LU', 'name': 'Luxembourg'}, 'id': 'LU'}, + {'snippet': {'gl': 'MK', 'name': 'Macedonia'}, 'id': 'MK'}, + {'snippet': {'gl': 'MY', 'name': 'Malaysia'}, 'id': 'MY'}, + {'snippet': {'gl': 'MX', 'name': 'Mexico'}, 'id': 'MX'}, + {'snippet': {'gl': 'ME', 'name': 'Montenegro'}, 'id': 'ME'}, + {'snippet': {'gl': 'MA', 'name': 'Morocco'}, 'id': 'MA'}, + {'snippet': {'gl': 'NP', 'name': 'Nepal'}, 'id': 'NP'}, + {'snippet': {'gl': 'NL', 'name': 'Netherlands'}, 'id': 'NL'}, + {'snippet': {'gl': 'NZ', 'name': 'New Zealand'}, 'id': 'NZ'}, + {'snippet': {'gl': 'NG', 'name': 'Nigeria'}, 'id': 'NG'}, + {'snippet': {'gl': 'NO', 'name': 'Norway'}, 'id': 'NO'}, + {'snippet': {'gl': 'OM', 'name': 'Oman'}, 'id': 'OM'}, + {'snippet': {'gl': 'PK', 'name': 'Pakistan'}, 'id': 'PK'}, + {'snippet': {'gl': 'PE', 'name': 'Peru'}, 'id': 'PE'}, + {'snippet': {'gl': 'PH', 'name': 'Philippines'}, 'id': 'PH'}, + {'snippet': {'gl': 'PL', 'name': 'Poland'}, 'id': 'PL'}, + {'snippet': {'gl': 'PT', 'name': 'Portugal'}, 'id': 'PT'}, + {'snippet': {'gl': 'PR', 'name': 'Puerto Rico'}, 'id': 'PR'}, + {'snippet': {'gl': 'QA', 'name': 'Qatar'}, 'id': 'QA'}, + {'snippet': {'gl': 'RO', 'name': 'Romania'}, 'id': 'RO'}, + {'snippet': {'gl': 'RU', 'name': 'Russia'}, 'id': 'RU'}, + {'snippet': {'gl': 'SA', 'name': 'Saudi Arabia'}, 'id': 'SA'}, + {'snippet': {'gl': 'SN', 'name': 'Senegal'}, 'id': 'SN'}, + {'snippet': {'gl': 'RS', 'name': 'Serbia'}, 'id': 'RS'}, + {'snippet': {'gl': 'SG', 'name': 'Singapore'}, 'id': 'SG'}, + {'snippet': {'gl': 'SK', 'name': 'Slovakia'}, 'id': 'SK'}, + {'snippet': {'gl': 'SI', 'name': 'Slovenia'}, 'id': 'SI'}, + {'snippet': {'gl': 'ZA', 'name': 'South Africa'}, 'id': 'ZA'}, + {'snippet': {'gl': 'KR', 'name': 'South Korea'}, 'id': 'KR'}, + {'snippet': {'gl': 'ES', 'name': 'Spain'}, 'id': 'ES'}, + {'snippet': {'gl': 'LK', 'name': 'Sri Lanka'}, 'id': 'LK'}, + {'snippet': {'gl': 'SE', 'name': 'Sweden'}, 'id': 'SE'}, + {'snippet': {'gl': 'CH', 'name': 'Switzerland'}, 'id': 'CH'}, + {'snippet': {'gl': 'TW', 'name': 'Taiwan'}, 'id': 'TW'}, + {'snippet': {'gl': 'TZ', 'name': 'Tanzania'}, 'id': 'TZ'}, + {'snippet': {'gl': 'TH', 'name': 'Thailand'}, 'id': 'TH'}, + {'snippet': {'gl': 'TN', 'name': 'Tunisia'}, 'id': 'TN'}, + {'snippet': {'gl': 'TR', 'name': 'Turkey'}, 'id': 'TR'}, + {'snippet': {'gl': 'UG', 'name': 'Uganda'}, 'id': 'UG'}, + {'snippet': {'gl': 'UA', 'name': 'Ukraine'}, 'id': 'UA'}, + {'snippet': {'gl': 'AE', 'name': 'United Arab Emirates'}, 'id': 'AE'}, + {'snippet': {'gl': 'GB', 'name': 'United Kingdom'}, 'id': 'GB'}, + {'snippet': {'gl': 'US', 'name': 'United States'}, 'id': 'US'}, + {'snippet': {'gl': 'VN', 'name': 'Vietnam'}, 'id': 'VN'}, + {'snippet': {'gl': 'YE', 'name': 'Yemen'}, 'id': 'YE'}, + {'snippet': {'gl': 'ZW', 'name': 'Zimbabwe'}, 'id': 'ZW'}, +]} def _config_actions(context, action, *_args): @@ -135,6 +308,89 @@ def _config_actions(context, action, *_args): '{0[lat]},{0[lon]}'.format(coords) ) + elif action == 'language_region': + client = Provider().get_client(context) + settings = context.get_settings() + + plugin_language = settings.get_language() + plugin_region = settings.get_region() + + kodi_language = context.get_language() + base_kodi_language = kodi_language.partition('-')[0] + + json_data = client.get_supported_languages(kodi_language) + items = json_data.get('items') or DEFAULT_LANGUAGES['items'] + + selected_language = [None] + + def _get_selected_language(item): + item_lang = item[1] + base_item_lang = item_lang.partition('-')[0] + if item_lang == kodi_language or item_lang == plugin_language: + selected_language[0] = item + elif (not selected_language[0] + and base_item_lang == base_kodi_language): + selected_language.append(item) + return item + + # Ignore es-419 as it causes hl not a valid language error + # https://github.com/jdf76/plugin.video.youtube/issues/418 + invalid_ids = ('es-419',) + language_list = sorted([ + (item['snippet']['name'], item['snippet']['hl']) + for item in items + if item['id'] not in invalid_ids + ], key=_get_selected_language) + + if selected_language[0]: + selected_language = language_list.index(selected_language[0]) + elif len(selected_language) > 1: + selected_language = language_list.index(selected_language[1]) + else: + selected_language = None + + language_id = ui.on_select( + localize('setup_wizard.locale.language'), + language_list, + preselect=selected_language + ) + if language_id == -1: + return + + json_data = client.get_supported_regions(language=language_id) + items = json_data.get('items') or DEFAULT_REGIONS['items'] + + selected_region = [None] + + def _get_selected_region(item): + item_region = item[1] + if item_region == plugin_region: + selected_region[0] = item + return item + + region_list = sorted([ + (item['snippet']['name'], item['snippet']['gl']) + for item in items + ], key=_get_selected_region) + + if selected_region[0]: + selected_region = region_list.index(selected_region[0]) + else: + selected_region = None + + region_id = ui.on_select( + localize('setup_wizard.locale.region'), + region_list, + preselect=selected_region + ) + if region_id == -1: + return + + # set new language id and region id + settings = context.get_settings() + settings.set_language(language_id) + settings.set_region(region_id) + def _maintenance_actions(context, action, params): target = params.get('target') diff --git a/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py b/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py index f7405445a..c3a51f6fc 100644 --- a/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py +++ b/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py @@ -20,270 +20,23 @@ from ...kodion.utils.datetime_parser import strptime -DEFAULT_LANGUAGES = {'items': [ - {'snippet': {'name': 'Afrikaans', 'hl': 'af'}, 'id': 'af'}, - {'snippet': {'name': 'Azerbaijani', 'hl': 'az'}, 'id': 'az'}, - {'snippet': {'name': 'Indonesian', 'hl': 'id'}, 'id': 'id'}, - {'snippet': {'name': 'Malay', 'hl': 'ms'}, 'id': 'ms'}, - {'snippet': {'name': 'Catalan', 'hl': 'ca'}, 'id': 'ca'}, - {'snippet': {'name': 'Czech', 'hl': 'cs'}, 'id': 'cs'}, - {'snippet': {'name': 'Danish', 'hl': 'da'}, 'id': 'da'}, - {'snippet': {'name': 'German', 'hl': 'de'}, 'id': 'de'}, - {'snippet': {'name': 'Estonian', 'hl': 'et'}, 'id': 'et'}, - {'snippet': {'name': 'English (United Kingdom)', 'hl': 'en-GB'}, 'id': 'en-GB'}, - {'snippet': {'name': 'English', 'hl': 'en'}, 'id': 'en'}, - {'snippet': {'name': 'Spanish (Spain)', 'hl': 'es'}, 'id': 'es'}, - {'snippet': {'name': 'Spanish (Latin America)', 'hl': 'es-419'}, 'id': 'es-419'}, - {'snippet': {'name': 'Basque', 'hl': 'eu'}, 'id': 'eu'}, - {'snippet': {'name': 'Filipino', 'hl': 'fil'}, 'id': 'fil'}, - {'snippet': {'name': 'French', 'hl': 'fr'}, 'id': 'fr'}, - {'snippet': {'name': 'French (Canada)', 'hl': 'fr-CA'}, 'id': 'fr-CA'}, - {'snippet': {'name': 'Galician', 'hl': 'gl'}, 'id': 'gl'}, - {'snippet': {'name': 'Croatian', 'hl': 'hr'}, 'id': 'hr'}, - {'snippet': {'name': 'Zulu', 'hl': 'zu'}, 'id': 'zu'}, - {'snippet': {'name': 'Icelandic', 'hl': 'is'}, 'id': 'is'}, - {'snippet': {'name': 'Italian', 'hl': 'it'}, 'id': 'it'}, - {'snippet': {'name': 'Swahili', 'hl': 'sw'}, 'id': 'sw'}, - {'snippet': {'name': 'Latvian', 'hl': 'lv'}, 'id': 'lv'}, - {'snippet': {'name': 'Lithuanian', 'hl': 'lt'}, 'id': 'lt'}, - {'snippet': {'name': 'Hungarian', 'hl': 'hu'}, 'id': 'hu'}, - {'snippet': {'name': 'Dutch', 'hl': 'nl'}, 'id': 'nl'}, - {'snippet': {'name': 'Norwegian', 'hl': 'no'}, 'id': 'no'}, - {'snippet': {'name': 'Uzbek', 'hl': 'uz'}, 'id': 'uz'}, - {'snippet': {'name': 'Polish', 'hl': 'pl'}, 'id': 'pl'}, - {'snippet': {'name': 'Portuguese (Portugal)', 'hl': 'pt-PT'}, 'id': 'pt-PT'}, - {'snippet': {'name': 'Portuguese (Brazil)', 'hl': 'pt'}, 'id': 'pt'}, - {'snippet': {'name': 'Romanian', 'hl': 'ro'}, 'id': 'ro'}, - {'snippet': {'name': 'Albanian', 'hl': 'sq'}, 'id': 'sq'}, - {'snippet': {'name': 'Slovak', 'hl': 'sk'}, 'id': 'sk'}, - {'snippet': {'name': 'Slovenian', 'hl': 'sl'}, 'id': 'sl'}, - {'snippet': {'name': 'Finnish', 'hl': 'fi'}, 'id': 'fi'}, - {'snippet': {'name': 'Swedish', 'hl': 'sv'}, 'id': 'sv'}, - {'snippet': {'name': 'Vietnamese', 'hl': 'vi'}, 'id': 'vi'}, - {'snippet': {'name': 'Turkish', 'hl': 'tr'}, 'id': 'tr'}, - {'snippet': {'name': 'Bulgarian', 'hl': 'bg'}, 'id': 'bg'}, - {'snippet': {'name': 'Kyrgyz', 'hl': 'ky'}, 'id': 'ky'}, - {'snippet': {'name': 'Kazakh', 'hl': 'kk'}, 'id': 'kk'}, - {'snippet': {'name': 'Macedonian', 'hl': 'mk'}, 'id': 'mk'}, - {'snippet': {'name': 'Mongolian', 'hl': 'mn'}, 'id': 'mn'}, - {'snippet': {'name': 'Russian', 'hl': 'ru'}, 'id': 'ru'}, - {'snippet': {'name': 'Serbian', 'hl': 'sr'}, 'id': 'sr'}, - {'snippet': {'name': 'Ukrainian', 'hl': 'uk'}, 'id': 'uk'}, - {'snippet': {'name': 'Greek', 'hl': 'el'}, 'id': 'el'}, - {'snippet': {'name': 'Armenian', 'hl': 'hy'}, 'id': 'hy'}, - {'snippet': {'name': 'Hebrew', 'hl': 'iw'}, 'id': 'iw'}, - {'snippet': {'name': 'Urdu', 'hl': 'ur'}, 'id': 'ur'}, - {'snippet': {'name': 'Arabic', 'hl': 'ar'}, 'id': 'ar'}, - {'snippet': {'name': 'Persian', 'hl': 'fa'}, 'id': 'fa'}, - {'snippet': {'name': 'Nepali', 'hl': 'ne'}, 'id': 'ne'}, - {'snippet': {'name': 'Marathi', 'hl': 'mr'}, 'id': 'mr'}, - {'snippet': {'name': 'Hindi', 'hl': 'hi'}, 'id': 'hi'}, - {'snippet': {'name': 'Bengali', 'hl': 'bn'}, 'id': 'bn'}, - {'snippet': {'name': 'Punjabi', 'hl': 'pa'}, 'id': 'pa'}, - {'snippet': {'name': 'Gujarati', 'hl': 'gu'}, 'id': 'gu'}, - {'snippet': {'name': 'Tamil', 'hl': 'ta'}, 'id': 'ta'}, - {'snippet': {'name': 'Telugu', 'hl': 'te'}, 'id': 'te'}, - {'snippet': {'name': 'Kannada', 'hl': 'kn'}, 'id': 'kn'}, - {'snippet': {'name': 'Malayalam', 'hl': 'ml'}, 'id': 'ml'}, - {'snippet': {'name': 'Sinhala', 'hl': 'si'}, 'id': 'si'}, - {'snippet': {'name': 'Thai', 'hl': 'th'}, 'id': 'th'}, - {'snippet': {'name': 'Lao', 'hl': 'lo'}, 'id': 'lo'}, - {'snippet': {'name': 'Myanmar (Burmese)', 'hl': 'my'}, 'id': 'my'}, - {'snippet': {'name': 'Georgian', 'hl': 'ka'}, 'id': 'ka'}, - {'snippet': {'name': 'Amharic', 'hl': 'am'}, 'id': 'am'}, - {'snippet': {'name': 'Khmer', 'hl': 'km'}, 'id': 'km'}, - {'snippet': {'name': 'Chinese', 'hl': 'zh-CN'}, 'id': 'zh-CN'}, - {'snippet': {'name': 'Chinese (Taiwan)', 'hl': 'zh-TW'}, 'id': 'zh-TW'}, - {'snippet': {'name': 'Chinese (Hong Kong)', 'hl': 'zh-HK'}, 'id': 'zh-HK'}, - {'snippet': {'name': 'Japanese', 'hl': 'ja'}, 'id': 'ja'}, - {'snippet': {'name': 'Korean', 'hl': 'ko'}, 'id': 'ko'}, -]} -DEFAULT_REGIONS = {'items': [ - {'snippet': {'gl': 'DZ', 'name': 'Algeria'}, 'id': 'DZ'}, - {'snippet': {'gl': 'AR', 'name': 'Argentina'}, 'id': 'AR'}, - {'snippet': {'gl': 'AU', 'name': 'Australia'}, 'id': 'AU'}, - {'snippet': {'gl': 'AT', 'name': 'Austria'}, 'id': 'AT'}, - {'snippet': {'gl': 'AZ', 'name': 'Azerbaijan'}, 'id': 'AZ'}, - {'snippet': {'gl': 'BH', 'name': 'Bahrain'}, 'id': 'BH'}, - {'snippet': {'gl': 'BY', 'name': 'Belarus'}, 'id': 'BY'}, - {'snippet': {'gl': 'BE', 'name': 'Belgium'}, 'id': 'BE'}, - {'snippet': {'gl': 'BA', 'name': 'Bosnia and Herzegovina'}, 'id': 'BA'}, - {'snippet': {'gl': 'BR', 'name': 'Brazil'}, 'id': 'BR'}, - {'snippet': {'gl': 'BG', 'name': 'Bulgaria'}, 'id': 'BG'}, - {'snippet': {'gl': 'CA', 'name': 'Canada'}, 'id': 'CA'}, - {'snippet': {'gl': 'CL', 'name': 'Chile'}, 'id': 'CL'}, - {'snippet': {'gl': 'CO', 'name': 'Colombia'}, 'id': 'CO'}, - {'snippet': {'gl': 'HR', 'name': 'Croatia'}, 'id': 'HR'}, - {'snippet': {'gl': 'CZ', 'name': 'Czech Republic'}, 'id': 'CZ'}, - {'snippet': {'gl': 'DK', 'name': 'Denmark'}, 'id': 'DK'}, - {'snippet': {'gl': 'EG', 'name': 'Egypt'}, 'id': 'EG'}, - {'snippet': {'gl': 'EE', 'name': 'Estonia'}, 'id': 'EE'}, - {'snippet': {'gl': 'FI', 'name': 'Finland'}, 'id': 'FI'}, - {'snippet': {'gl': 'FR', 'name': 'France'}, 'id': 'FR'}, - {'snippet': {'gl': 'GE', 'name': 'Georgia'}, 'id': 'GE'}, - {'snippet': {'gl': 'DE', 'name': 'Germany'}, 'id': 'DE'}, - {'snippet': {'gl': 'GH', 'name': 'Ghana'}, 'id': 'GH'}, - {'snippet': {'gl': 'GR', 'name': 'Greece'}, 'id': 'GR'}, - {'snippet': {'gl': 'HK', 'name': 'Hong Kong'}, 'id': 'HK'}, - {'snippet': {'gl': 'HU', 'name': 'Hungary'}, 'id': 'HU'}, - {'snippet': {'gl': 'IS', 'name': 'Iceland'}, 'id': 'IS'}, - {'snippet': {'gl': 'IN', 'name': 'India'}, 'id': 'IN'}, - {'snippet': {'gl': 'ID', 'name': 'Indonesia'}, 'id': 'ID'}, - {'snippet': {'gl': 'IQ', 'name': 'Iraq'}, 'id': 'IQ'}, - {'snippet': {'gl': 'IE', 'name': 'Ireland'}, 'id': 'IE'}, - {'snippet': {'gl': 'IL', 'name': 'Israel'}, 'id': 'IL'}, - {'snippet': {'gl': 'IT', 'name': 'Italy'}, 'id': 'IT'}, - {'snippet': {'gl': 'JM', 'name': 'Jamaica'}, 'id': 'JM'}, - {'snippet': {'gl': 'JP', 'name': 'Japan'}, 'id': 'JP'}, - {'snippet': {'gl': 'JO', 'name': 'Jordan'}, 'id': 'JO'}, - {'snippet': {'gl': 'KZ', 'name': 'Kazakhstan'}, 'id': 'KZ'}, - {'snippet': {'gl': 'KE', 'name': 'Kenya'}, 'id': 'KE'}, - {'snippet': {'gl': 'KW', 'name': 'Kuwait'}, 'id': 'KW'}, - {'snippet': {'gl': 'LV', 'name': 'Latvia'}, 'id': 'LV'}, - {'snippet': {'gl': 'LB', 'name': 'Lebanon'}, 'id': 'LB'}, - {'snippet': {'gl': 'LY', 'name': 'Libya'}, 'id': 'LY'}, - {'snippet': {'gl': 'LT', 'name': 'Lithuania'}, 'id': 'LT'}, - {'snippet': {'gl': 'LU', 'name': 'Luxembourg'}, 'id': 'LU'}, - {'snippet': {'gl': 'MK', 'name': 'Macedonia'}, 'id': 'MK'}, - {'snippet': {'gl': 'MY', 'name': 'Malaysia'}, 'id': 'MY'}, - {'snippet': {'gl': 'MX', 'name': 'Mexico'}, 'id': 'MX'}, - {'snippet': {'gl': 'ME', 'name': 'Montenegro'}, 'id': 'ME'}, - {'snippet': {'gl': 'MA', 'name': 'Morocco'}, 'id': 'MA'}, - {'snippet': {'gl': 'NP', 'name': 'Nepal'}, 'id': 'NP'}, - {'snippet': {'gl': 'NL', 'name': 'Netherlands'}, 'id': 'NL'}, - {'snippet': {'gl': 'NZ', 'name': 'New Zealand'}, 'id': 'NZ'}, - {'snippet': {'gl': 'NG', 'name': 'Nigeria'}, 'id': 'NG'}, - {'snippet': {'gl': 'NO', 'name': 'Norway'}, 'id': 'NO'}, - {'snippet': {'gl': 'OM', 'name': 'Oman'}, 'id': 'OM'}, - {'snippet': {'gl': 'PK', 'name': 'Pakistan'}, 'id': 'PK'}, - {'snippet': {'gl': 'PE', 'name': 'Peru'}, 'id': 'PE'}, - {'snippet': {'gl': 'PH', 'name': 'Philippines'}, 'id': 'PH'}, - {'snippet': {'gl': 'PL', 'name': 'Poland'}, 'id': 'PL'}, - {'snippet': {'gl': 'PT', 'name': 'Portugal'}, 'id': 'PT'}, - {'snippet': {'gl': 'PR', 'name': 'Puerto Rico'}, 'id': 'PR'}, - {'snippet': {'gl': 'QA', 'name': 'Qatar'}, 'id': 'QA'}, - {'snippet': {'gl': 'RO', 'name': 'Romania'}, 'id': 'RO'}, - {'snippet': {'gl': 'RU', 'name': 'Russia'}, 'id': 'RU'}, - {'snippet': {'gl': 'SA', 'name': 'Saudi Arabia'}, 'id': 'SA'}, - {'snippet': {'gl': 'SN', 'name': 'Senegal'}, 'id': 'SN'}, - {'snippet': {'gl': 'RS', 'name': 'Serbia'}, 'id': 'RS'}, - {'snippet': {'gl': 'SG', 'name': 'Singapore'}, 'id': 'SG'}, - {'snippet': {'gl': 'SK', 'name': 'Slovakia'}, 'id': 'SK'}, - {'snippet': {'gl': 'SI', 'name': 'Slovenia'}, 'id': 'SI'}, - {'snippet': {'gl': 'ZA', 'name': 'South Africa'}, 'id': 'ZA'}, - {'snippet': {'gl': 'KR', 'name': 'South Korea'}, 'id': 'KR'}, - {'snippet': {'gl': 'ES', 'name': 'Spain'}, 'id': 'ES'}, - {'snippet': {'gl': 'LK', 'name': 'Sri Lanka'}, 'id': 'LK'}, - {'snippet': {'gl': 'SE', 'name': 'Sweden'}, 'id': 'SE'}, - {'snippet': {'gl': 'CH', 'name': 'Switzerland'}, 'id': 'CH'}, - {'snippet': {'gl': 'TW', 'name': 'Taiwan'}, 'id': 'TW'}, - {'snippet': {'gl': 'TZ', 'name': 'Tanzania'}, 'id': 'TZ'}, - {'snippet': {'gl': 'TH', 'name': 'Thailand'}, 'id': 'TH'}, - {'snippet': {'gl': 'TN', 'name': 'Tunisia'}, 'id': 'TN'}, - {'snippet': {'gl': 'TR', 'name': 'Turkey'}, 'id': 'TR'}, - {'snippet': {'gl': 'UG', 'name': 'Uganda'}, 'id': 'UG'}, - {'snippet': {'gl': 'UA', 'name': 'Ukraine'}, 'id': 'UA'}, - {'snippet': {'gl': 'AE', 'name': 'United Arab Emirates'}, 'id': 'AE'}, - {'snippet': {'gl': 'GB', 'name': 'United Kingdom'}, 'id': 'GB'}, - {'snippet': {'gl': 'US', 'name': 'United States'}, 'id': 'US'}, - {'snippet': {'gl': 'VN', 'name': 'Vietnam'}, 'id': 'VN'}, - {'snippet': {'gl': 'YE', 'name': 'Yemen'}, 'id': 'YE'}, - {'snippet': {'gl': 'ZW', 'name': 'Zimbabwe'}, 'id': 'ZW'}, -]} - - def process_language(provider, context, step, steps): localize = context.localize ui = context.get_ui() step += 1 - if not ui.on_yes_no_input( + if ui.on_yes_no_input( localize('setup_wizard') + ' ({0}/{1})'.format(step, steps), (localize('setup_wizard.prompt') % localize('setup_wizard.prompt.locale')) ): - return step - - client = provider.get_client(context) - settings = context.get_settings() - - plugin_language = settings.get_language() - plugin_region = settings.get_region() - - kodi_language = context.get_language() - base_kodi_language = kodi_language.partition('-')[0] - - json_data = client.get_supported_languages(kodi_language) - items = json_data.get('items') or DEFAULT_LANGUAGES['items'] - - selected_language = [None] - - def _get_selected_language(item): - item_lang = item[1] - base_item_lang = item_lang.partition('-')[0] - if item_lang == kodi_language or item_lang == plugin_language: - selected_language[0] = item - elif not selected_language[0] and base_item_lang == base_kodi_language: - selected_language.append(item) - return item - - # Ignore es-419 as it causes hl not a valid language error - # https://github.com/jdf76/plugin.video.youtube/issues/418 - invalid_ids = ('es-419',) - language_list = sorted([ - (item['snippet']['name'], item['snippet']['hl']) - for item in items - if item['id'] not in invalid_ids - ], key=_get_selected_language) - - if selected_language[0]: - selected_language = language_list.index(selected_language[0]) - elif len(selected_language) > 1: - selected_language = language_list.index(selected_language[1]) - else: - selected_language = None - - language_id = ui.on_select( - localize('setup_wizard.locale.language'), - language_list, - preselect=selected_language - ) - if language_id == -1: - return step - - json_data = client.get_supported_regions(language=language_id) - items = json_data.get('items') or DEFAULT_REGIONS['items'] - - selected_region = [None] - - def _get_selected_region(item): - item_region = item[1] - if item_region == plugin_region: - selected_region[0] = item - return item - - region_list = sorted([ - (item['snippet']['name'], item['snippet']['gl']) - for item in items - ], key=_get_selected_region) - - if selected_region[0]: - selected_region = region_list.index(selected_region[0]) - else: - selected_region = None - - region_id = ui.on_select( - localize('setup_wizard.locale.region'), - region_list, - preselect=selected_region - ) - if region_id == -1: - return step - - # set new language id and region id - settings = context.get_settings() - settings.set_language(language_id) - settings.set_region(region_id) + context.execute( + 'RunScript({addon_id},config/language_region)'.format( + addon_id=ADDON_ID, + ), + wait_for=WAIT_END_FLAG, + ) + context.get_settings(refresh=True) return step diff --git a/resources/settings.xml b/resources/settings.xml index 140b5503f..ee9e3b98b 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -857,7 +857,17 @@ - + + + 0 + + true + + RunScript($ID,config/language_region) + + true + + 0 en-US From 00d2bdc5f05659ab504f39fd1c881d4070e8445d Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Thu, 19 Sep 2024 07:37:19 +1000 Subject: [PATCH 10/10] Version bump v7.1.0+beta.3 --- addon.xml | 2 +- changelog.txt | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 0fdfbc8c3..7715fa22e 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + diff --git a/changelog.txt b/changelog.txt index 5cf89fc29..ff8bb8af5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,16 @@ +## v7.1.0+beta.3 +### Fixed +- Fix various timing and sync issues with script, service, plugin and Kodi settings + +### Changed +- Move IP location lookup to script and add to settings dialog +- Move language and region selection to script and add to settings dialog + +### New +- Add hide_next_page query parameter to hide plugin Next page item #896 +- Add new input_prompt command for search endpoint to bypass Kodi window caching + - plugin://plugin.video.youtube/kodion/search/input_prompt + ## v7.1.0+beta.2 ### Fixed - Fix possible regression causing 6s delay on first play