123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- import sys, os, urllib2, re, requests
- #CLI_MODE = True
- from kodiswift import xbmc, xbmcgui, CLI_MODE
- from kodiswift import Plugin, storage
- from resources.lib.content import util, ContentSources
- #from resources.lib.content import Downloader
- #from twisted.web import client
- #from twisted.internet import reactor, defer
-
- #plugin = Plugin()
- #plugin.load_addon_settings()
- #playlist = plugin.get_setting("general_playlist",str)
- #proxy_url = plugin.get_setting("general_proxy_url",str)
-
- cunicode = lambda s: s.decode("utf8") if isinstance(s, str) else s
- cstr = lambda s: s.encode("utf8") if isinstance(s, unicode) else s
-
- cmd = sys.argv[1]
- title = sys.argv[2]
- data = sys.argv[3]
- download_dir = sys.argv[4]
-
- cur_directory = os.path.dirname(__file__)
- sources_directory = os.path.join(cur_directory,"resources","lib", "content", "sources")
- sources = ContentSources.ContentSources(sources_directory)
-
- def main():
- if not sources.is_video(data):
- print "It is not video link"
- notify("It is not video link")
- sys.exit(1)
-
- streams = sources.get_streams(data)
-
- if not CLI_MODE:
- ret = 0
- #ret = xbmcgui.Dialog().select("Select stream",streams) # TODO
- else:
- ret = 0
- stream = streams[ret]
- #output = stream["name"].replace("\\"," ").replace(":"," ").replace("|"," ")
- output = re.sub("[\\/\n\r\t,:\?\|'~\.]","_",title)
- if isinstance(output, str):
- output = output.decode("utf8")
-
- for sub in stream["subs"]:
- suburl = sub["url"]
- slang = "_" + sub["lang"] if sub["lang"] else ""
- download_sub(suburl, output+slang)
-
- if "nfo" in stream and stream["nfo"]:
- nfofile = os.path.join(download_dir, output+".nfo")
- with open(nfofile,"w") as f:
- nfo_txt = util.nfo2xml(stream["nfo"])
- f.write(nfo_txt)
-
- download_video(stream["url"], os.path.join(download_dir, output), stream["headers"])
-
- #d = Downloader.download_video(stream["url"], os.path.join(download_dir, output), stream["headers"])
- #reactor.run()
-
-
- #xbmcgui.Dialog().ok("Info","Start download")
-
- #mode = "a" if os.path.exists("context_menu.log") else "w"
- #with open("context_menu.log", mode) as f:
- # f.write("%s %s %s %s", sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
-
-
- def download_video(url,output,headers=None):
- #output = stream["name"].replace("\\"," ").replace(":"," ").replace("|"," ")
- if not headers:
- headers = {"user-agent":"Enigma2"}
- try:
- h = get_header(url,headers=headers)
- mtype = h.get("content-type")
- ext,stream_type = get_ext(mtype)
- except Exception as e:
- ext,stream_type = (".ts","hls")
- output = output+ext
- if stream_type == "hls":
- download_hls(url, output, headers=headers)
- else:
- download_file(url, output, headers=headers)
-
-
- def download_hls(url, title, download_dir="", headers=None, overwrite=True, limit=None):
- UA = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0"
- if not headers:
- headers = {"User-Agent" : UA}
- key = headers["key"] if "key" in headers else ""
- # if not "User-Agent" in headers:
- # headers["User-Agent"] = UA
- tsname = os.path.join(download_dir,title)
-
- notify("Download started - %s" % title)
- print "Start download"
- print url
- try:
- r = requests.get(url,headers=headers)
- except Exception as e:
- raise Exception("Cannot open manifsest file - %s"%url)
- if not r.content.startswith("#EXTM3U"):
- raise Exception("Not valid manifest file - %s" % url)
- streams = re.findall(r"#EXT-X-STREAM-INF:.*?BANDWIDTH=(\d+).*?\n(.+?)$", r.content, re.IGNORECASE | re.MULTILINE)
- i = 0
- while streams:
- if i > 4: break
- sorted(streams, key=lambda item: int(item[0]), reverse=True)
- base_url = "/".join(url.split("?")[0].split("/")[:-1])+"/"
- url = streams[0][1]
- if not url.startswith("http"):
- url = base_url + url
- print url
- try:
- r = requests.get(url, headers=headers)
- except Exception as e:
- raise Exception("Cannot open manifsest file - %s"%url)
- i += 1
- streams = re.findall(r"#EXT-X-STREAM-INF:.*?BANDWIDTH=(\d+).*?\n(.+?)$", r.content, re.IGNORECASE | re.MULTILINE)
- ts_list = re.findall(r"#EXTINF:([\d\.]+),.*?\n(.+?)$", r.content, re.IGNORECASE | re.MULTILINE)
- base_url = "/".join(url.split("/")[:-1])+"/"
-
- if not len(ts_list):
- raise Exception("Cannot read fragment list in manifsest file - %s"%url)
-
- ts_num = 0
- type = "vod" if "#EXT-X-ENDLIST" in r.content else "live"
- currentbytes = 0.0
- totalbytes = -1
- currenttime = 0.0
- totaltime = sum(map(float,zip(*ts_list)[0]))
- #ts_file = open(outputfile, "wb")
-
- if isinstance(tsname, str):
- tsname = tsname.decode("utf8")
- tsfile = open(tsname,"wb")
- for ts in ts_list:
- url2 = ts[1]
- #print "Downloading ", url2
- #fname = os.path.join(download_dir,url2.split("/")[-1])
- if not url2.startswith("http"):
- url2 = base_url + url2
-
- r = requests.get(url2, headers=headers, verify=False)
- content = r.content
- if key:
- from Crypto.Cipher import AES
- key2 = binascii.a2b_hex(key)
- iv = content[:16]
- d = AES.new(key2, AES.MODE_CBC, iv)
- content = d.decrypt(content[16:])
- #with open(fname,"wb") as f:
- #f.write(content)
- tsfile.write(content)
-
- content_length = len(content)
- currentbytes += content_length
- currenttime += float(ts_list[ts_num][0])
- totalbytes = currentbytes * totaltime / currenttime
- ts_num += 1
- #print "Fragment %s downloaded (%s)"%(self.ts_num,len(content))
- progress = float(currentbytes)/float(totalbytes)*100
- print "%.1f%% (%i/%i)"%(progress,currentbytes,totalbytes)
-
- if type == "vod":
- if ts_num >= len(ts_list) or (limit and currenttime>limit):
- break
- else:
- if limit and currenttime>limit: # TODO
- break
-
- print "Finished"
- notify("Download finished - %s" % title)
-
- tsfile.close()
-
-
- def download_file(url, title, download_dir="", headers=None, overwrite=True, limit=None):
- UA = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0"
- if not headers:
- headers = {"User-Agent" : UA}
- key = headers["key"] if "key" in headers else ""
- # if not "User-Agent" in headers:
- # headers["User-Agent"] = UA
- fname = os.path.join(download_dir,title)
- if isinstance(fname, str):
- fname = fname.decode("utf8")
-
- notify("Download started - %s" % title)
- print "Start download"
- print url
- try:
- r = requests.get(url,headers=headers, stream=True)
- except Exception as e:
- raise Exception("Cannot open url - %s"%url)
- currentbytes = 0.0
- totalbytes = int(r.headers["content-length"])
-
- with open(fname, 'wb') as fd:
- for chunk in r.iter_content(chunk_size=1024*1024):
- fd.write(chunk)
- currentbytes += len(chunk)
- progress = float(currentbytes)/float(totalbytes)*100
- print "%.1f%% (%i/%i)"%(progress,currentbytes,totalbytes)
-
- print "Finished"
- notify("Download finished - %s" % title)
-
- def download_sub(suburl, output):
- try:
- subs = urllib2.urlopen(suburl).read()
- except:
- subs = None
- if subs:
- if ".xml" in suburl:
- subs = util.ttaf2srt(subs)
- subext = ".srt"
- elif ".vtt" in suburl:
- subext = ".vtt"
- elif ".srt" in suburl:
- subext = ".srt"
- else:
- subext = ""
- if subext:
- subfile = cunicode(os.path.join(download_dir, output+subext))
- with open(subfile,"w") as f:
- f.write(subs)
- else:
- print "\n Error downloading subtitle %s"%suburl
-
-
-
- def get_header(url,headers=None):
- r = requests.head(url,headers=headers)
- return r.headers
-
- def get_ext(mtype):
- stype = "http"
- if mtype in ("vnd.apple.mpegURL","application/x-mpegURL",'application/x-mpegurl',"application/vnd.apple.mpegurl"):
- return ".ts","hls"
- elif mtype in ("application/dash+xml"):
- return ".ts","dash" # TODO dash stream type could be different !
- elif mtype in ("video/mp4"):
- return ".mp4","http"
- elif mtype in ("video/MP2T","video/mp2t"):
- return ".ts","http"
- elif mtype in ("video/x-flv"):
- return ".flv","http"
- elif mtype in ("video/quicktime"):
- return ".mov","http"
- elif mtype in ("video/x-msvideo"):
- return ".avi","http"
- elif mtype in ("video/x-ms-wmv"):
- return ".wmv","http"
- elif mtype in ("video/x-matroska"):
- return ".mkv","http"
- else:
- return ".mp4","http"
-
-
- def notify(text, title="Info", time=10000):
- if isinstance(text, unicode):
- text = text.encode("utf8")
- #xbmc.executebuiltin('Notification(Hello World,This is a simple example of notifications,5000,/script.hellow.world.png)')
- xbmc.executebuiltin('Notification(%s, %s, %d, %s)'%("Info", text, time, xbmcgui.NOTIFICATION_INFO))
-
- if __name__ == '__main__':
- main()
|