def migrate_from_pickled_fav(): """ This function moves existing pickled favourites in the new json file used for the favourites. The new format (json) appeared in 0.2.17~beta04 All user with version >= 0.2.17 will use favourites in the JSON format Maybe we can remove the migration check on version 0.2.20? """ # Move all pickled existing favs in json file fav_pickle_fp = os.path.join(Script.get_info('profile'), "favourites.pickle") if xbmcvfs.exists(fav_pickle_fp): Script.log('Start favourites migration from pickle file to json file') new_fav_dict = {} with storage.PersistentDict("favourites.pickle") as db: new_fav_dict = dict(db) # Fix old fav for item_hash, item_dict in new_fav_dict.items(): if 'params' in item_dict and isinstance(item_dict['params'], listing.Params): new_fav_dict[item_hash]['params'] = dict(new_fav_dict[item_hash]['params']) try: del new_fav_dict[item_hash]['params']['item_dict']['params'] except Exception: pass if 'properties' in item_dict: if isinstance(item_dict['properties'], listing.Property): new_fav_dict[item_hash]['properties'] = dict(new_fav_dict[item_hash]['properties']) fav_json_fp = os.path.join(Script.get_info('profile'), "favourites.json") with open(fav_json_fp, 'w') as f: json.dump(new_fav_dict, f, indent=4) xbmcvfs.delete(fav_pickle_fp)
def grab_tv_guide(menu_id, menu): xmltv_url = get_xmltv_url(menu_id) Script.log('xmltv url of {}: {}'.format(menu_id, xmltv_url)) xmltv_fn = os.path.basename(urlparse(xmltv_url).path) Script.log('xmltv filename of {}: {}'.format(menu_id, xmltv_fn)) xmltv_fp = os.path.join(Script.get_info('profile'), xmltv_fn) # Remove old xmltv files of this country dirs, files = xbmcvfs.listdir(Script.get_info('profile')) for fn in files: if xmltv_infos[menu_id]['keyword'] in fn and fn != xmltv_fn: Script.log('Remove old xmltv file: {}'.format(fn)) xbmcvfs.delete(os.path.join(Script.get_info('profile'), fn)) # Check if we need to download a fresh xmltv file if not xbmcvfs.exists(xmltv_fp): Script.log("xmltv file of {} for today does not exist, let's download it".format(menu_id)) r = urlquick.get(xmltv_url) with open(xmltv_fp, 'wb') as f: f.write(r.content) # Grab programmes in xmltv file programmes = read_current_programmes(xmltv_fp) # Use the channel as key tv_guide = {} for programme in programmes: programme = programme_post_treatment(programme) tv_guide[programme['channel']] = programme return tv_guide
def download_xmltv_file(country_id, day_delta=0): """Try to download XMLTV file of country_id for today + day_delta. Args: country_id (str) day_delta (int): 0: Today, 1: Tomorrow,... Returns: str: xmltv filepath. """ # Retrieve URL xmltv_url = get_xmltv_url(country_id, day_delta=day_delta) Script.log('xmltv url of {} country with day_delta {}: {}'.format( country_id, day_delta, xmltv_url)) # Compute dst filepath xmltv_fn = os.path.basename(urlparse(xmltv_url).path) Script.log('xmltv filename: {}'.format(xmltv_fn)) xmltv_fp = os.path.join(Script.get_info('profile'), xmltv_fn) # Remove old xmltv files of this country dirs, files = xbmcvfs.listdir(Script.get_info('profile')) today = datetime.date.today() for fn in files: if xmltv_infos[country_id]['keyword'] not in fn: continue try: file_date_s = fn.split( xmltv_infos[country_id]['keyword'])[1].split('.xml')[0] file_date = datetime_strptime(file_date_s, '%Y%m%d').date() if file_date < today: Script.log('Remove old xmltv file: {}'.format(fn)) xbmcvfs.delete(os.path.join(Script.get_info('profile'), fn)) except Exception: pass # Check if we need to download a fresh xmltv file need_to_downlod_xmltv_file = False if not xbmcvfs.exists(xmltv_fp): Script.log( "xmltv file of {} for today does not exist, let's download it". format(country_id)) need_to_downlod_xmltv_file = True else: # Check if we have the last version of the file current_file_md5 = compute_md5(xmltv_fp) remote_file_md5 = get_remote_xmltv_md5(country_id, day_delta=day_delta) print(current_file_md5) print(remote_file_md5) if current_file_md5 != remote_file_md5: Script.log( "A new version of xmltv file of {} for today exists, let's download it" .format(country_id)) need_to_downlod_xmltv_file = True if need_to_downlod_xmltv_file: r = urlquick.get(xmltv_url, max_age=-1) with open(xmltv_fp, 'wb') as f: f.write(r.content) return xmltv_fp
def delete_favourites(plugin): """Callback function of 'Delete favourites' setting button Args: plugin (codequick.script.Script) """ Script.log('Delete favourites db') xbmcvfs.delete( os.path.join(Script.get_info('profile'), 'favourites.pickle')) xbmcvfs.delete(os.path.join(Script.get_info('profile'), 'favourites.json')) Script.notify(Script.localize(30374), '')
def clear_cache(plugin): # Callback function of clear cache setting button # Clear urlquick cache urlquick.cache_cleanup(-1) Script.notify(plugin.localize(30371), '') # Remove all tv guides dirs, files = xbmcvfs.listdir(Script.get_info('profile')) for fn in files: if '.xml' in fn and fn != 'settings.xml': Script.log('Remove xmltv file: {}'.format(fn)) xbmcvfs.delete(os.path.join(Script.get_info('profile'), fn))
def check_addon(addonid, minVersion=False): """Checks if selected add-on is installed.""" try: curVersion = Script.get_info("version", addonid) if minVersion and LooseVersion(curVersion) < LooseVersion(minVersion): Script.log( '{addon} {curVersion} doesn\'t setisfy required version {minVersion}.' .format(addon=addonid, curVersion=curVersion, minVersion=minVersion)) Dialog().ok( "Error", "{minVersion} version of {addon} is required to play this content." .format(addon=addonid, minVersion=minVersion)) return False return True except RuntimeError: Script.log('{addon} is not installed.'.format(addon=addonid)) if not _install_addon(addonid): # inputstream is missing on system Dialog().ok( "Error", "[B]{addon}[/B] is missing on your Kodi install. This add-on is required to play this content." .format(addon=addonid)) return False return True
def grab_tv_guide(menu_id): try: xmltv_url = get_xmltv_url(menu_id) Script.log('xmltv url of {}: {}'.format(menu_id, xmltv_url)) xmltv_fn = os.path.basename(urlparse(xmltv_url).path) Script.log('xmltv filename of {}: {}'.format(menu_id, xmltv_fn)) xmltv_fp = os.path.join(Script.get_info('profile'), xmltv_fn) # Remove old xmltv files of this country dirs, files = xbmcvfs.listdir(Script.get_info('profile')) for fn in files: if xmltv_infos[menu_id]['keyword'] in fn and fn != xmltv_fn: Script.log('Remove old xmltv file: {}'.format(fn)) xbmcvfs.delete(os.path.join(Script.get_info('profile'), fn)) # Check if we need to download a fresh xmltv file if not xbmcvfs.exists(xmltv_fp): Script.log( "xmltv file of {} for today does not exist, let's download it". format(menu_id)) r = urlquick.get(xmltv_url) with open(xmltv_fp, 'wb') as f: f.write(r.content) # Grab programmes in xmltv file programmes = read_current_programmes(xmltv_fp) # Use the channel as key tv_guide = {} for programme in programmes: programme = programme_post_treatment(programme) tv_guide[programme['channel']] = programme return tv_guide except Exception as e: Script.notify(Script.localize(LABELS['TV guide']), Script.localize( LABELS['An error occurred while getting TV guide']), display_time=7000) Script.log('xmltv module failed with error: {}'.format( e, lvl=Script.ERROR)) return {}
def _install_addon(addonid): """Install addon.""" try: # See if there's an installed repo that has it executebuiltin('InstallAddon({})'.format(addonid), wait=True) # Check if add-on exists! version = Script.get_info("version", addonid) Script.log('{addon} {version} add-on installed from repo.'.format( addon=addonid, version=version)) return True except RuntimeError: Script.log('{addon} add-on not installed.'.format(addon=addonid)) return False
def geoip(): """Get country code based on IP address Returns: str: Country code (e.g. FR) """ # better service - https://geoftv-a.akamaihd.net/ws/edgescape.json try: resp = urlquick.get('https://geoftv-a.akamaihd.net/ws/edgescape.json', max_age=-1) data = json.loads(resp.text) if 'reponse' in data: return data['reponse']['geo_info']['country_code'] except Exception: pass Script.notify(Script.get_info('name'), Script.localize(30724), icon=Script.NOTIFY_WARNING) Script.log('Failed to get country code based on IP address', lvl=Script.WARNING) return None
def get_item_media_path(item_media_path): """Get full path or URL of an item_media Args: item_media_path (str or list): Partial media path of the item (e.g. channels/fr/tf1.png) Returns: str: Full path or URL of the item_pedia """ full_path = '' # Local image in ressources/media folder if type(item_media_path) is list: full_path = os.path.join(Script.get_info("path"), "resources", "media", *(item_media_path)) # Remote image with complete URL elif 'http' in item_media_path: full_path = item_media_path # Image in our resource.images add-on else: full_path = 'resource://resource.images.catchuptvandmore/' + item_media_path return utils.ensure_native_str(full_path)
def get_item_media_path(item_media_path): """Get full path or URL of an item_media Args: item_media_path (str or list): Partial media path of the item (e.g. channels/fr/tf1.png) Returns: str: Full path or URL of the item_pedia """ full_path = '' # Local image in ressources/media folder if type(item_media_path) is list: full_path = os.path.join(Script.get_info("path"), "resources", "media", *(item_media_path)) # Remote image with complete URL elif 'http' in item_media_path: full_path = item_media_path # Remote image on our images repo else: full_path = 'https://github.com/Catch-up-TV-and-More/images/raw/master/' + item_media_path return utils.ensure_native_str(full_path)
# Local imports # delete_for_submission_start from resources.lib.vpn import add_vpn_context # delete_for_submission_end from resources.lib.kodi_utils import get_kodi_version import resources.lib.favourites as fav <<<<<<< HEAD:plugin.video.catchuptvandmore/resources/lib/menu_utils.py from resources.lib.addon_utils import get_item_label from resources.lib.migration_utils import migrate_old_menus_settings ======= >>>>>>> cf69920d1ba10a4558544c5d79d7c35f56d3e2c3:resources/lib/menu_utils.py from resources.lib.addon_utils import get_item_label MENUS_SETTINGS_FP = os.path.join(Script.get_info('profile'), "menus_settings.json") """ Json file that keeps, for each menu of the addon, what elements are hidden and the order of items in each menu """ """Utility functions to deal with user menus settings """ def get_menus_settings(): """Get menus settings dict from json file
from codequick import Script, utils from kodi_six import xbmc from kodi_six import xbmcvfs from kodi_six import xbmcgui # Local imports # delete_for_submission_start from resources.lib.vpn import add_vpn_context # delete_for_submission_end from resources.lib.kodi_utils import get_kodi_version import resources.lib.favourites as fav from resources.lib.addon_utils import get_item_label from resources.lib.migration_utils import migrate_old_menus_settings MENUS_SETTINGS_FP = os.path.join(Script.get_info('profile'), "menus_settings.json") """ Json file that keeps, for each menu of the addon, what elements are hidden and the order of items in each menu """ """Utility functions to deal with user menus settings """ def get_menus_settings(): """Get menus settings dict from json file Returns:
def migrate_old_menus_settings(menus_settings_fp): """ This function moves old user settings concerning hidden menu and items order in the new json file used for that purpose. The feature (json) appeared in 0.2.17~betaXX All user with version >= 0.2.17 will use item settings in the JSON format Maybe we can remove the migration check on version 0.2.20? """ # If the json file already exists, the migration has already be done if xbmcvfs.exists(menus_settings_fp): return # We directly read the XML setting file (faster than 'xbmcaddon.Addon().getSetting(s)') addon_settings_fp = os.path.join(Script.get_info('profile'), "settings.xml") if not xbmcvfs.exists(addon_settings_fp): return Script.log('Start item settings migration to json file') j = {} skeletons = [ "root", "live_tv", "replay", 'websites', "fr_live", "ch_live", "uk_live", "wo_live", "be_live", "jp_live", "ca_live", "us_live", "pl_live", "es_live", "tn_live", "it_live", "nl_live", "cn_live", "fr_replay", "ch_replay", "uk_replay", "wo_replay", "be_replay", "jp_replay", "ca_replay", "us_replay", "es_replay", "tn_replay", "it_replay", "nl_replay", "cn_replay" ] tree = ET.parse(addon_settings_fp) old_settings = {} for elem in tree.findall('setting'): if 'id' in elem.attrib: setting_id = elem.attrib['id'] if 'value' in elem.attrib: # Kodi 17 case setting_value = elem.attrib['value'] else: # Kodi 18 and 19 case setting_value = elem.text # try: # print('Setting: "{}" --> "{}"'.format(setting_id, setting_value)) # except Exception: # pass old_settings[setting_id] = setting_value for skeleton in skeletons: current_menu = importlib.import_module('resources.lib.skeletons.' + skeleton).menu for setting_id, setting_value in old_settings.items(): order = False if '.order' in setting_id: setting_id = setting_id.split('.')[0] order = True if setting_id in current_menu: item_infos = current_menu[setting_id] if setting_value != "": if order: if item_infos['order'] != int(setting_value): if skeleton not in j: j[skeleton] = {} if setting_id not in j[skeleton]: j[skeleton][setting_id] = {} j[skeleton][setting_id]['order'] = int(setting_value) else: if setting_value.lower() == "false" and item_infos['enabled'] is True: if skeleton not in j: j[skeleton] = {} if setting_id not in j[skeleton]: j[skeleton][setting_id] = {} j[skeleton][setting_id]['hidden'] = True # Save new item settings json with open(menus_settings_fp, 'w') as f: json.dump(j, f, indent=4)
# Copyright: (c) 2016, Chamchenko # GNU General Public License v2.0+ (see LICENSE.txt or https://www.gnu.org/licenses/gpl-2.0.txt) # This file is part of plugin.video.shahid import xbmc from codequick.utils import urljoin_partial from codequick import Script XBMC_VERSION = int( xbmc.getInfoLabel("System.BuildVersion").split('-')[0].split('.')[0]) INPUTSTREAM_PROP = 'inputstream' if XBMC_VERSION >= 19 else 'inputstreamaddon' #Add-on related ADDON_ID = 'plugin.video.shahid' ADDON_NAME = Script.get_info('name') SETTINGS_LOC = Script.get_info('profile') ADDON_PATH = Script.get_info('path') ADDON_VERSION = Script.get_info('version') ICON = Script.get_info('icon') FANART = Script.get_info('fanart') Hide_Clips = Script.setting.get_boolean('Hide_Clips') HIDE_PREMIUM = Script.setting.get_boolean('Hide_Premium') MODE_KIDS = Script.setting.get_boolean('Mode_Kids') QUALITY = Script.setting.get_string('Quality').replace('p', '') EMAIL = Script.setting.get_string('username') PASSWORD = Script.setting.get_string('password') Movie_Category_Mode = Script.setting.get_string('Movie_Category_Mode') Show_Category_Mode = Script.setting.get_string('Show_Category_Mode') language = xbmc.getLanguage(xbmc.ISO_639_1) if language != 'ar' and language != 'en':
# Inspired by https://gitlab.com/ronie/script.kodi.loguploader/blob/master/default.py import os import re import xbmc import xbmcvfs import xbmcgui import pyqrcode from codequick import Script import urlquick from resources.lib.labels import LABELS PROFILE = Script.get_info('profile') CWD = Script.get_info('path') URL = 'https://paste.kodi.tv/' LOGPATH = xbmc.translatePath('special://logpath') LOGFILE = os.path.join(LOGPATH, 'kodi.log') REPLACES = ( ('//.+?:.+?@', '//USER:PASSWORD@'), ('password.*', 'password*******LINE_DELETED*********'), ('login.*', 'login******LINE_DELETED**********'), ('Password.*', 'Password*******LINE_DELETED*********'), ('Login.*', 'Login******LINE_DELETED**********'), ('email.*', 'email******LINE_DELETED**********'), ('<user>.+?</user>', '<user>USER</user>'), ('<pass>.+?</pass>', '<pass>PASSWORD</pass>'), )
import json from builtins import str from builtins import range from kodi_six import xbmc from kodi_six import xbmcgui from kodi_six import xbmcvfs from codequick import utils, storage, Script, listing from hashlib import md5 import resources.lib.mem_storage as mem_storage from resources.lib.migration_utils import migrate_from_pickled_fav from resources.lib.kodi_utils import get_selected_item_art, get_selected_item_label, get_selected_item_params, get_selected_item_stream, get_selected_item_info from resources.lib.addon_utils import get_item_label, get_item_media_path FAV_JSON_FP = os.path.join(Script.get_info('profile'), "favourites.json") def get_fav_dict_from_json(): """Get favourites dict from favourites.json Returns: dict: Favourites dict """ migrate_from_pickled_fav() if not xbmcvfs.exists(FAV_JSON_FP): return {} try: with open(FAV_JSON_FP) as f: return json.load(f)
except ImportError: from urllib import urlencode import socket # Kodi imports from codequick import Script from kodi_six import xbmcgui # Local imports from resources.lib.addon_utils import get_item_label, get_item_media_path from resources.lib.xmltv import grab_programmes PLUGIN_KODI_PATH = "plugin://plugin.video.catchuptvandmore" # Json file that keeps user settings concerning Kodi Live TV integration made by IPTV Manager TV_INTEGRATION_SETTINGS_FP = os.path.join(Script.get_info('profile'), "tv_integration_settings.json") """Utility functions to deal with user tv integration settings """ def get_tv_integration_settings(): """Get tv integration settings dict from json file Returns: dict: Tv integration settings """ try: with open(TV_INTEGRATION_SETTINGS_FP) as f: settings = json.load(f)