Skip to content

Commit 91461df

Browse files
author
bossanova808
committed
[script.module.bossanova808] 1.0.2
1 parent 26686e9 commit 91461df

File tree

3 files changed

+155
-4
lines changed

3 files changed

+155
-4
lines changed

script.module.bossanova808/addon.xml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2-
<addon id="script.module.bossanova808" name="Bossanova808 Dependencies" version="1.0.1" provider-name="bossanova808">
2+
<addon id="script.module.bossanova808" name="Bossanova808 Dependencies" version="1.0.2" provider-name="bossanova808">
33
<requires>
44
<import addon="xbmc.python" version="3.0.0"/>
55
</requires>
@@ -10,8 +10,10 @@
1010
<license>GPL-3.0-only</license>
1111
<website>https://github.com/bossanova808/script.module.bossanova808</website>
1212
<source>https://github.com/bossanova808/script.module.bossanova808</source>
13-
<news>v1.0.1
14-
- Updates for Piers and some defensive programming</news>
13+
<news>v1.0.2
14+
- Fix for previous, for systems using older Python
15+
- Add some more helper functions
16+
</news>
1517
<assets>
1618
<icon>resources/icon.png</icon>
1719
</assets>

script.module.bossanova808/changelog.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
v1.0.2
2+
- Fix for previous, for systems using older Python
3+
- Add some more helper functions
4+
15
v1.0.1
26
- Updates for Piers and some defensive programming
37

script.module.bossanova808/resources/lib/bossanova808/utilities.py

Lines changed: 146 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1+
from __future__ import annotations
12
import json
23
import re
34
import xbmc
5+
import xbmcaddon
46
import xbmcgui
57
import xbmcvfs
68
import xml.etree.ElementTree as ElementTree
79
from urllib.parse import unquote
810
from 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
1317
from .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+
217335
def 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

Comments
 (0)