def export(self, results='playthis', ctype='video'): if results == 'resolved': from addon_lib.playback import resolve else: def resolve(url): return url rows = self._get() if rows: _m3u = '#EXTM3U\n' m3u = _m3u for item, content_type, title, thumb in rows: if content_type != ctype: continue if results == 'resolved': resolved = resolve(item) else: resolved = None if resolved: log_utils.log( 'M3UUtils.export adding resolved item: |{0!s}| as |{1!s}|' .format(resolved, title), log_utils.LOGDEBUG) m3u += '#EXTINF:{0!s} tvg-logo="{3!s}",{1!s}\n{2!s}\n'.format( '0', title, resolved, thumb) else: if results == 'playthis': pt_url = 'plugin://plugin.video.playthis/?mode=play&player=false&history=false&path={0!s}' \ .format(quote(item)) log_utils.log( 'M3UUtils.export adding PlayThis item: |{0!s}| as |{1!s}|' .format(pt_url, title), log_utils.LOGDEBUG) m3u += '#EXTINF:{0!s} tvg-logo="{3!s}",{1!s}\n{2!s}\n'.format( '0', title, pt_url, thumb) else: log_utils.log( 'M3UUtils.export adding unresolved item: |{0!s}| as |{1!s}|' .format(item, title), log_utils.LOGDEBUG) m3u += '#EXTINF:{0!s} tvg-logo="{3!s}",{1!s}\n{2!s}\n'.format( '0', title, item, thumb) if m3u != _m3u: log_utils.log( 'M3UUtils.export writing .m3u: |{0!s}|'.format( self.filename), log_utils.LOGDEBUG) try: with open(self.filename, 'w+') as f: f.write(m3u) log_utils.log('M3UUtils.export writing .m3u completed.', log_utils.LOGDEBUG) kodi.notify(msg=kodi.i18n('export_success'), sound=False) return except: log_utils.log('M3UUtils.export failed to write .m3u', log_utils.LOGDEBUG) kodi.notify(msg=kodi.i18n('export_fail'), sound=False) return log_utils.log('M3UUtils.export no items for export to .m3u', log_utils.LOGDEBUG) kodi.notify(msg=kodi.i18n('no_items_export'), sound=False)
def export_strm(row_id, export_path=None): if export_path is None: export_path = kodi.get_setting('export_path_strm') if not export_path: export_path = kodi.Dialog().browse(3, kodi.i18n('export_path_strm'), 'files', '', False, False) kodi.set_setting('export_path_strm', export_path) if export_path: default_filename = '' play_history = PlayHistory() rows = play_history.get(row_id=row_id) if rows: url, content_type, title, thumb = rows[0] default_filename = kodi.string_to_filename(title) + '.strm' strm_name = kodi.get_keyboard(kodi.i18n('strm_filename'), default_filename) if strm_name: if export_path.startswith('special://'): if not export_path.endswith('/'): export_path += '/' kodi.set_setting('export_path_strm', export_path) strm_file = kodi.translate_path(export_path + strm_name) else: strm_file = os.path.join(export_path, strm_name) STRMUtils(strm_file).export(row_id)
def export(self, row_id): rows = self._get(row_id) if rows: url, content_type, title, thumb = rows[0] play_path = { 'mode': MODES.PLAY, 'player': 'false', 'history': 'false', 'path': quote(url), 'thumb': quote(thumb) } strm = kodi.get_plugin_url(play_path) if strm: log_utils.log( 'STRMUtils.export writing .m3u: |{0!s}|'.format( self.filename), log_utils.LOGDEBUG) try: with open(self.filename, 'w+') as f: f.write(strm) log_utils.log('STRMUtils.export writing .m3u completed.', log_utils.LOGDEBUG) kodi.notify(msg=kodi.i18n('export_success'), sound=False) return except: log_utils.log('STRMUtils.export failed to write .strm', log_utils.LOGDEBUG) kodi.notify(msg=kodi.i18n('export_fail'), sound=False) return log_utils.log('STRMUtils.export no item for export to .strm', log_utils.LOGDEBUG) kodi.notify(msg=kodi.i18n('no_items_export'), sound=False)
def clear_cache(): confirmed = kodi.Dialog().yesno(kodi.i18n('confirm'), kodi.i18n('cache_yes_no')) if confirmed: result = cache.reset_cache() if result: kodi.notify(msg=kodi.i18n('cache_success'), sound=False) else: kodi.notify(msg=kodi.i18n('cache_failed'), sound=False)
def delete_row(row_id, title='', refresh=True): confirmed = kodi.Dialog().yesno( kodi.i18n('confirm'), '%s \'%s\'%s' % (kodi.i18n('delete_url'), unquote(title), '?')) if confirmed: play_history = PlayHistory() result, rowcount = play_history.delete_row_id(row_id) if (result, rowcount) == (1, 1) and refresh: kodi.refresh_container()
def clear_history(ctype=None): ltype = ctype if ltype is None: ltype = 'all' confirmed = kodi.Dialog().yesno(kodi.i18n('confirm'), kodi.i18n('clear_yes_no') % ltype) if confirmed: play_history = PlayHistory() play_history.clear(ctype) kodi.refresh_container()
def clear(self, ctype=None): if ctype is None: result = DATABASE.execute('DROP TABLE {0!s}'.format(self.TABLE), '') else: result = DATABASE.execute( 'DELETE FROM {0!s} WHERE content_type=?'.format(self.TABLE), (ctype, )) if result == 1: self.vacuum() kodi.notify(msg=kodi.i18n('history_cleared'), sound=False) else: kodi.notify(msg=kodi.i18n('fail_history_clear'), sound=False)
def change_thumb_by_row_id(row_id, local=True, refresh=True): if local: thumbnail = kodi.Dialog().browse(2, kodi.i18n('choose_thumbnail'), 'pictures', '', True, False, THUMBNAILS_DIR) else: thumbnail = kodi.get_keyboard(kodi.i18n('input_new_thumb')) if thumbnail and (not thumbnail.endswith('/')) and ( not thumbnail.endswith('\\')): play_history = PlayHistory() result = play_history.change_thumb(row_id, thumbnail) if result and refresh: kodi.refresh_container()
def download_audio(video_id, background=True): url = YOUTUBE_VIDEO_URL % video_id info = get_video_info(url) if info: stream = info._streams[0] ytdl_format = stream.get('ytdl_format', {}) formats = ytdl_format.get('formats', []) best_quality = 0 best_format = None if formats: for fmt in formats: fmt_desc = fmt.get('format', '') log_utils.log('format: |%s|' % fmt_desc) if 'audio only' in fmt_desc.lower(): format_id = fmt.get('format_id', '') asr = fmt.get('asr', '') tbr = fmt.get('tbr', '') abr = fmt.get('abr', '') ext = fmt.get('ext', '') log_utils.log( 'id: |%s| ext: |%s| asr: |%s| tbr: |%s| abr: |%s|' % (format_id, ext, asr, tbr, abr)) if 'm4a' in ext: tbr = int(fmt.get('tbr')) if tbr > best_quality: best_quality = tbr best_format = fmt log_utils.log( 'Updated best_format: |%s| id: |%s| ext: |%s| asr: |%s| tbr: |%s| abr: |%s|' % (fmt_desc, format_id, ext, asr, tbr, abr)) if best_format: stream['xbmc_url'] = best_format[ 'url'] + '|' + urllib.urlencode({'User-Agent': USER_AGENT}) stream['url'] = best_format['url'] stream['ytdl_format'].update(best_format) stream['ytdl_format']['formats'] = [best_format] info._streams = [stream] log_utils.log( 'Downloading: |audio| video_id: |%s| Background: |%s|' % (video_id, str(background))) _download(info, background) else: log_utils.log( 'No audio-only stream formats found: |%s|' % video_id, log_utils.LOGERROR) kodi.notify(msg=kodi.i18n('no_audio_stream_formats'), sound=False) else: log_utils.log('No stream formats found: |%s|' % video_id, log_utils.LOGERROR) kodi.notify(msg=kodi.i18n('no_stream_formats'), sound=False)
def clear_cookies(): confirmed = kodi.Dialog().yesno(kodi.i18n('confirm'), kodi.i18n('cookies_yes_no')) if confirmed: try: if kodi.vfs.exists(COOKIE_FILE): result = kodi.vfs.delete(COOKIE_FILE) else: result = True except: result = False if result: kodi.notify(msg=kodi.i18n('cookies_success'), sound=False) else: kodi.notify(msg=kodi.i18n('cookies_failed'), sound=False)
def change_thumb(self, row_id, thumb): execute = 'UPDATE {0!s} SET thumbnail=? WHERE id=? AND addon_id=?'.format( self.TABLE) result = DATABASE.execute(execute, (unquote(thumb), row_id, self.ID)) if result != 1: kodi.notify(msg=kodi.i18n('thumbchange_failed'), sound=False) return result
def rename_row_id(row_id, refresh=True): label = kodi.get_keyboard(kodi.i18n('input_new_label')) if label: play_history = PlayHistory() result = play_history.rename_row_id(row_id, label) if result and refresh: kodi.refresh_container()
def get_input(self): got_input = kodi.get_keyboard(kodi.i18n('enter_for_playback'), '') if got_input: got_input = got_input.strip() got_input = quote(re.sub(r'\s+', ' ', got_input)) return got_input return ''
def rename_row_id(self, row_id, label): execute = 'UPDATE {0!s} SET label=? WHERE id=? AND addon_id=?'.format( self.TABLE) result = DATABASE.execute(execute, (label, row_id, self.ID)) if result != 1: kodi.notify(msg=kodi.i18n('rename_failed'), sound=False) return result
def manage_context(row_id, title): context_items = [ 'rename_row_id(row_id=row_id)', 'change_thumb_by_row_id(row_id=row_id)', 'change_thumb_by_row_id(row_id=row_id, local=False)', 'delete_row(row_id=row_id, title=unquote(title))' ] select_items = [ kodi.i18n('rename'), kodi.i18n('local_thumb'), kodi.i18n('url_thumb'), kodi.i18n('delete_url') ] result = kodi.Dialog().select(kodi.i18n('manage'), select_items) if result != -1: eval(context_items[result])
def get_video_info(url): info = YDStreamExtractor.getVideoInfo(url) if hasattr(info, '_streams'): return info else: log_utils.log('Stream not available: |%s|' % url, log_utils.LOGERROR) kodi.notify(msg=kodi.i18n('stream_not_available'), sound=False) return None
def get_video_info(url): info = YDStreamExtractor.getVideoInfo(url) if hasattr(info, '_streams'): return info else: log_utils.log('Stream not available: |%s|' % url, log_utils.LOGERROR) kodi.notify(msg=kodi.i18n('stream_not_available'), sound=False) return None
def delete_row_id(self, row_id): execute = 'DELETE FROM {0!s} WHERE id=? AND addon_id=?'.format( self.TABLE) result, rowcount = DATABASE.execute_w_rowcount(execute, (row_id, self.ID)) if result != 1: kodi.notify(msg=kodi.i18n('delete_failed'), sound=False) return result, rowcount
def delete_url(self, url): execute = 'DELETE FROM {0!s} WHERE url=? AND addon_id=?'.format( self.TABLE) result, rowcount = DATABASE.execute_w_rowcount(execute, (url, self.ID)) if result != 1: kodi.notify(msg=kodi.i18n('delete_failed'), sound=False) if rowcount > 0: self.vacuum() return result, rowcount
def download(download_type='video', background=True): download_type = download_type.lower() plugin_url = sys.listitem.getfilename() log_utils.log('ListItem.FileNameAndPath: |%s|' % plugin_url) if plugin_url: video_id = get_video_id(plugin_url) if video_id: if download_type == 'video': download_video(video_id, background=background) elif download_type == 'audio': download_audio(video_id, background=background) else: log_utils.log('Requested unknown download_type: |%s|' % download_type, log_utils.LOGERROR) else: kodi.notify(msg=kodi.i18n('not_found_video_id'), sound=False) else: log_utils.log('Plugin URL not found', log_utils.LOGERROR) kodi.notify(msg=kodi.i18n('not_found_plugin_url'), sound=False)
def export_m3u(export_path=None, from_list='history', ctype='video'): if export_path is None: export_path = kodi.get_setting('export_path') if not export_path: export_path = kodi.Dialog().browse(3, kodi.i18n('export_path'), 'files', '', False, False) kodi.set_setting('export_path', export_path) if export_path: m3u_name = kodi.get_keyboard(kodi.i18n('m3u_filename'), '') if m3u_name: if export_path.startswith('special://'): if not export_path.endswith('/'): export_path += '/' kodi.set_setting('export_path', export_path) m3u_file = kodi.translate_path(export_path + m3u_name) else: m3u_file = os.path.join(export_path, m3u_name) M3UUtils(m3u_file, from_list).export(ctype=ctype)
def download(download_type='video', background=True): download_type = download_type.lower() plugin_url = sys.listitem.getfilename() log_utils.log('ListItem.FileNameAndPath: |%s|' % plugin_url) if plugin_url: video_id = get_video_id(plugin_url) if video_id: if download_type == 'video': download_video(video_id, background=background) elif download_type == 'audio': download_audio(video_id, background=background) else: log_utils.log( 'Requested unknown download_type: |%s|' % download_type, log_utils.LOGERROR) else: kodi.notify(msg=kodi.i18n('not_found_video_id'), sound=False) else: log_utils.log('Plugin URL not found', log_utils.LOGERROR) kodi.notify(msg=kodi.i18n('not_found_plugin_url'), sound=False)
def download_audio(video_id, background=True): url = YOUTUBE_VIDEO_URL % video_id info = get_video_info(url) if info: stream = info._streams[0] ytdl_format = stream.get('ytdl_format', {}) formats = ytdl_format.get('formats', []) best_quality = 0 best_format = None if formats: for fmt in formats: fmt_desc = fmt.get('format', '') log_utils.log('format: |%s|' % fmt_desc) if 'audio only' in fmt_desc.lower(): format_id = fmt.get('format_id', '') asr = fmt.get('asr', '') tbr = fmt.get('tbr', '') abr = fmt.get('abr', '') ext = fmt.get('ext', '') log_utils.log('id: |%s| ext: |%s| asr: |%s| tbr: |%s| abr: |%s|' % (format_id, ext, asr, tbr, abr)) if 'm4a' in ext: tbr = int(fmt.get('tbr')) if tbr > best_quality: best_quality = tbr best_format = fmt log_utils.log('Updated best_format: |%s| id: |%s| ext: |%s| asr: |%s| tbr: |%s| abr: |%s|' % (fmt_desc, format_id, ext, asr, tbr, abr)) if best_format: stream['xbmc_url'] = best_format['url'] + '|' + urllib.urlencode({'User-Agent': USER_AGENT}) stream['url'] = best_format['url'] stream['ytdl_format'].update(best_format) stream['ytdl_format']['formats'] = [best_format] info._streams = [stream] log_utils.log('Downloading: |audio| video_id: |%s| Background: |%s|' % (video_id, str(background))) _download(info, background) else: log_utils.log('No audio-only stream formats found: |%s|' % video_id, log_utils.LOGERROR) kodi.notify(msg=kodi.i18n('no_audio_stream_formats'), sound=False) else: log_utils.log('No stream formats found: |%s|' % video_id, log_utils.LOGERROR) kodi.notify(msg=kodi.i18n('no_stream_formats'), sound=False)
def history_dialog(self, ctype): if self.size_limit() != 0: _queries = self.get() if len(_queries) > 0: queries = [] for item, content_type, label in _queries: if content_type == ctype: queries += [label] if len(queries) > 0: queries.insert(0, '[B]{0!s}[/B]'.format(kodi.i18n('new_'))) queries.insert( 1, '[B]{0!s}[/B]'.format(kodi.i18n('clear_history'))) index = kodi.Dialog().select(kodi.i18n('choose_playback'), queries) if index > -1: if index == 1: self.clear() return '' elif index > 1: return queries[index] else: return '' return self.get_input()
def play_remote(path, thumb='', title=''): rpc_client = HttpJSONRPC() command = {'jsonrpc': '2.0', 'id': 1, 'method': 'Player.GetActivePlayers'} response = rpc_client.execute_rpc(command) if 'error' in response: kodi.notify(kodi.get_name(), response['error'], duration=7000) return try: player_id = response['result'][0]['playerid'] except IndexError: player_id = None if player_id == 2: # stop picture player if active, it will block command = { 'jsonrpc': '2.0', 'id': 1, 'method': 'Player.Stop', 'params': { 'playerid': player_id } } response = rpc_client.execute_rpc(command) if 'error' in response: kodi.notify(kodi.get_name(), response['error'], duration=7000) return filename = kodi.get_plugin_url({ 'mode': MODES.PLAY, 'player': 'false', 'path': path, 'thumb': thumb, 'title': title }) command = { 'jsonrpc': '2.0', 'id': 1, 'method': 'Player.Open', 'params': { 'item': { 'file': filename } } } response = rpc_client.execute_rpc(command) if 'error' in response: kodi.notify(kodi.get_name(), response['error'], duration=7000) else: if 'No Response' not in response['result']: kodi.notify(kodi.get_name(), kodi.i18n('send_success'))
def history_directory(self, ctype): icon_path = kodi.get_icon() fanart_path = kodi.get_fanart() total_items = None if self.size_limit() != 0: _queries = self.get(include_ids=True) queries = [] for index, (row_id, item, content_type, label, thumbnail) in enumerate(_queries): if content_type == ctype: queries += [_queries[index]] if len(queries) > 0: total_items = len(queries) can_remote_send = HttpJSONRPC().has_connection_details resolve_locally = kodi.get_setting('resolve-locally') == 'true' for row_id, item, content_type, label, thumbnail in queries: play_path = { 'mode': MODES.PLAY, 'player': 'false', 'history': 'false', 'path': quote(item), 'thumb': quote(thumbnail) } if ctype == 'image': play_path = item menu_items = [(kodi.i18n('new_'), 'RunPlugin(%s)' % (kodi.get_plugin_url({ 'mode': MODES.NEW, 'player': 'true' }))), (kodi.i18n('manage'), 'Container.Update(%s)' % (kodi.get_plugin_url({ 'mode': MODES.MANAGE_MENU, 'row_id': row_id, 'title': quote(label) }))), (kodi.i18n('export'), 'Container.Update(%s)' % (kodi.get_plugin_url({ 'mode': MODES.EXPORT_MENU, 'row_id': row_id, 'ctype': content_type }))), (kodi.i18n('clear_history'), 'RunPlugin(%s)' % (kodi.get_plugin_url( { 'mode': MODES.CLEARHISTORY, 'ctype': content_type }))), (kodi.i18n('refresh'), 'Container.Refresh')] if can_remote_send: if resolve_locally: send_path = { 'mode': MODES.PLAY, 'path': quote(item), 'thumb': quote(thumbnail), 'title': quote(label), 'player': 'remote' } else: send_path = { 'mode': MODES.SENDREMOTE, 'path': quote(item), 'thumb': quote(thumbnail), 'title': quote(label) } menu_items.append((kodi.i18n('send_remote_playthis'), 'RunPlugin(%s)' % (kodi.get_plugin_url(send_path)))) is_folder = False thumb = icon_path if content_type == 'image': thumb = item if thumbnail: thumb = thumbnail info = {'title': label} if content_type == 'audio': info.update({'mediatype': 'song'}) elif content_type == 'video': info.update({'mediatype': 'video'}) elif content_type == 'executable': is_folder = True play_path['player'] = 'true' log_utils.log( 'Creating item |{2}|: path |{0}| content type |{1}|'. format(play_path, content_type, label), log_utils.LOGDEBUG) kodi.create_item(play_path, label, thumb=thumb, fanart=fanart_path, is_folder=is_folder, is_playable=True, total_items=total_items, menu_items=menu_items, content_type=content_type, info=info) if not total_items: menu_items = [(kodi.i18n('refresh'), 'Container.Refresh')] kodi.create_item({ 'mode': MODES.NEW, 'player': 'true' }, kodi.i18n('new_'), thumb=icon_path, fanart=fanart_path, is_folder=False, is_playable=False, menu_items=menu_items) kodi.end_of_directory(cache_to_disc=False)
def export_context(row_id, ctype): context_items = ['export_strm(row_id=row_id)', 'export_m3u(ctype=ctype)'] select_items = [kodi.i18n('export_to_strm'), kodi.i18n('export_list_m3u')] result = kodi.Dialog().select(kodi.i18n('export'), select_items) if result != -1: eval(context_items[result])