#!/usr/bin/python # -*- coding: utf-8 -*- '''Author is caasiu <caasiu@outlook.com> && source code is under GPLv3''' import xbmc, xbmcgui, xbmcaddon, xbmcvfs import os, sys, re, json __addon_id__= 'plugin.video.bdyun' plugin_path = xbmcaddon.Addon(__addon_id__).getAddonInfo('path') lib_path = os.path.join(plugin_path, 'resources', 'modules') sys.path.append(lib_path) from resources.modules import get_auth, pcs, utils, myplayer from xbmcswift2 import Plugin, actions plugin = Plugin() dialog = xbmcgui.Dialog() @plugin.route('/') def main_menu(): user_info = get_user_info() if user_info is None: items = [{ 'label': u'登入', 'path': plugin.url_for('login_dialog'), 'is_playable': False }] else: items = [{ 'label': u'## 管理当前帐号: %s' %user_info['username'], 'path': plugin.url_for('accout_setting'), 'is_playable': False, },{ 'label': u'## 搜索文件(文件夹/视频/音乐)', 'path': plugin.url_for('search'), 'is_playable': False },{ 'label': u'## 刷新', 'path': plugin.url_for('refresh'), 'is_playable': False }] for loopTime in range(0, 5): validation = pcs.token_validation(user_info['cookie'], user_info['tokens']) if validation: try: homemenu = plugin.get_storage('homemenu') if homemenu.get('item_list'): item_list = homemenu.get('item_list') else: item_list = menu_cache(user_info['cookie'], user_info['tokens']) items.extend(item_list) break except (KeyError, TypeError, UnicodeError): dialog.ok('Error', u'请求参数错误', u'请点击登出再重新登录') items.extend([{'label': u'登出 && 重新登录', 'path': plugin.url_for('clear_cache')}]) break else: cookie,tokens = get_auth.run(user_info['username'], user_info['password']) if tokens['bdstoken']: save_user_info(user_info['username'], user_info['password'], cookie, tokens) else: items.extend([{'label': u'重新登录', 'path': plugin.url_for('relogin')}]) break if loopTime == 4: dialog.ok('Error', u'未知错误', u'请重新登录') items.extend([{'label': u'重新登录', 'path': plugin.url_for('relogin')}]) return plugin.finish(items, update_listing=True) @plugin.route('/login_dialog/') @plugin.route('/login_dialog/', name='relogin') def login_dialog(): username = dialog.input(u'用户名:', type=xbmcgui.INPUT_ALPHANUM) password = dialog.input(u'密码:', type=xbmcgui.INPUT_ALPHANUM, option=xbmcgui.ALPHANUM_HIDE_INPUT) if username and password: cookie,tokens = get_auth.run(username,password) if tokens: save_user_info(username,password,cookie,tokens) homemenu = plugin.get_storage('homemenu') homemenu.clear() dialog.ok('',u'登录成功', u'点击返回首页并耐心等待') items = [{'label': u'<< 返回首页', 'path': plugin.url_for('main_menu')}] return plugin.finish(items, update_listing=True) else: dialog.ok('Error',u'用户名或密码不能为空') return None @plugin.route('/accout_setting/') def accout_setting(): user_info = get_user_info() items = [{ 'label': u'<< 返回首页', 'path': plugin.url_for('main_menu') },{ 'label': u'登出和清除缓存', 'path': plugin.url_for('clear_cache'), 'is_playable': False },{ 'label': u'重新登录/切换帐号', 'path': plugin.url_for('relogin'), 'is_playable': False },{ 'label': u'插件设置', 'path': plugin.url_for('setting'), 'is_playable': False }] if user_info: return plugin.finish(items, update_listing=True) else: return @plugin.route('/setting/') def setting(): plugin.open_settings() @plugin.route('/accout_setting/clear_cache/') def clear_cache(): info = plugin.get_storage('info') homemenu = plugin.get_storage('homemenu') pcs_info = plugin.get_storage('pcs_info') info.clear() homemenu.clear() pcs_info.clear() dialog.notification('', u'清除完毕', xbmcgui.NOTIFICATION_INFO, 3000) xbmc.executebuiltin('Container.Refresh') return @plugin.route('/search/') def search(): user_info = get_user_info() user_cookie = user_info['cookie'] user_tokens = user_info['tokens'] key = dialog.input(heading=u'输入文件名/关键词') if key: s = pcs.search(user_cookie, user_tokens, key) items = [] if len(s['list']) == 1: for result in s['list']: if result['isdir'] == 1: item = { 'label': result['server_filename'], 'path': plugin.url_for('directory', path=result['path'].encode('utf-8')), 'is_playable': False } items.append(item) elif result['category'] == 1: if 'thumbs' in result and 'url2' in result['thumbs']: ThumbPath = result['thumbs']['url2'] item = { 'label': result['server_filename'], 'path': plugin.url_for('quality', filepath=result['path'].encode('utf-8')), 'is_playable': False, 'icon': ThumbPath, } else: item = { 'label': result['server_filename'], 'path': plugin.url_for('quality', filepath=result['path'].encode('utf-8')), 'is_playable': False, } items.append(item) elif result['category'] == 2: item = { 'label': result['server_filename'], 'path': plugin.url_for('play_music', filepath=result['path'].encode('utf-8')), 'is_playable': False, } items.append(item) if items: return plugin.finish(items) else: dialog.ok('',u'搜素的文件不属于文件夹、视频或音频') elif s['list']: for result in s['list']: if result['isdir'] == 1: item = { 'label': result['path'], 'path': plugin.url_for('directory', path=result['path'].encode('utf-8')), 'is_playable': False } items.insert(0, item) elif result['category'] == 1: if 'thumbs' in result and 'url2' in result['thumbs']: ThumbPath = result['thumbs']['url2'] item = { 'label': result['path'], 'path': plugin.url_for('quality', filepath=result['path'].encode('utf-8')), 'is_playable': False, 'icon': ThumbPath, } else: item = { 'label': result['path'], 'path': plugin.url_for('quality', filepath=result['path'].encode('utf-8')), 'is_playable': False, } items.append(item) elif result['category'] == 2: item = { 'label': result['path'], 'path': plugin.url_for('play_music', filepath=result['path'].encode('utf-8')), 'is_playable': False, } items.append(item) if items: return plugin.finish(items) else: dialog.ok('',u'搜素的文件不属于文件夹、视频或音频') else: dialog.ok('',u'没有找到文件') return None return @plugin.route('/directory/<path>') def directory(path): if isinstance(path, str): path = path.decode('utf-8') user_info = get_user_info() user_cookie = user_info['cookie'] user_tokens = user_info['tokens'] dir_files = pcs.list_dir_all(user_info['cookie'], user_info['tokens'], path) item_list = MakeList(dir_files) previous_path = os.path.dirname(path).encode('utf-8') if previous_path == '/': item_list.insert(0,{ 'label': u'<< 返回首页', 'path': plugin.url_for('main_menu') }) else: item_list.insert(0,{ 'label': u'<< 返回上一目录', 'path': plugin.url_for('directory', path=previous_path), }) item_list.insert(0,{ 'label': u'## 当前目录: %s' % path, 'path': plugin.url_for('refresh') }) return plugin.finish(item_list, update_listing=True) @plugin.route('/refresh/') def refresh(): homemenu = plugin.get_storage('homemenu') homemenu.clear() xbmc.executebuiltin('Container.Refresh') @plugin.route('/quality/<filepath>') def quality(filepath): if plugin.get_setting('show_stream_type', bool): stream_type = ['M3U8_AUTO_720', 'NONE'] choice = dialog.select(u'请选择画质', [u'流畅',u'原画']) if choice < 0: return elif choice == 0: stream = stream_type[choice] elif choice == 1: stream = False elif plugin.get_setting('stream_type', str) == 'NONE': stream = False else: stream = plugin.get_setting('stream_type', str) if isinstance(filepath, str): filepath = filepath.decode('utf-8') video_path = playlist_path(filepath, stream) name = os.path.basename(filepath) listitem = xbmcgui.ListItem(name) listitem.setInfo(type='Video', infoLabels={'Title': name}) if video_path: xbmc.Player().play(video_path, listitem, windowed=False) @plugin.route('/play_music/<filepath>') def play_music(filepath): if isinstance(filepath, str): filepath = filepath.decode('utf-8') url = playlist_path(filepath, stream=False) name = os.path.basename(filepath) listitem = xbmcgui.ListItem(name) listitem.setInfo(type='Music', infoLabels={'Title': name}) if url: xbmc.Player().play(url, listitem, windowed=False) # cache the output of content menu def menu_cache(cookie, tokens): pcs_files = pcs.list_dir_all(cookie, tokens, path='/') if pcs_files: item_list = MakeList(pcs_files) else: return [{'label': u'请点击一下「刷新」', 'path': plugin.url_for('refresh')}] homemenu = plugin.get_storage('homemenu', TTL=60) homemenu['item_list'] = item_list return item_list def get_user_info(): info = plugin.get_storage('info') user_info = info.get('user_info') return user_info def save_user_info(username, password, cookie, tokens): info = plugin.get_storage('info') user_info = info.setdefault('user_info',{}) user_info['username'] = username user_info['password'] = password user_info['cookie'] = cookie user_info['tokens'] = tokens info.sync() def MakeList(pcs_files): item_list = [] ContextMenu = [ ('搜索', actions.background(plugin.url_for('search'))), ('刷新', actions.background(plugin.url_for('refresh'))), ('登出', actions.background(plugin.url_for('clear_cache'))), ] for result in pcs_files: if result['isdir'] == 1: item = { 'label': result['server_filename'], 'path': plugin.url_for('directory', path=result['path'].encode('utf-8')), 'is_playable': False, 'context_menu': ContextMenu, } item_list.append(item) elif result['category'] == 1: if 'thumbs' in result and 'url2' in result['thumbs']: ThumbPath = result['thumbs']['url2'] item = { 'label': result['server_filename'], 'path': plugin.url_for('quality', filepath=result['path'].encode('utf-8')), 'is_playable': False, 'icon': ThumbPath, 'context_menu': ContextMenu, } else: item = { 'label': result['server_filename'], 'path': plugin.url_for('quality', filepath=result['path'].encode('utf-8')), 'is_playable': False, 'context_menu': ContextMenu, } item_list.append(item) elif result['category'] == 2: item = { 'label': result['server_filename'], 'path': plugin.url_for('play_music', filepath=result['path'].encode('utf-8')), 'is_playable': False, 'context_menu': ContextMenu, } item_list.append(item) return item_list def playlist_path(pcs_file_path, stream): user_info = get_user_info() user_name = user_info['username'] user_cookie = user_info['cookie'] user_tokens = user_info['tokens'] if stream: playlist_data = pcs.get_streaming_playlist(user_cookie, pcs_file_path, stream) if playlist_data: raw_dir = os.path.dirname(pcs_file_path) m = re.search('\/(.*)', raw_dir) dirname = m.group(1) basename = os.path.basename(pcs_file_path) r = re.search('(.*)\.(.*)$', basename) filename = ''.join([r.group(1), stream, '.m3u8']) dirpath = os.path.join(utils.data_dir(), user_name, dirname) if not xbmcvfs.exists(dirpath): xbmcvfs.mkdirs(dirpath) filepath = os.path.join(dirpath, filename) tmpFile = xbmcvfs.File(filepath, 'w') tmpFile.write(bytearray(playlist_data, 'utf-8')) return filepath else: dialog.notification('', u'无法打开视频', xbmcgui.NOTIFICATION_INFO, 4000) return None else: url = pcs.stream_download(user_cookie, user_tokens, pcs_file_path) if url: return url else: dialog.notification('', u'无法打开原画,请尝试流畅模式', xbmcgui.NOTIFICATION_INFO, 4000) return None if __name__ == '__main__': plugin.run()