Skip to content

Commit

Permalink
Feature/add update addon details (#20)
Browse files Browse the repository at this point in the history
* Cleaning up addon code
* Implemented updating of addons
  • Loading branch information
chrisism authored Nov 30, 2022
1 parent abc2cbb commit fb6d156
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 57 deletions.
5 changes: 3 additions & 2 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
## Current
- More details about addon plugins

## Previous
- Added support for PEGI rating
- Fixed bug deleting collections
- Proper icon/thumb mapping for virtual collections

## Previous
- Virtual categories now render items from database
- Add and execute single instance ROMs or Games
- Added an overview option with installed plugins
Expand Down
2 changes: 1 addition & 1 deletion resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Advanced Kodi Launcher package initialisation file.

# Copyright (c) 2016-2019 Wintermute0110 <wintermute0110@gmail.com>
# Copyright (c) Chrisism <crizizz@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down
2 changes: 1 addition & 1 deletion resources/lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Advanced Kodi Launcher package inisialisation file.

# Copyright (c) 2016-2019 Wintermute0110 <wintermute0110@gmail.com>
# Copyright (c) Chrisism <crizizz@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down
188 changes: 145 additions & 43 deletions resources/lib/commands/addon_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# Advanced Kodi Launcher: Commands (import & export of configurations)
#
# Copyright (c) Wintermute0110 <[email protected]> / Chrisism <[email protected]>
# Copyright (c) Chrisism <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand All @@ -20,22 +20,24 @@
import logging
import typing
import collections
import time

# -- Kodi libs --
# -- Kodi libs --
import xbmc
import xbmcaddon

# -- AKL libs --
# -- AKL libs --
from akl import constants
from akl.utils import kodi

from resources.lib.commands.mediator import AppMediator
from resources.lib import globals
from resources.lib.repositories import UnitOfWork, AelAddonRepository
from resources.lib.domain import AelAddon
from resources.lib.domain import AelAddon, g_assetFactory

logger = logging.getLogger(__name__)


@AppMediator.register('SCAN_FOR_ADDONS')
def cmd_scan_addons(args):
kodi.notify('Scanning for AKL supported addons')
Expand All @@ -46,17 +48,19 @@ def cmd_scan_addons(args):
xbmc.executebuiltin('InstallAddon(script.akl.defaults)', True)
addon_count = _check_installed_addons()

logger.info('cmd_scan_addons(): Processed {} addons'.format(addon_count))
kodi.notify('Scan completed. Found {} addons'.format(addon_count))
logger.info(f'cmd_scan_addons(): Processed {addon_count} addons')
kodi.notify(f'Scan completed. Found {addon_count} addons')


@AppMediator.register('SHOW_ADDONS')
def cmd_show_addons(args):
def cmd_show_addons(args):
uow = UnitOfWork(globals.g_PATHS.DATABASE_FILE_PATH)
with uow:
repository = AelAddonRepository(uow)
addons = repository.find_all()

options = collections.OrderedDict()
options["cmd_SCAN_FOR_ADDONS"] = "> Scan for new or updated addons"
for addon in addons:
logger.info(f"Installed Addon {addon.get_addon_id()} v{addon.get_version()} {addon.get_addon_type()}")
if addon.get_addon_id() in options:
Expand All @@ -68,33 +72,123 @@ def cmd_show_addons(args):
selected_option = kodi.OrdDictionaryDialog().select(s, options)
if selected_option is None:
return


if selected_option.startswith("cmd_"):
cmd = selected_option.replace("cmd_", "")
AppMediator.sync_cmd(cmd)
cmd_show_addons()
return

AppMediator.sync_cmd("ADDON_DETAILS", {'addon_id': selected_option})


@AppMediator.register('ADDON_DETAILS')
def cmd_addon_details(args):
addon_id:str = args['addon_id'] if 'addon_id' in args else None

options = collections.OrderedDict()
options["UPDATE"] = "Refresh/update addon"
options["METADATA"] = "Supported metadata"
options["ASSETS"] = "Supported assets"
options["SETTINGS"] = "Plugin settings"

addon = xbmcaddon.Addon(addon_id)
title = f"Addon: {addon.getAddonInfo('name')}"

selected_option = kodi.OrdDictionaryDialog().select(title, options)
if selected_option is None:
AppMediator.sync_cmd('SHOW_ADDONS')
return

if selected_option == "UPDATE":
kodi.run_script(addon_id, {'--cmd': 'update-settings'})
time.sleep(1)

addon = xbmcaddon.Addon(addon_id)
addon_name = addon.getAddonInfo('name')
addon_types = addon.getSettingString('akl.plugin_types').split('|')
addon_version = addon.getAddonInfo('version')

uow = UnitOfWork(globals.g_PATHS.DATABASE_FILE_PATH)
with uow:
repository = AelAddonRepository(uow)

if constants.AddonType.LAUNCHER.name in addon_types:
ael_addon = repository.find_by_addon_id(addon_id, constants.AddonType.LAUNCHER)
specific_name = addon.getSetting('akl.launcher.friendlyname')
ael_addon.set_name(specific_name if specific_name else addon_name)
ael_addon.set_version(addon_version)
repository.update_addon(ael_addon)

if constants.AddonType.SCANNER.name in addon_types:
ael_addon = repository.find_by_addon_id(addon_id, constants.AddonType.SCANNER)
specific_name = addon.getSetting('akl.scanner.friendlyname')
ael_addon.set_name(specific_name if specific_name else addon_name)
ael_addon.set_version(addon_version)
repository.update_addon(ael_addon)

if constants.AddonType.SCRAPER.name in addon_types:
ael_addon = repository.find_by_addon_id(addon_id, constants.AddonType.SCRAPER)
specific_name = addon.getSetting('akl.scraper.friendlyname')
ael_addon.set_name(specific_name if specific_name else addon_name)
ael_addon.set_version(addon_version)
ael_addon.set_extra_settings({
'supported_metadata': addon.getSetting('akl.scraper.supported_metadata'),
'supported_assets': addon.getSetting('akl.scraper.supported_assets')
})
repository.update_addon(ael_addon)
uow.commit()
kodi.notify("Updated addon")
cmd_addon_details(args)
return

if selected_option == "METADATA":
supported_metadata_str = addon.getSetting('akl.scraper.supported_metadata')
options = { m: constants.METADATA_DESCRIPTIONS[m] for m in supported_metadata_str.split('|') }
kodi.OrdDictionaryDialog().select(f"Supported metadata: {addon.getAddonInfo('name')}", options)
cmd_addon_details(args)
return

if selected_option == "ASSETS":
supported_assets_str = addon.getSetting('akl.scraper.supported_assets')
assets = g_assetFactory.get_asset_list_by_IDs(supported_assets_str.split('|'))
options = { a.id: a.name for a in assets }
kodi.OrdDictionaryDialog().select(f"Supported assets: {addon.getAddonInfo('name')}", options)
cmd_addon_details(args)
return

if selected_option == "SETTINGS":
addon.openSettings()
cmd_addon_details(args)
return

AppMediator.sync_cmd('SHOW_ADDONS')


def _check_installed_addons() -> int:
addon_count = 0
json_response = kodi.jsonrpc_query("Addons.GetAddons", params={
'installed': True, 'enabled': True,
'type': 'xbmc.python.script'})
'installed': True, 'enabled': True, 'type': 'xbmc.python.script'})

uow = UnitOfWork(globals.g_PATHS.DATABASE_FILE_PATH)
with uow:
addon_repository = AelAddonRepository(uow)
existing_addons = [*addon_repository.find_all()]
addon_repository = AelAddonRepository(uow)
existing_addons = [*addon_repository.find_all()]

existing_launcher_ids = { a.get_addon_id(): a for a in existing_addons if a.get_addon_type() == constants.AddonType.LAUNCHER }
existing_scanner_ids = { a.get_addon_id(): a for a in existing_addons if a.get_addon_type() == constants.AddonType.SCANNER }
existing_scraper_ids = { a.get_addon_id(): a for a in existing_addons if a.get_addon_type() == constants.AddonType.SCRAPER }
existing_launcher_ids = {a.get_addon_id(): a for a in existing_addons if a.get_addon_type() == constants.AddonType.LAUNCHER}
existing_scanner_ids = {a.get_addon_id(): a for a in existing_addons if a.get_addon_type() == constants.AddonType.SCANNER}
existing_scraper_ids = {a.get_addon_id(): a for a in existing_addons if a.get_addon_type() == constants.AddonType.SCRAPER}

for row in json_response['result'].get('addons', []):
addon_id = row['addonid']
addon = xbmcaddon.Addon(addon_id)
addon = xbmcaddon.Addon(addon_id)
# Check if add-on is a AKL support plugin
if addon.getSetting('akl.enabled').lower() != 'true':
continue

logger.debug('cmd_scan_addons(): Found addon {}'.format(addon_id))
logger.debug(f'Found addon {addon_id}')
addon_types = addon.getSettingString('akl.plugin_types').split('|')
addon_count = addon_count + 1
addon_count = addon_count + 1

if constants.AddonType.LAUNCHER.name in addon_types:
_process_launcher_addon(addon_id, addon, existing_launcher_ids, addon_repository)
Expand All @@ -108,12 +202,12 @@ def _check_installed_addons() -> int:
uow.commit()
return addon_count


def _process_launcher_addon(
addon_id:str,
addon:xbmcaddon.Addon,
existing_addon_ids:typing.Dict[str,AelAddon],
addon_repository:AelAddonRepository):

addon_id: str,
addon: xbmcaddon.Addon,
existing_addon_ids: typing.Dict[str, AelAddon],
addon_repository: AelAddonRepository):
addon_name = addon.getSetting('akl.launcher.friendlyname')
addon_name = addon.getAddonInfo('name') if addon_name is None or addon_name == '' else addon_name

Expand All @@ -129,17 +223,17 @@ def _process_launcher_addon(
return
addon_obj.set_id(existing_addon_ids[addon_id].get_id())
addon_repository.update_addon(addon_obj)
logger.debug('cmd_scan_addons(): Updated launcher addon {}'.format(addon_id))
logger.debug(f'Updated launcher addon {addon_id}')
else:
addon_repository.insert_addon(addon_obj)
logger.debug('cmd_scan_addons(): Added launcher addon {}'.format(addon_id))

logger.debug(f'Added launcher addon {addon_id}')


def _process_scanner_addon(
addon_id:str,
addon:xbmcaddon.Addon,
existing_addon_ids:typing.Dict[str,AelAddon],
addon_repository:AelAddonRepository):

addon_id: str,
addon: xbmcaddon.Addon,
existing_addon_ids: typing.Dict[str, AelAddon],
addon_repository: AelAddonRepository):
addon_name = addon.getSetting('akl.scanner.friendlyname')
addon_name = addon.getAddonInfo('name') if addon_name is None or addon_name == '' else addon_name

Expand All @@ -150,22 +244,22 @@ def _process_scanner_addon(
'addon_type': constants.AddonType.SCANNER.name
})

if addon_id in existing_addon_ids:
if addon_id in existing_addon_ids:
if existing_addon_ids[addon_id].get_version() == addon_obj.get_version():
return
addon_obj.set_id(existing_addon_ids[addon_id].get_id())
addon_repository.update_addon(addon_obj)
logger.debug('cmd_scan_addons(): Updated scanner addon {}'.format(addon_id))
logger.debug(f'Updated scanner addon {addon_id}')
else:
addon_repository.insert_addon(addon_obj)
logger.debug('cmd_scan_addons(): Added scanner addon {}'.format(addon_id))

logger.debug(f'Added scanner addon {addon_id}')


def _process_scraper_addon(
addon_id:str,
addon:xbmcaddon.Addon,
existing_addon_ids:typing.Dict[str,AelAddon],
addon_repository:AelAddonRepository):

addon_id: str,
addon: xbmcaddon.Addon,
existing_addon_ids: typing.Dict[str, AelAddon],
addon_repository: AelAddonRepository):
addon_name = addon.getSetting('akl.scraper.friendlyname')
addon_name = addon.getAddonInfo('name') if addon_name is None or addon_name == '' else addon_name

Expand All @@ -177,16 +271,24 @@ def _process_scraper_addon(
})

addon_obj.set_extra_settings({
'supported_metadata': addon.getSetting('akl.scraper.supported_metadata'),
'supported_metadata': addon.getSetting('akl.scraper.supported_metadata'),
'supported_assets': addon.getSetting('akl.scraper.supported_assets')
})

if addon_id in existing_addon_ids:
if existing_addon_ids[addon_id].get_version() == addon_obj.get_version():
return

kodi.run_script(addon_id, {'--cmd': 'update-settings'})
time.sleep(1)
addon_obj.set_extra_settings({
'supported_metadata': addon.getSetting('akl.scraper.supported_metadata'),
'supported_assets': addon.getSetting('akl.scraper.supported_assets')
})

addon_obj.set_id(existing_addon_ids[addon_id].get_id())
addon_repository.update_addon(addon_obj)
logger.debug('cmd_scan_addons(): Updated scraper addon {}'.format(addon_id))
logger.debug(f'Updated scraper addon {addon_id}')
else:
addon_repository.insert_addon(addon_obj)
logger.debug('cmd_scan_addons(): Added scraper addon {}'.format(addon_id))
logger.debug(f'Added scraper addon {addon_id}')
4 changes: 2 additions & 2 deletions resources/lib/commands/category_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# Advanced Kodi Launcher: Commands (category management)
#
# Copyright (c) Wintermute0110 <[email protected]> / Chrisism <[email protected]>
# Copyright (c) Chrisism <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -65,7 +65,7 @@ def cmd_add_category(args):

@AppMediator.register('EDIT_CATEGORY')
def cmd_edit_category(args):
logger.debug('EDIT_CATEGORY: cmd_edit_category() BEGIN')
logger.debug('EDIT_CATEGORY: BEGIN')
category_id:str = args['category_id'] if 'category_id' in args else None

if category_id is None:
Expand Down
4 changes: 2 additions & 2 deletions resources/lib/commands/rom_launcher_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ def cmd_manage_romcollection_launchers(args):
selected_option = kodi.OrdDictionaryDialog().select(s, options)
if selected_option is None:
# >> Exits context menu
logger.debug('EDIT_ROMCOLLECTION_LAUNCHERS: cmd_manage_romcollection_launchers() Selected None. Closing context menu')
logger.debug('EDIT_ROMCOLLECTION_LAUNCHERS: Selected None. Closing context menu')
AppMediator.sync_cmd('EDIT_ROMCOLLECTION', args)
return

# >> Execute subcommand. May be atomic, maybe a submenu.
logger.debug('EDIT_ROMCOLLECTION_LAUNCHERS: cmd_manage_romcollection_launchers() Selected {}'.format(selected_option))
logger.debug(f'EDIT_ROMCOLLECTION_LAUNCHERS: Selected {selected_option}')
AppMediator.sync_cmd(selected_option, args)

@AppMediator.register('EDIT_ROM_LAUNCHERS')
Expand Down
6 changes: 6 additions & 0 deletions resources/lib/domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,18 @@ def get_id(self) -> str:
def get_name(self) -> str:
return self.entity_data['name']

def set_name(self, name: str):
self.entity_data['name'] = name

def get_addon_id(self) -> str:
return self.entity_data['addon_id']

def get_version(self) -> str:
return self.entity_data['version']

def set_version(self, version: str):
self.entity_data['version'] = version

def get_addon_type(self) -> constants.AddonType:
return constants.AddonType[self.entity_data['addon_type']] if 'addon_type' in self.entity_data else constants.AddonType.UNKNOWN

Expand Down
3 changes: 1 addition & 2 deletions resources/lib/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
# Advanced Kodi Launcher: Globals
#

# Copyright (c) Wintermute0110 <[email protected]> / Chrisism <[email protected]>
# Portions (c) 2010-2015 Angelscry
# Copyright (c) Chrisism <[email protected]>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down
Loading

0 comments on commit fb6d156

Please sign in to comment.