1+ from __future__ import annotations
12import json
23import re
34import xbmc
5+ import xbmcaddon
46import xbmcgui
57import xbmcvfs
68import xml .etree .ElementTree as ElementTree
79from urllib .parse import unquote
810from typing import Any
911
12+
13+ # (TODO - once OzWeather 2.1.6 and matching Skin Patcher are released, the WEATHER_WINDOW just below can be removed again...)
1014# noinspection PyPackages
11- from .constants import ADDON
15+ from .constants import *
1216# noinspection PyPackages
1317from .logger import Logger
1418
@@ -214,6 +218,120 @@ def is_playback_paused() -> bool:
214218 return bool (xbmc .getCondVisibility ("Player.Paused" ))
215219
216220
221+ def get_addon_version (addon_id : str ) -> str | None :
222+ """
223+ Helper function to return the currently installed version of Kodi addon by its ID.
224+
225+ :param addon_id: the ID of the addon, e.g. weather.ozweather
226+ :return: the version string (e.g. "0.0.1"), or None if the addon is not installed and enabled
227+ """
228+ try :
229+ addon = xbmcaddon .Addon (id = addon_id )
230+ version = addon .getAddonInfo ('version' )
231+ except RuntimeError as e :
232+ Logger .error (f"Error getting version for { addon_id } " )
233+ Logger .error (e )
234+ return None
235+
236+ return version
237+
238+
239+ def get_resume_point (library_type : str , dbid : int ) -> float | None :
240+ """
241+ Get the resume point from the Kodi library for a given Kodi DB item
242+
243+ :param library_type: one of 'episode', 'movie' or 'musicvideo'
244+ :param dbid: the Kodi DB item ID
245+ :return: the resume point, or None if there isn't one set
246+ """
247+
248+ params = _get_jsonrpc_video_lib_params (library_type )
249+ # Short circuit if there is an issue get the JSON RPC method etc.
250+ if not params :
251+ return None
252+ get_method , id_name , result_key = params
253+
254+ json_dict = {
255+ "jsonrpc" :"2.0" ,
256+ "id" :"getResumePoint" ,
257+ "method" :get_method ,
258+ "params" :{
259+ id_name :dbid ,
260+ "properties" :["resume" ],
261+ }
262+ }
263+
264+ query = json .dumps (json_dict )
265+ json_response = send_kodi_json (f'Get resume point for { library_type } with dbid: { dbid } ' , query )
266+ if not json_response :
267+ Logger .error ("Nothing returned from JSON-RPC query" )
268+ return None
269+
270+ result = json_response .get ('result' )
271+ if result :
272+ try :
273+ resume_point = result [result_key ]['resume' ]['position' ]
274+ except (KeyError , TypeError ) as e :
275+ Logger .error ("Could not get resume point" )
276+ Logger .error (e )
277+ resume_point = None
278+ else :
279+ Logger .error ("No result returned from JSON-RPC query" )
280+ resume_point = None
281+
282+ Logger .info (f"Resume point retrieved: { resume_point } " )
283+
284+ return resume_point
285+
286+
287+ def get_playcount (library_type : str , dbid : int ) -> int | None :
288+ """
289+ Get the playcount for the given Kodi DB item
290+
291+ :param library_type: one of 'episode', 'movie' or 'musicvideo'
292+ :param dbid: the Kodi DB item ID
293+ :return: the playcount if there is one, or None
294+ """
295+
296+ params = _get_jsonrpc_video_lib_params (library_type )
297+ # Short circuit if there is an issue get the JSON RPC method etc.
298+ if not params :
299+ return None
300+ get_method , id_name , result_key = params
301+
302+ json_dict = {
303+ "jsonrpc" :"2.0" ,
304+ "id" :"getPlayCount" ,
305+ "method" :get_method ,
306+ "params" :{
307+ id_name :dbid ,
308+ "properties" :["playcount" ],
309+ }
310+ }
311+
312+ query = json .dumps (json_dict )
313+ json_response = send_kodi_json (f'Get playcount for { library_type } with dbid: { dbid } ' , query )
314+ if not json_response :
315+ Logger .error ("Nothing returned from JSON-RPC query" )
316+ return None
317+
318+ result = json_response .get ('result' )
319+ if result :
320+ try :
321+ play_count = result [result_key ]['playcount' ]
322+ except (KeyError , TypeError ) as e :
323+ Logger .error ("Could not get playcount" )
324+ Logger .error (e )
325+ play_count = None
326+ else :
327+ Logger .error ("No result returned from JSON-RPC query" )
328+ play_count = None
329+
330+ Logger .info (f"Playcount retrieved: { play_count } " )
331+
332+ return play_count
333+
334+
217335def footprints (startup : bool = True ) -> None :
218336 """
219337 TODO - this has moved to Logger - update all addons to use Logger.start/.stop directly, then ultimately remove this!
@@ -225,3 +343,30 @@ def footprints(startup: bool = True) -> None:
225343 Logger .start ()
226344 else :
227345 Logger .stop ()
346+
347+
348+ def _get_jsonrpc_video_lib_params (library_type : str ) -> tuple [str , str , str ] | None :
349+ """
350+ Given a Kodi library type, return the JSON RPC library parameters needed to get details
351+
352+ :param library_type: one of 'episode', 'movie' or 'musicvideo'
353+ :return: method for getting details, the name of the id, and the key for the results returned
354+ """
355+
356+ if library_type == 'episode' :
357+ get_method = 'VideoLibrary.GetEpisodeDetails'
358+ id_name = 'episodeid'
359+ result_key = 'episodedetails'
360+ elif library_type == 'movie' :
361+ get_method = 'VideoLibrary.GetMovieDetails'
362+ id_name = 'movieid'
363+ result_key = 'moviedetails'
364+ elif library_type == 'musicvideo' :
365+ get_method = 'VideoLibrary.GetMusicVideoDetails'
366+ id_name = 'musicvideoid'
367+ result_key = 'musicvideodetails'
368+ else :
369+ Logger .error (f"Unsupported library type: { library_type } " )
370+ return None
371+
372+ return get_method , id_name , result_key
0 commit comments