def _check_updates(): _time = int(time()) if _time < settings.getInt('_last_updates_check', 0) + UPDATES_CHECK_TIME: return settings.setInt('_last_updates_check', _time) new_md5 = session.get(ADDONS_MD5).text.split(' ')[0] if new_md5 == settings.get('addon_md5'): return settings.set('_addon_md5', new_md5) updates = [] slyguy_addons = session.gz_json(ADDONS_URL) slyguy_installed = [x['addonid'] for x in kodi_rpc('Addons.GetAddons', {'installed': True, 'enabled': True})['addons'] if x['addonid'] in slyguy_addons] for addon_id in slyguy_installed: addon = get_addon(addon_id, install=False) if not addon: continue cur_version = addon.getAddonInfo('version') new_version = slyguy_addons[addon_id]['version'] if LooseVersion(cur_version) < LooseVersion(new_version): updates.append([addon_id, cur_version, new_version]) if not updates: return log.debug('Updating repos due to {} addon updates'.format(len(updates))) xbmc.executebuiltin('UpdateAddonRepos')
def _device_id(self): device_id = userdata.get('device_id') if device_id: return device_id device_id = settings.get('device_id') try: mac_address = uuid.getnode() if mac_address != uuid.getnode(): mac_address = '' except: mac_address = '' system, arch = get_system_arch() device_id = device_id.format(username=userdata.get('username'), mac_address=mac_address, system=system).strip() if not device_id: device_id = uuid.uuid4() log.debug('Raw device id: {}'.format(device_id)) device_id = hash_6(device_id, length=16) log.debug('Hashed device id: {}'.format(device_id)) userdata.set('device_id', device_id) return device_id
def dma(self): self._refresh_token() ip = settings.get('region_ip') if not ip or ip == '0.0.0.0': ip = self._ip() params = { 'ipaddress': ip, 'dtp': 8, #controls quality 'syncBackVersion': '3.0', 'mvpdId': 'AllAccess', 'is60FPS': 'true', 'did': self._device_id(), } data = self._session.get('/v3.0/androidphone/dma.json', params=self._params(params)).json() if not data['success']: log.warning( 'Failed to get local CBS channel for IP address ({}). Server message: {}' .format(ip, data.get('message'))) return None return data['dmas'][0]
def login(self, username, password, kickdevice=None): self.logout() raw_id = self._format_id(settings.get('device_id')).lower() device_id = hashlib.sha1(raw_id.encode('utf8')).hexdigest() log.debug('Raw device id: {}'.format(raw_id)) log.debug('Hashed device id: {}'.format(device_id)) hex_password = self._hex_password(password, device_id) params = { 'appID': APP_ID, 'format': 'json', } payload = { 'username': username, 'password': hex_password, 'deviceId': device_id, 'accountType': 'foxtel', } if kickdevice: payload['deviceToKick'] = kickdevice log.debug('Kicking device: {}'.format(kickdevice)) data = self._session.post( '/auth.class.api.php/logon/{site_id}'.format(site_id=VOD_SITEID), data=payload, params=params).json() response = data['LogonResponse'] devices = response.get('CurrentDevices', []) error = response.get('Error') success = response.get('Success') if error: if not devices or kickdevice: raise APIError(_(_.LOGIN_ERROR, msg=error.get('Message'))) options = [d['Nickname'] for d in devices] index = gui.select(_.DEREGISTER_CHOOSE, options) if index < 0: raise APIError(_(_.LOGIN_ERROR, msg=error.get('Message'))) kickdevice = devices[index]['DeviceID'] return self.login(username, password, kickdevice=kickdevice) userdata.set('token', success['LoginToken']) userdata.set('deviceid', success['DeviceId']) userdata.set('entitlements', success.get('Entitlements', '')) if settings.getBool('save_password', False): userdata.set('pswd', password) log.debug('Password Saved') self.logged_in = True
def callback(): function = settings.get('function') if not settings.getBool('silent', False): gui.notification(_(_.RUN_FUNCTION, function=function)) log.debug('Running function: {}'.format(function)) xbmc.executebuiltin(function)
def __init__(self, output_path=None, forced=False): self.output_path = output_path or xbmc.translatePath( settings.get('output_dir', '').strip() or ADDON_PROFILE) if not os.path.exists(self.output_path): os.makedirs(self.output_path) self.forced = forced self.tmp_file = os.path.join(self.output_path, 'iptv_merge_tmp') self.integrations = get_integrations() self._playlist_epgs = []
def iptv_is_setup(): addon = get_addon(IPTV_SIMPLE_ID, required=False, install=False) if not addon: return False output_dir = settings.get('output_dir', '').strip() or ADDON_PROFILE playlist_path = os.path.join(output_dir, PLAYLIST_FILE_NAME) epg_path = os.path.join(output_dir, EPG_FILE_NAME) return addon.getSetting('m3uPathType') == '0' and addon.getSetting('epgPathType') == '0' \ and addon.getSetting('m3uPath') == playlist_path and addon.getSetting('epgPath') == epg_path
def new_session(self): self.logged_in = False host = settings.get('business_host') if settings.getBool( 'business_account', False) else DEFAULT_HOST if host != userdata.get('host', DEFAULT_HOST): userdata.delete('access_token') userdata.set('host', host) self._session = Session(HEADERS, base_url=API_URL.format(host)) self._set_authentication()
def play(channel_id, **kwargs): url = api.play(channel_id) license_path = plugin.url_for(license_request, channel_id=channel_id) return plugin.Item( path=url, inputstream=inputstream.Widevine(license_key=license_path, challenge='b{SSM}', response='B'), headers=HEADERS, proxy_data={'default_language': settings.get('default_language')}, )
def _device_serial(self): def _format_id(string): try: mac_address = uuid.getnode() if mac_address != uuid.getnode(): mac_address = '' except: mac_address = '' system, arch = get_system_arch() return str(string.format(mac_address=mac_address, system=system).strip()) return str(uuid.uuid3(uuid.UUID(UUID_NAMESPACE), _format_id(settings.get('device_id'))))
def new_session(self): self._session = Session(HEADERS) self._cache_key = self._region = settings.getEnum('region', REGIONS, default=US) if self._region in X_FORWARDS: self._session.headers.update({'x-forwarded-for': X_FORWARDS[self._region]}) elif self._region == CUSTOM: region_ip = settings.get('region_ip', '0.0.0.0') if region_ip != '0.0.0.0': self._session.headers.update({'x-forwarded-for': region_ip}) self._cache_key = region_ip self._cache_key += str(settings.getBool('show_epg', False))
def __init__(self, output_path=None, forced=False): self.working_path = ADDON_PROFILE self.output_path = output_path or xbmc.translatePath( settings.get('output_dir', '').strip() or self.working_path) if not xbmcvfs.exists(self.working_path): xbmcvfs.mkdirs(self.working_path) if not xbmcvfs.exists(self.output_path): xbmcvfs.mkdirs(self.output_path) self.forced = forced self.tmp_file = os.path.join(self.working_path, 'iptv_merge_tmp') self._playlist_epgs = []
def _check_news(): _time = int(time()) if _time < settings.getInt('_last_news_check', 0) + NEWS_CHECK_TIME: return settings.setInt('_last_news_check', _time) news = Session(timeout=15).gz_json(NEWS_URL) if not news: return if 'id' not in news or news['id'] == settings.get('_last_news_id'): return settings.set('_last_news_id', news['id']) settings.set('_news', json.dumps(news))
def _hex_password(self, password, device_id): nickname = self._format_id(settings.get('device_name')) log.debug('Device nickname: {}'.format(nickname)) payload = { 'deviceId': device_id, 'nickName': nickname, 'format': 'json', 'appID': 'GO2', 'accountType': 'foxtel', 'plt': PLT_DEVICE, } secret = self._session.post( '/auth.class.api.php/prelogin/{site_id}'.format( site_id=VOD_SITEID), data=payload).json()['secret'] log.debug('Pass Secret: {}{}'.format(secret[:5], 'x' * len(secret[5:]))) try: #python3 iv = bytes.fromhex(AES_IV) except AttributeError: #python2 iv = str(bytearray.fromhex(AES_IV)) encrypter = pyaes.Encrypter( pyaes.AESModeOfOperationCBC(secret.encode('utf8'), iv)) ciphertext = encrypter.feed(password) ciphertext += encrypter.feed() try: #python3 hex_password = ciphertext.hex() except AttributeError: #python2 hex_password = ciphertext.encode('hex') log.debug('Hex password: {}{}'.format(hex_password[:5], 'x' * len(hex_password[5:]))) return hex_password
def _setup(check_only=False, reinstall=True, run_merge=True): addon = get_addon(IPTV_SIMPLE_ID, required=not check_only, install=not check_only) if not addon: return False output_dir = settings.get('output_dir', '').strip() or ADDON_PROFILE playlist_path = os.path.join(output_dir, PLAYLIST_FILE_NAME) epg_path = os.path.join(output_dir, EPG_FILE_NAME) is_setup = addon.getSetting('m3uPathType') == '0' and addon.getSetting('epgPathType') == '0' \ and addon.getSetting('m3uPath') == playlist_path and addon.getSetting('epgPath') == epg_path if check_only: return is_setup elif is_setup and not reinstall: if run_merge: set_kodi_string('_iptv_merge_force_run', '1') return True ## IMPORT ANY CURRENT URL SOURCES ## cur_epg_url = addon.getSetting('epgUrl') cur_epg_type = addon.getSetting('epgPathType') if cur_epg_url: epg = EPG(source_type=EPG.TYPE_URL, path=cur_epg_url, enabled=cur_epg_type == '1') try: epg.save() except: pass cur_m3u_url = addon.getSetting('m3uUrl') cur_m3u_type = addon.getSetting('m3uPathType') start_chno = int(addon.getSetting('startNum') or 1) #user_agent = addon.getSetting('userAgent') if cur_m3u_url: playlist = Playlist(source_type=Playlist.TYPE_URL, path=cur_m3u_url, enabled=cur_m3u_type == '1') if start_chno != 1: playlist.use_start_chno = True playlist.start_chno = start_chno try: playlist.save() except: pass ################################ addon.setSetting('epgPath', epg_path) addon.setSetting('m3uPath', playlist_path) addon.setSetting('epgUrl', '') addon.setSetting('m3uUrl', '') addon.setSetting('m3uPathType', '0') addon.setSetting('epgPathType', '0') set_kodi_setting('epg.futuredaystodisplay', 7) # set_kodi_setting('epg.ignoredbforclient', True) set_kodi_setting('pvrmanager.syncchannelgroups', True) set_kodi_setting('pvrmanager.preselectplayingchannel', True) set_kodi_setting('pvrmanager.backendchannelorder', True) set_kodi_setting('pvrmanager.usebackendchannelnumbers', True) if run_merge: set_kodi_string('_iptv_merge_force_run', '1') gui.ok(_.SETUP_IPTV_COMPLETE) return True
def _setup(): addon = get_addon(IPTV_SIMPLE_ID, required=True, install=True) with gui.progress(_.SETTING_UP_IPTV) as progress: kodi_rpc('Addons.SetAddonEnabled', {'addonid': IPTV_SIMPLE_ID, 'enabled': False}) output_dir = settings.get('output_dir', '').strip() or ADDON_PROFILE playlist_path = os.path.join(output_dir, PLAYLIST_FILE_NAME) epg_path = os.path.join(output_dir, EPG_FILE_NAME) ## IMPORT ANY CURRENT URL SOURCES ## cur_epg_url = addon.getSetting('epgUrl') cur_epg_type = addon.getSetting('epgPathType') if cur_epg_url: epg = EPG(source_type=EPG.TYPE_URL, path=cur_epg_url, enabled=cur_epg_type == '1') try: epg.save() except: pass cur_m3u_url = addon.getSetting('m3uUrl') cur_m3u_type = addon.getSetting('m3uPathType') start_chno = int(addon.getSetting('startNum') or 1) #user_agent = addon.getSetting('userAgent') if cur_m3u_url: playlist = Playlist(source_type=Playlist.TYPE_URL, path=cur_m3u_url, enabled=cur_m3u_type == '1') if start_chno != 1: playlist.use_start_chno = True playlist.start_chno = start_chno try: playlist.save() except: pass ################################ addon.setSetting('epgPath', epg_path) addon.setSetting('m3uPath', playlist_path) addon.setSetting('epgUrl', '') addon.setSetting('m3uUrl', '') addon.setSetting('m3uPathType', '0') addon.setSetting('epgPathType', '0') monitor = xbmc.Monitor() progress.update(30) monitor.waitForAbort(2) kodi_rpc('Addons.SetAddonEnabled', {'addonid': IPTV_SIMPLE_ID, 'enabled': True}) progress.update(60) monitor.waitForAbort(2) progress.update(100) set_kodi_setting('epg.futuredaystodisplay', 7) # set_kodi_setting('epg.ignoredbforclient', True) set_kodi_setting('pvrmanager.syncchannelgroups', True) set_kodi_setting('pvrmanager.preselectplayingchannel', True) set_kodi_setting('pvrmanager.backendchannelorder', True) set_kodi_setting('pvrmanager.usebackendchannelnumbers', True) set_kodi_string('_iptv_merge_force_run', '1') gui.ok(_.SETUP_IPTV_COMPLETE) return True
def _setup(): addon = get_addon(IPTV_SIMPLE_ID, required=True, install=True) with gui.progress(_.SETTING_UP_IPTV) as progress: kodi_rpc('Addons.SetAddonEnabled', {'addonid': IPTV_SIMPLE_ID, 'enabled': False}) output_dir = xbmc.translatePath(settings.get('output_dir', '').strip() or ADDON_PROFILE) playlist_path = os.path.join(output_dir, PLAYLIST_FILE_NAME) epg_path = os.path.join(output_dir, EPG_FILE_NAME) if not os.path.exists(playlist_path): with open(playlist_path, 'w') as f: f.write('''#EXTM3U #EXTINF:-1 tvg-id="iptv_merge" tvg-chno="1000" tvg-logo="{}",{} {}'''.format(ADDON_ICON, 'IPTV Merge: Click me to run a merge!', plugin.url_for(merge))) if not os.path.exists(epg_path): with open(epg_path, 'w') as f: f.write('''<?xml version="1.0" encoding="utf-8" ?><tv><channel id="iptv_merge"></channel></tv>''') ## IMPORT ANY CURRENT SOURCES ## cur_epg_url = addon.getSetting('epgUrl') cur_epg_path = addon.getSetting('epgPath') cur_epg_type = addon.getSetting('epgPathType') if cur_epg_path != epg_path and os.path.exists(xbmc.translatePath(cur_epg_path)): epg = EPG(source_type=EPG.TYPE_FILE, path=cur_epg_path, enabled=cur_epg_type == '0') epg.auto_archive_type() try: epg.save() except: pass if cur_epg_url: epg = EPG(source_type=EPG.TYPE_URL, path=cur_epg_url, enabled=cur_epg_type == '1') epg.auto_archive_type() try: epg.save() except: pass cur_m3u_url = addon.getSetting('m3uUrl') cur_m3u_path = addon.getSetting('m3uPath') cur_m3u_type = addon.getSetting('m3uPathType') start_chno = int(addon.getSetting('startNum') or 1) #user_agent = addon.getSetting('userAgent') if cur_m3u_path != playlist_path and os.path.exists(xbmc.translatePath(cur_m3u_path)): playlist = Playlist(source_type=Playlist.TYPE_FILE, path=cur_m3u_path, enabled=cur_m3u_type == '0') playlist.auto_archive_type() if start_chno != 1: playlist.use_start_chno = True playlist.start_chno = start_chno try: playlist.save() except: pass if cur_m3u_url: playlist = Playlist(source_type=Playlist.TYPE_URL, path=cur_m3u_url, enabled=cur_m3u_type == '1') playlist.auto_archive_type() if start_chno != 1: playlist.use_start_chno = True playlist.start_chno = start_chno try: playlist.save() except: pass ##### addon.setSetting('epgPath', epg_path) addon.setSetting('m3uPath', playlist_path) addon.setSetting('epgUrl', '') addon.setSetting('m3uUrl', '') addon.setSetting('m3uPathType', '0') addon.setSetting('epgPathType', '0') monitor = xbmc.Monitor() progress.update(30) monitor.waitForAbort(2) kodi_rpc('Addons.SetAddonEnabled', {'addonid': IPTV_SIMPLE_ID, 'enabled': True}) progress.update(60) monitor.waitForAbort(2) progress.update(100) set_kodi_setting('epg.futuredaystodisplay', 7) # set_kodi_setting('epg.ignoredbforclient', True) set_kodi_setting('pvrmanager.syncchannelgroups', True) set_kodi_setting('pvrmanager.preselectplayingchannel', True) set_kodi_setting('pvrmanager.backendchannelorder', True) set_kodi_setting('pvrmanager.usebackendchannelnumbers', True) gui.ok(_.SETUP_IPTV_COMPLETE) return True
def playlists(self, refresh=True): playlist_path = os.path.join(self.output_path, PLAYLIST_FILE_NAME) working_path = os.path.join(self.working_path, PLAYLIST_FILE_NAME) if not refresh and xbmcvfs.exists(playlist_path) and xbmcvfs.exists( working_path): return working_path start_time = time.time() database.connect() try: progress = gui.progressbg() if self.forced else None playlists = list(Playlist.select().where( Playlist.enabled == True).order_by(Playlist.order)) Playlist.update({ Playlist.results: [] }).where(Playlist.enabled == False).execute() Channel.delete().where( Channel.custom == False, Channel.playlist.not_in(playlists)).execute() for count, playlist in enumerate(playlists): count += 1 if progress: progress.update( int(count * (100 / len(playlists))), 'Merging Playlist ({}/{})'.format( count, len(playlists)), _(playlist.label, _bold=True)) playlist_start = time.time() error = None try: log.debug('Processing: {}'.format(playlist.path)) if playlist.source_type != Playlist.TYPE_CUSTOM: self._process_source(playlist, METHOD_PLAYLIST, self.tmp_file) with database.db.atomic() as transaction: try: added = self._process_playlist( playlist, self.tmp_file) except: transaction.rollback() raise else: added = len(playlist.channels) except AddonError as e: error = e except Error as e: error = e log.exception(e) except Exception as e: error = e log.exception(e) else: playlist.results.insert(0, [ int(time.time()), Playlist.OK, '{} Channels ({:.2f}s)'.format( added, time.time() - playlist_start) ]) error = None if error: result = [int(time.time()), Playlist.ERROR, str(error)] if playlist.results and playlist.results[0][ 1] == Playlist.ERROR: playlist.results[0] = result else: playlist.results.insert(0, result) remove_file(self.tmp_file) playlist.results = playlist.results[:3] playlist.save() count = 0 starting_ch_no = settings.getInt('start_ch_no', 1) with codecs.open(working_path, 'w', encoding='utf8') as outfile: outfile.write(u'#EXTM3U') group_order = settings.get('group_order') if group_order: outfile.write(u'\n\n#EXTGRP:{}'.format(group_order)) chno = starting_ch_no tv_groups = [] for channel in Channel.playlist_list(radio=False): if channel.chno is None: channel.chno = chno chno = channel.chno + 1 tv_groups.extend(channel.groups) outfile.write(u'\n\n') outfile.write(channel.get_lines()) count += 1 chno = starting_ch_no for channel in Channel.playlist_list(radio=True): if channel.chno is None: channel.chno = chno chno = channel.chno + 1 new_groups = [] for group in channel.groups: count = 1 while group in tv_groups: group = _(_.RADIO_GROUP, group=group) if count > 1: group = u'{} #{}'.format(group, count) count += 1 new_groups.append(group) channel.groups = new_groups outfile.write(u'\n\n') outfile.write(channel.get_lines()) count += 1 if count == 0: outfile.write(u'\n\n#EXTINF:-1,EMPTY PLAYLIST\nhttp') log.debug('Wrote {} Channels'.format(count)) Playlist.after_merge() _safe_copy(working_path, playlist_path) finally: database.close() if progress: progress.close() remove_file(self.tmp_file) log.debug('Playlist Merge Time: {0:.2f}'.format(time.time() - start_time)) return working_path