# -*- coding: utf-8 -*- try: import wingdbstub #import ptvsd #ptvsd.enable_attach("debug", address = ('127.0.0.1', 5678)) #ptvsd.wait_for_attach() print "[playstream] Remote debug started" except: print "[playstream] Remote debug skipped" pass import os, os.path,sys, glob, shutil, re import urllib, traceback try: import cPickle as pickle except: import pickle import pickle, threading from kodiswift import Plugin, ListItem, storage from kodiswift import xbmc, xbmcgui, xbmcplugin, xbmcvfs, xbmcaddon, CLI_MODE from resources.lib.content import ContentSources, util #from downloadqueue import DownloadQueue cur_directory = os.path.dirname(__file__) icon_folder = os.path.join(cur_directory, "resources", "picons") icong_url = xbmcaddon.Addon().getAddonInfo("path") + "/resources/picons/" sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),"resources","lib", "content", "sources")) plugin = Plugin() prefix = "plugin://%s/" % plugin.id #plugin.load_addon_settings() use_storage = plugin.get_setting("general_use_storage",bool) # TODO vajag nočekot vai nav labāk lietot pickle storage_ttl = plugin.get_setting("general_ttl",int) use_proxy = plugin.get_setting("general_proxy_use",bool) proxy_url = plugin.get_setting("general_proxy_url",str) playlist = plugin.get_setting("general_playlist",str) download_dir = plugin.get_setting("general_download_dir",str) view_mode = plugin.get_setting("general_view_mode",str) streams_file = plugin.get_setting("general_streams_file",str) streams_file_remote = plugin.get_setting("general_streams_file_remote",str) use_streams_file_remote = plugin.get_setting("general_use_streams_file_remote",bool) download_overwrite = plugin.get_setting("general_download_overwrite",bool) #storage_path = os.path.join(plugin.storage_path,"sources.p") if use_storage: try: storage = plugin.get_storage("playstream","pickle",ttl=30) except Exception as e: os.remove(os.path.join(plugin.storage_path, "playstream")) try: storage = plugin.get_storage("playstream", "pickle", ttl=30) except Exception as e: print "[playstream] error opening storage", plugin.storage_path print "Got Exception: ", str(e) import traceback traceback.print_exc() plugin.notify("Error opening permament storage", "Info", 10000, xbmcgui.NOTIFICATION_INFO) storage = None os.remove(os.path.join(plugin.storage_path, "playstream")) cur_directory = os.path.dirname(__file__) sources_directory = os.path.join(cur_directory,"resources","lib", "content", "sources") cfg_list = glob.glob(os.path.join(sources_directory,"*.cfg")) for cf in cfg_list: cf2 = os.path.join(plugin.storage_path,os.path.split(cf)[1]) if not os.path.exists(cf2): shutil.copyfile(cf,cf2) if use_storage and storage is not None and "sources" in storage: print "[playstream] Restore sources from storage" sources = storage["sources"] # if use_storage and os.path.exists(storage_path): #"sources" in storage: #sources = pickle.load(open(storage_path,"rb")) else: print "[playstream] Create sources objects" if use_streams_file_remote: try: sources = ContentSources.ContentSources(sources_directory, streams_file_remote) except Exception as e: try: sources = ContentSources.ContentSources(sources_directory, streams_file) plugin.notify("Remote streams file is not available, fallback to local") except Exception as e: plugin.notify(e.message) else: try: sources = ContentSources.ContentSources(sources_directory, streams_file) except Exception as e: plugin.notify(e.message) for source in sources.plugins: if not ("options" in dir(sources.plugins[source]) and sources.plugins[source].options): continue options = sources.plugins[source].options if not options: continue for option in options: key="%s_%s"%(source,option) if key in ("viaplay_device"): continue # exception list, value = plugin.get_setting(key) options[option] = value sources.plugins[source].options_write(options) @plugin.route(".+" ) def main(): global prefix plugin.set_content("movies") data = plugin.request.url.replace(prefix,"") data = urllib.unquote(data) sources.plugins["config"].read_streams() if not data: data = u"config::home" print "[playstream] processing data=%s"%data if sources.is_video(data): try: streams = sources.get_streams(data) except Exception,e: #xbmcgui.Dialog().ok("Error",unicode(e)) plugin.notify(unicode(e),"Error",10000, xbmcgui.NOTIFICATION_ERROR) traceback.print_exc() return plugin.set_resolved_url(None) if streams: return play_video(streams) else: plugin.notify("No streams found!","Error",10000,xbmcgui.NOTIFICATION_ERROR) return plugin.set_resolved_url(None) else: if "{0}" in data: q = plugin.keyboard(default=None, heading="Search for", hidden=False) if isinstance(q,str): q = q.decode("utf8") if isinstance(data,str): data = data.decode("utf8") data = data.format(q) try: items = get_list(data) except Exception,e: plugin.notify(unicode(e),"Error",10000,xbmcgui.NOTIFICATION_ERROR) traceback.print_exc() return [] if use_storage and storage is not None: print "[playstream] Save sources to storage" storage["sources"] = sources storage.sync() return plugin.finish(items, view_mode=get_view_mode(view_mode), update_listing=False, cache_to_disc=False) def get_list(data): if isinstance(data,unicode): data = data.encode("utf8") content = sources.get_content(data) print "[playstream] %s items returned"%len(content) items = [] i = 1 for item in content: if item[1] == "back": continue title = item[0].decode("utf8") if isinstance(item[0],str) else item[0] data2 = item[1].decode("utf8") if isinstance(item[1],str) else item[1] data2 = urllib.quote(data2, ":/") is_playable = True if sources.is_video(item[1]) else False img = item[2].decode("utf8") if isinstance(item[2],str) else item[2] desc = item[3].decode("utf8") if isinstance(item[3],str) else item[3] #print title.encode("utf8"),data2,img context_menu = [ #("Add to PlayStream playlist", # u'RunScript(special://home/addons/%s/context_menu.py,"playlist","%s","%s","%s","%s")' % ( # plugin.id, title, data2, playlist, proxy_url)), ("Add to PlayStream favorites", u'RunScript(special://home/addons/%s/context_menu.py,"add","%s","%s","%s","%s")'%( plugin.id, title, data2 ,img, desc)), ] if data.startswith("config::"): lst = data.split("::")[1] context_menu.extend([ ("Delete from PlayStream favorites", u'RunScript(special://home/addons/%s/context_menu.py,"delete","%s","%s")' % ( plugin.id, lst, i)), ("Move in PlayStream favorites", u'RunScript(special://home/addons/%s/context_menu.py,"move","%s","%s")' % ( plugin.id, lst, i)), ]) context_menu.extend([ # "ActivateWindow(,'plugin:///',return)" ("* Download jobs list *", u'RunScript(special://home/addons/%s/queue_management.py,"%s","list")' % (plugin.id, plugin.handle)), #("* Download jobs list *", u'ActivateWindow(10025,"plugin://plugin.video.playstream/downloads::list")'), #plugin.id #("Active download jobs", u'RunPlugin(plugin://plugin.video.playstream/downloads::list)'), #plugin.id ]) if is_playable: context_menu.extend([ ("Download video to default folder", u'RunScript(special://home/addons/%s/context_download.py,"download","%s","%s","%s")' % ( plugin.id, title, data2, download_dir)), ("Download video, ask folder", u'RunScript(special://home/addons/%s/context_download.py,"download2","%s","%s","%s")' % ( plugin.id, title, data2, download_dir)), ("Download video to subfolder, ask parent folder", u'RunScript(special://home/addons/%s/context_download.py,"download3","%s","%s","%s")' % ( plugin.id, title, data2, download_dir)), ]) else: context_menu.extend([ ("Download list to default folder", u'RunScript(special://home/addons/%s/context_download.py,"download","%s","%s","%s")' % ( plugin.id, title, data2, download_dir)), ("Download list, ask folder", u'RunScript(special://home/addons/%s/context_download.py,"download2","%s","%s","%s")' % ( plugin.id, title, data2, download_dir)), ]) item = { "label": title, "path": prefix+data2, "thumbnail":thumb_data(img, is_playable), #"poster":thumb_data(img, is_playable) , "icon":thumb_data(img, is_playable) , "info":{"plot":desc}, "is_playable":is_playable, "context_menu": context_menu, } if view_mode == "Poster": item["poster"] = thumb_data(img, is_playable) items.append(item) i += 1 return items def play_video(streams): if len(streams)>1: slist = [] for s in streams: name2 = "%s,%s" % (s["quality"],s["lang"]) if s["lang"] else s["quality"] slist.append("[%s] %s"%(name2, s["name"])) res = xbmcgui.Dialog().select("Select stream",slist) if not CLI_MODE else 0 #res = xbmcgui.Dialog().contextmenu(slist) if not CLI_MODE else 0 stream = streams[res] else: stream = streams[0] subfiles = [] #stream = util.stream_chamge(stream) if use_proxy: if "resolver" in stream and stream["resolver"] in ("hqq","filmas") or \ "surl" in stream and re.search(r"http*://(hqq|goo\.gl)",stream["surl"]) or \ "lattelecom.tv/mobile-vod/" in stream["url"]: # TODO #re.search(r"http*://.+?lattelecom\.tv/.+?auth_token=[^=]+=", stream["url"]): stream["url"] = util.streamproxy_encode(stream["url"],stream["headers"],proxy_url) stream["headers"] = {} if stream["headers"]: hh = [] for k in stream["headers"]: h = "%s=%s"%(k,urllib.quote(stream["headers"][k])) hh.append(h) hh = "&".join(hh) stream["url"] = stream["url"] +"|"+hh print "[playstream] play_video ", stream["url"] if "subs" in stream and stream["subs"]: for sub in stream["subs"]: suburl = sub["url"] subs = util.Captions(suburl) srt = subs.get_srt() #subfile = plugin.temp_fn("subtitles.srt") subfile = os.path.join(os.path.dirname(__file__),sub["lang"]+".srt") f = open(subfile, "w") f.write(srt) f.close() subfiles.append(subfile) item = ListItem(label=stream["name"], thumbnail=thumb_data(stream["img"], True), path=stream["url"]) item.set_info("video",{"plot":stream["desc"]}) item.set_is_playable(True) return plugin.set_resolved_url(item,subfiles) #return plugin.play_video(item) def thumb_data(img, video=False): default = "video.png" if video else "folder.png" if img in ("default", ""): img = default if not img.startswith("http"): img = icong_url + img return img def get_view_mode(vm): modes = { "skin.estuary": { "None": None, "List": 50, "Poster": 51, "IconWall":52 , "Shift": 53, "InfoWall": 54, "WideList": 55, "Wall": 500, "Banner": 501, "FanArt": 502 }, "skin.estuary.is": { "None": None, "List": 50, "Poster": 51, "IconWall":52 , "Shift": 53, "InfoWall": 54, "WideList": 55, "Wall": 500, "Banner": 501, "FanArt": 502 }, "skin.estuary.isl": { "None": None, "List": 50, "Poster": 51, "IconWall":52 , "Shift": 53, "InfoWall": 54, "WideList": 55, "Wall": 500, "Banner": 501, "FanArt": 502 }, } skin = xbmc.getSkinDir() if skin in modes and vm in modes[skin]: view_mode = modes[skin][vm] else: view_mode = 50 return view_mode if __name__ == '__main__': if CLI_MODE: from kodiswift.cli.cli import main as start start() else: plugin.run() if use_storage and storage is not None: print "[playstream] Save sources to storage" storage["sources"] = sources storage.sync() print "Save sources to storage" #pickle.dump(sources,open(storage_path,"wb"),pickle.HIGHEST_PROTOCOL)