Ivars 7 年 前
コミット
ee3876f54b
共有19 個のファイルを変更した761 個の追加559 個の削除を含む
  1. 12
    5
      ContentSources.py
  2. 98
    59
      PlayStream.py
  3. 535
    437
      PlayStream.wpr
  4. 5
    1
      changelog.md
  5. 1
    1
      imake.bat
  6. 68
    35
      playstreamproxy.py
  7. 3
    1
      plugin.py
  8. 1
    5
      resolver.py
  9. 3
    1
      resolvers/hdgo.py
  10. バイナリ
      resolvers/hdgo.pyc
  11. 2
    0
      resolvers/hqqresolver.py
  12. バイナリ
      resolvers/hqqresolver.pyc
  13. 3
    1
      resolvers/kapnob.py
  14. バイナリ
      resolvers/kapnob.pyc
  15. 3
    1
      resolvers/kodik.py
  16. バイナリ
      resolvers/kodik.pyc
  17. 8
    6
      resolvers/openload3.py
  18. バイナリ
      resolvers/openload3.pyc
  19. 19
    6
      util.py

+ 12
- 5
ContentSources.py ファイルの表示

@@ -7,7 +7,7 @@
7 7
 #
8 8
 
9 9
 import sys,os,re
10
-import glob
10
+import glob, traceback
11 11
 sys.path.insert(0,os.path.dirname(os.path.abspath(__file__)))
12 12
 from  sources.SourceBase import stream_type
13 13
 import util
@@ -105,6 +105,12 @@ class ContentSources(object):
105 105
                 for k in s:
106 106
                     if isinstance(s[k],unicode):
107 107
                         s[k] = s[k].encode("utf8")
108
+                if not "resolver" in s:
109
+                    s["resolver"] = stream
110
+                if not "surl" in s or not s["surl"]:
111
+                    s["surl"] = data
112
+                if not "nfo" in s:
113
+                    s["nfo"]={"tvshow":{"title":s["title"],"thumb":s["img"],"plot":s["desc"]}}
108 114
             return streams
109 115
         else:
110 116
             return []
@@ -155,7 +161,7 @@ if __name__ == "__main__":
155 161
     while True:
156 162
         print
157 163
         for i,item in enumerate(content):
158
-            s = "%i: %s - %s %s %s "%(i+1,item[0],item[1],item[2],item[3])
164
+            s = "%i: %s - %s %s %s "%(i,item[0],item[1],item[2],item[3])
159 165
             print s #.encode(sys.stdout.encoding,"replace")
160 166
 
161 167
         while True:
@@ -170,7 +176,7 @@ if __name__ == "__main__":
170 176
             except:
171 177
                 print "Not number!"
172 178
         if exit_loop: break
173
-        cur2 = content[n-1]
179
+        cur2 = content[n]
174 180
 
175 181
         data0 = cur2[1].split("::")[1] if "::" in cur2[1] else cur2[1]
176 182
         if not data0:
@@ -188,7 +194,8 @@ if __name__ == "__main__":
188 194
                 try:
189 195
                     streams = sources.get_streams(cur2[1])
190 196
                 except Exception as e:
191
-                    print str(e)
197
+                    print unicode(e)
198
+                    traceback.print_exc()
192 199
                     streams = []
193 200
             if streams:
194 201
                 util.play_video(streams)
@@ -208,7 +215,7 @@ if __name__ == "__main__":
208 215
         try:
209 216
             content = sources.get_content(cur[1])
210 217
         except Exception as e:
211
-            print str(e)
218
+            print unicode(e)
212 219
             raw_input("Continue?")
213 220
 
214 221
 

+ 98
- 59
PlayStream.py ファイルの表示

@@ -1,7 +1,6 @@
1 1
 #!/usr/bin/env python
2 2
 # coding=utf8
3 3
 #
4
-#
5 4
 # This file is part of PlayStream - enigma2 plugin to play video streams from various sources
6 5
 # Copyright (c) 2016 ivars777 (ivars777@gmail.com)
7 6
 # Distributed under the GNU GPL v3. For full terms see http://www.gnu.org/licenses/gpl-3.0.en.html
@@ -12,51 +11,47 @@ import os,time,sys,os,os.path
12 11
 import datetime,re
13 12
 import urllib2
14 13
 
14
+from Plugins.Plugin import PluginDescriptor
15 15
 from enigma import ePicLoad, eServiceReference, eTimer, getDesktop
16
-from Components.ActionMap import ActionMap, HelpableActionMap
16
+from Screens.Screen import Screen
17 17
 from Screens.InfoBarGenerics import InfoBarShowHide
18
+from Screens.InfoBar import MoviePlayer
19
+from Screens.MessageBox import MessageBox
20
+from Screens.LocationBox import LocationBox
21
+from Screens.ChoiceBox import ChoiceBox
22
+from Screens.VirtualKeyBoard import VirtualKeyBoard
23
+#from Screens.InputBox import InputBox
18 24
 from Components.AVSwitch import AVSwitch
25
+from Components.ActionMap import ActionMap, HelpableActionMap
19 26
 from Components.Label import Label
27
+from Components.Input import Input
20 28
 from Components.MenuList import MenuList
21 29
 from Components.Pixmap import Pixmap
22 30
 from Components.Sources.List import List
23 31
 from Components.Sources.StaticText import StaticText
24 32
 from Components.Button import Button
25
-from Plugins.Plugin import PluginDescriptor
26
-from Screens.InfoBar import MoviePlayer
27
-from Screens.MessageBox import MessageBox
33
+from Components.Task import job_manager
34
+from Components.config import config, ConfigSubsection, ConfigText, ConfigInteger, ConfigLocations, ConfigDirectory, ConfigSet, ConfigYesNo, ConfigSelection, getConfigListEntry, ConfigSelectionNumber, ConfigNumber
35
+from Components.ConfigList import ConfigListScreen
28 36
 from Tools import Notifications
29
-from Screens.LocationBox import LocationBox
30
-#from Screens.InputBox import InputBox
31
-from Screens.ChoiceBox import ChoiceBox
32
-from Screens.VirtualKeyBoard import VirtualKeyBoard
33
-from Components.Input import Input
34
-from Screens.Screen import Screen
35 37
 from Tools.BoundFunction import boundFunction
36 38
 from Tools.Directories import resolveFilename, SCOPE_PLUGINS
37 39
 from Tools.LoadPixmap import LoadPixmap
38 40
 from twisted.web.client import downloadPage,defer,reactor
39
-from Components.Task import job_manager
40
-from Components.config import config, ConfigSubsection, ConfigText, ConfigInteger, ConfigLocations, ConfigDirectory, ConfigSet, ConfigYesNo, ConfigSelection, getConfigListEntry, ConfigSelectionNumber
41
-
42 41
 
43 42
 import ContentSources
44 43
 import util
45 44
 from VideoDownload import downloadJob, HLSDownloadJob,VideoDownloadList
46 45
 #import enigma2_api
47
-e2 = None
48 46
 
47
+e2 = None
49 48
 ##########################################################################
50
-from Components.config import config, ConfigSubsection, ConfigYesNo, getConfigListEntry, \
51
-     ConfigSelection, ConfigNumber, ConfigDirectory,ConfigText
52
-from Components.ConfigList import ConfigListScreen
53
-from Screens.LocationBox import LocationBox
54
-
55 49
 config.plugins.playstream = ConfigSubsection()
56 50
 config.plugins.playstream.locations = ConfigLocations(default=["/media/hdd/movie/"])
57 51
 config.plugins.playstream.download_dir = ConfigDirectory(default="/media/hdd/movie/")
58 52
 config.plugins.playstream.tmp_dir = ConfigDirectory(default="/tmp/playstream/")
59 53
 config.plugins.playstream.streamproxy_start = ConfigYesNo(default = True)
54
+config.plugins.playstream.overwrite_download = ConfigYesNo(default = False)
60 55
 #config.plugins.playstream.size = ConfigSelection({"400x240":"400x240","220x132":"220x132","100x60":"100x60"}, default="220x132")
61 56
 config.plugins.playstream.clear_tmp = ConfigYesNo(default = True)
62 57
 
@@ -83,9 +78,11 @@ class ConfigScreen(ConfigListScreen,Screen):
83 78
         cfg = config.plugins.playstream
84 79
         self.list = [
85 80
             getConfigListEntry(_("Download folder"), cfg.download_dir),
81
+            getConfigListEntry(_("Overwrite download video"), cfg.overwrite_download),
86 82
             getConfigListEntry(_("TMP folder"), cfg.tmp_dir),
87 83
             getConfigListEntry(_("Clear tmp folder on exit"), cfg.clear_tmp),
88 84
             getConfigListEntry(_("Start playstreamproxy"), cfg.streamproxy_start),
85
+
89 86
         ]
90 87
         ConfigListScreen.__init__(self, self.list, session = self.session)
91 88
         self["key_red"] = Button(_("Cancel"))
@@ -110,14 +107,14 @@ class ConfigScreen(ConfigListScreen,Screen):
110 107
     def ok(self):
111 108
         if self["config"].getCurrent()[1] == config.plugins.playstream.download_dir:
112 109
             folder = config.plugins.playstream.download_dir.value
113
-            #self.session.openWithCallback(self.select_download_dir, LocationBox,"Select Folder")
114
-            self.session.openWithCallback(self.select_download_dir, LocationBox,"Select download folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
110
+            #self.session.openWithCallback(self.cb_download_dir, LocationBox,"Select Folder")
111
+            self.session.openWithCallback(self.cb_download_dir, LocationBox,"Select download folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
115 112
         elif self["config"].getCurrent()[1] == config.plugins.playstream.tmp_dir:
116 113
             self.session.openWithCallback(self.select_tmp_dir, LocationBox,"Select tmp folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
117 114
         else:
118 115
             self.save()
119 116
 
120
-    def select_download_dir(self, folder, select=None):
117
+    def cb_download_dir(self, folder, select=None):
121 118
         if not folder:
122 119
             return
123 120
         print "Folder selected - %s"%folder
@@ -160,10 +157,10 @@ def make_service(stream):
160 157
     service_type = 4097
161 158
     if re.search("\.ts$",url.split("?")[0],re.IGNORECASE):
162 159
         service_type = 1
163
-    if "resolver" in stream and stream["resolver"] in ("hqq","viaplay"):
160
+    if "resolver" in stream and stream["resolver"] in ("hqq","viaplay","filmas"):
164 161
         url = util.streamproxy_encode(stream["url"], stream["headers"])
165
-        if os.path.exists("/usr/bin/exteplayer3"): # problem playing hqq streams with gstreamer, use exteplayer3
166
-            service_type = 5002
162
+        #if os.path.exists("/usr/bin/exteplayer3"): # problem playing hqq streams with gstreamer, use exteplayer3
163
+            #service_type = 5002
167 164
     print "service_type=",service_type
168 165
     print "stream_url=",url
169 166
     service = eServiceReference(service_type, 0, url)
@@ -632,7 +629,7 @@ class MainScreen(Screen):
632 629
                 try:
633 630
                     self.session.open(PSPlayer, streams)
634 631
                 except Exception as e:
635
-                    self.msg2("Error launching player - " + str(e))
632
+                    self.msg("Error launching player - " + str(e))
636 633
                     return
637 634
             else:
638 635
                 self.msg("No stream found - %s"%(self.current[1]))
@@ -715,11 +712,15 @@ class MainScreen(Screen):
715 712
         ]
716 713
         if self.sources.is_video(self.current[1]):
717 714
             lst.extend([
718
-            ("Download video","download","Download video in background"),
715
+            ("Download video to default folder","download","Download video to default folder"),
716
+            ("Download video, ask folder","download2","Download video, ask download folder"),
717
+            ("Download video to subfolder, ask parent folder","download3","Download video to subfolder, ask download folder"),
718
+
719 719
             ])
720 720
         else:
721 721
             lst.extend([
722
-            ("Download videos in folder","download","Download videos in folder (if any)"),
722
+            ("Download list to default folder","download","Download videos in list (if any)"),
723
+            ("Download list, ask folder","download2","Download videos in list (if any), ask download folder"),
723 724
             ])
724 725
         if "config::" in self.cur_menu[1]:
725 726
             lst.extend([
@@ -735,6 +736,7 @@ class MainScreen(Screen):
735 736
         #print "item_menu_selected",answer
736 737
         if not answer:
737 738
             return
739
+        self.answer = answer[1]
738 740
 
739 741
         if answer[1] == "info":
740 742
             self.session.open(MessageBox, "Not yet implemented!", MessageBox.TYPE_INFO)
@@ -748,33 +750,22 @@ class MainScreen(Screen):
748 750
 
749 751
         elif answer[1] == "favorites":
750 752
             lists = self.config.get_lists()
751
-            lists2 = [(l,l) for l in lists]
753
+            lists2 = [(self.config.get_title(l),l) for l in lists]
754
+            print lists2
752 755
             self.session.openWithCallback(self.cb_favorites, ChoiceBox, title="Selected menu item will be added",list = lists2)
753 756
 
754
-        elif answer[1] == 'download':
755
-            current = self.current
756
-            if not self.sources.is_video(current[1]):
757
-                #self.msg("Can not download listst (yet) - %s"%(current[1]))
758
-                n = 0
759
-                for current2 in self.sources.get_content(current[1]):
760
-                    if self.sources.is_video(current2[1]):
761
-                        n += 1
762
-                        self.download_video(current2)
763
-                if n>0:
764
-                    self.msg("%s videos download started"%n)
765
-                else:
766
-                    self.msg("No videos to download")
767
-            else:
768
-                if self.download_video(current):
769
-                    self.msg("Video download started")
757
+        elif answer[1] in ("download2","download3"):  # ask download folder before
758
+            self.session.openWithCallback(self.download_prepare, LocationBox,"Select download folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
770 759
 
760
+        elif answer[1] == 'download':
761
+            self.download_prepare(config.plugins.playstream.download_dir.value)
771 762
 
772 763
         elif answer[1] == 'download_list':
773 764
             self.download_list()
774 765
 
775 766
         elif answer[1] == 'download_folder':
776 767
             #downloadDir = "/media/hdd/movie" #config.plugins.playstream.downloadDir.value TODO
777
-            self.session.openWithCallback(self.select_download_dir, LocationBox,"Select download folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
768
+            self.session.openWithCallback(self.cb_download_dir, LocationBox,"Select download folder","",config.plugins.playstream.download_dir.value,config.plugins.playstream.locations,False,"Select folder",None,True,True)
778 769
 
779 770
         elif answer[1] == "delete":
780 771
             lst = self.cur_menu[1].replace("config::","")
@@ -793,7 +784,31 @@ class MainScreen(Screen):
793 784
             pass #TODO
794 785
         return
795 786
 
796
-    def select_download_dir(self, downloadDir, select=None):
787
+    def download_prepare(self, download_dir=""):
788
+        current = self.current
789
+        if not download_dir:
790
+            return
791
+            #download_dir = config.plugins.playstream.download_dir.value
792
+        title = re.sub("\[.+?\]","", util.make_fname(current[0])).strip()
793
+        download_dir2 = os.path.join(download_dir, title)
794
+        if not self.sources.is_video(current[1]):
795
+            #self.msg("Can not download listst (yet) - %s"%(current[1]))
796
+            n = 0
797
+            for current2 in self.sources.get_content(current[1]):
798
+                if self.sources.is_video(current2[1]):
799
+                    n += 1
800
+                    self.download_video(current2,download_dir2)
801
+            if n>0:
802
+                self.msg("%s videos download started to %s"%(n,download_dir2))
803
+            else:
804
+                self.msg("No videos to download")
805
+        else:
806
+            if self.answer == "download":
807
+                download_dir2 = download_dir
808
+            if self.download_video(current,download_dir2):
809
+                self.msg("Video download started to %s"%download_dir2)
810
+
811
+    def cb_download_dir(self, downloadDir, select=None):
797 812
         if not downloadDir:
798 813
             return
799 814
         print "Folder selected - %s"%downloadDir
@@ -805,7 +820,7 @@ class MainScreen(Screen):
805 820
     def download_list(self):
806 821
         self.session.open(VideoDownloadList)
807 822
 
808
-    def download_video(self,current):
823
+    def download_video(self,current, download_dir=""):
809 824
         if self.sources.stream_type(current[1]):
810 825
             stream = util.item()
811 826
             stream["url"] = current[1]
@@ -831,9 +846,9 @@ class MainScreen(Screen):
831 846
         else:
832 847
             stream = streams[0]
833 848
         stream = util.stream_change(stream)
834
-        return self.download_stream(stream)
849
+        return self.download_stream(stream, download_dir)
835 850
 
836
-    def download_stream(self,stream):
851
+    def download_stream(self,stream,download_dir=""):
837 852
         print "download stream",stream
838 853
         #self.msg("Start downloading..")
839 854
         self.stream = stream
@@ -846,16 +861,31 @@ class MainScreen(Screen):
846 861
         title = self.stream["name"].strip()
847 862
         url = self.stream["url"]
848 863
         stream_type = self.stream["type"] #self.sources.stream_type(stream["url"])
849
-        downloadDir = config.plugins.playstream.download_dir.value
864
+        downloadDir = config.plugins.playstream.download_dir.value if not download_dir else download_dir
850 865
         if not os.path.exists(downloadDir):
851
-            print 'Sorry, download directory "%s" not exist!\nPlease specify in the settings existing directory'%downloadDir
852
-            self.msg0(_('Sorry, download directory "%s" not exist!\nPlease specify in the settings existing directory'%downloadDir))
853
-            return
854
-        fname0 = re.sub("[/\n\r\t,:]"," ",title)
855
-        fname0 = re.sub("['""]","",fname0)
866
+            try:
867
+                os.mkdir(downloadDir)
868
+            except Exception as e:
869
+                print 'Error creating download directory "%s"!\nPlease specify in the settings existing directory\n%s'%(downloadDir,str(e))
870
+                self.msg('Error creating download directory "%s"!\nPlease specify in the settings existing directory\n%s'%(downloadDir,str(e)))
871
+                return
872
+        fname0 = util.make_fname(title)
856 873
         fname = fname0 +".mp4"
857 874
         outputfile = os.path.join(downloadDir, fname)
858 875
         #print "Trying to download - ", current
876
+        if self.stream["img"]:
877
+            try:
878
+                thumb = urllib2.urlopen(stream["img"]).read()
879
+            except:
880
+                thumb = ""
881
+            if thumb:
882
+                imgext = ".jpg"
883
+                m = re.search("(\.\w{3})$",stream["img"])
884
+                if m:
885
+                    imgext = m.group(1)
886
+                imgfile = os.path.join(downloadDir,fname0+imgext)
887
+                with open(imgfile,"wb") as f:
888
+                    f.write(thumb)
859 889
         if self.stream["subs"]:
860 890
             suburl = self.stream["subs"][0]["url"]
861 891
             print "\n**Download subtitles %s - %s"%(title,suburl)
@@ -870,8 +900,17 @@ class MainScreen(Screen):
870 900
                     f.write(subs)
871 901
             else:
872 902
                 print "\n Error downloading subtitle %s"%suburl
873
-
874
-        if os.path.exists(outputfile):
903
+        if "nfo" in self.stream and self.stream["nfo"]:
904
+            nfofile = subfile = os.path.join(downloadDir,fname0+".nfo")
905
+            with open(nfofile,"w") as f:
906
+                nfo_type,nfo = next(self.stream["nfo"].iteritems())
907
+                f.write("<%s>\n"%nfo_type.encode("utf8"))
908
+                for k,v in nfo.iteritems():
909
+                    if isinstance(v,unicode): v = v.encode("utf8")
910
+                    f.write("    <%s>%s</%s>\n"%(k.encode("utf8"), v, k.encode("utf8")))
911
+                f.write("</%s>\n"%nfo_type.encode("utf8"))
912
+        overwrite = config.plugins.playstream.overwrite_download.value
913
+        if not overwrite and os.path.exists(outputfile):
875 914
             self.msg( _('Sorry, this file already exists:\n%s') % outputfile)
876 915
             return False
877 916
             #os.remove(outputfile)

+ 535
- 437
PlayStream.wpr
ファイル差分が大きすぎるため省略します
ファイルの表示


+ 5
- 1
changelog.md ファイルの表示

@@ -1,4 +1,8 @@
1
-**0.6a** (12.02.2016):
1
+**0.6b** (05.03.2017)
2
+- uzlabota lejupielāde (foldera paprasišana, lejupielāde apakšfolderi u.c.)
3
+- .nfo un .jpg failu veidošana pie lejupielādes (jēdzigs .nfo pagaidam tikai iPlayer)
4
+
5
+**0.6a** (12.02.2017):
2 6
 - kombinētā versija ar Kodi, salabots, lai iet kopā (funkcionali nekas jauns)
3 7
 
4 8
 **0.5y** (11.02.2016):

+ 1
- 1
imake.bat ファイルの表示

@@ -2,7 +2,7 @@
2 2
 :=== Parameters ===
3 3
 
4 4
 if ()==(%1%) (
5
-    set ver=0.6a
5
+    set ver=0.6b
6 6
 	rem echo Please provide version
7 7
 	rem pause
8 8
 	rem GOTO:EOF

+ 68
- 35
playstreamproxy.py ファイルの表示

@@ -8,6 +8,7 @@ import sys
8 8
 import time
9 9
 import atexit
10 10
 import re
11
+import binascii
11 12
 
12 13
 from signal import SIGTERM
13 14
 
@@ -22,7 +23,7 @@ requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
22 23
 
23 24
 HOST_NAME = ""
24 25
 PORT_NUMBER = 88
25
-DEBUG = True
26
+DEBUG = False
26 27
 
27 28
 headers2dict = lambda  h: dict([l.strip().split(": ") for l in h.strip().splitlines()])
28 29
 sessions = {}
@@ -41,7 +42,7 @@ class StreamHandler(BaseHTTPRequestHandler):
41 42
         SPLIT_CODE = "%7E"
42 43
         EQ_CODE = "%3D"
43 44
         COL_CODE = "%3A"
44
-
45
+        self.log_message("get_url: \n%s", self.path)
45 46
         p = self.path.split("~")
46 47
         url = urllib.unquote(p[0][1:])
47 48
         url = url.replace(COL_CODE, ":")
@@ -68,17 +69,21 @@ class StreamHandler(BaseHTTPRequestHandler):
68 69
 
69 70
     def fetch_url2(self, wfile, url, headers):
70 71
         if DEBUG: print "\n***********************************************************"
71
-        self.log_message("fetch_url: %s", url)
72
+        self.log_message("fetch_url: \n%s", url)
72 73
         #self.log_message("headers: %s", headers)
73 74
 
74 75
         base_url = "/".join(url.split("/")[0:-1])
75 76
         if base_url not in sessions:
76
-            sessions[base_url] = requests.Session()
77
+            sessions[base_url]={}
78
+            sessions[base_url]["session"] = requests.Session()
79
+            sessions[base_url]["key"] = binascii.a2b_hex(headers["key"]) if "key" in headers and headers["key"] else None
77 80
             #cj = cookielib.CookieJar()
78 81
             #sessions[base_url] = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
79 82
         else:
80
-            pass
81
-        ses = sessions[base_url]
83
+            if "key" in headers and headers["key"]: sessions[base_url]["key"] = binascii.a2b_hex(headers["key"])
84
+        ses = sessions[base_url]["session"]
85
+        key = sessions[base_url]["key"]
86
+
82 87
         if DEBUG: print "**Request headers: "
83 88
         ses.headers.update(headers)
84 89
         #ses.addheaders=[]
@@ -93,41 +98,69 @@ class StreamHandler(BaseHTTPRequestHandler):
93 98
         for h in r.headers:
94 99
             if DEBUG: print h,"=",r.headers[h]
95 100
         self.send_response(code)
101
+
102
+        print code
103
+        if code <> 200:
104
+            self.fetch_offline(wfile)
105
+            return
106
+
96 107
         if DEBUG: print "**Return headers:"
108
+        headers2 = {}
97 109
         for h in r.headers:
98
-            if h.lower() in ("user-agent","server"):continue
99
-            if h.lower()=="connection":
100
-                if DEBUG: print h," skipped"
110
+            if h.lower() in ("user-agent","server","transfer-encoding","content-encoding","connection"):
111
+                if DEBUG: print h," - skipped"
101 112
                 continue
102
-            self.send_header(h, r.headers[h])
103
-            if DEBUG:print h,"=",r.headers[h]
104
-        self.end_headers()
113
+            else:
114
+                headers2[h] = r.headers[h]
115
+                if DEBUG:print h,"=",r.headers[h]
116
+
117
+        # Content-Type: application/vnd.apple.mpegurl
118
+        if r.headers["Content-Type"] == "application/vnd.apple.mpegurl" and key:
119
+            content = r.content
120
+            content = r.content.replace(base_url+"/","")
121
+            content = re.sub("#EXT-X-KEY:METHOD=AES-128.+\n", "", content, 0, re.IGNORECASE | re.MULTILINE)
122
+            headers2["Content-Length"] = "%s"%len(content)
123
+            self.send_headers(headers2)
124
+            wfile.write(content)
125
+
126
+        # Content-Type: video/MP2T
127
+        elif r.headers["Content-Type"] == "video/MP2T" and key:
128
+            content = r.content
129
+            from Crypto.Cipher import AES
130
+            iv = content[:16]
131
+            d = AES.new(key, AES.MODE_CBC, iv)
132
+            content = d.decrypt(content[16:])
133
+            headers2["Content-Length"] = "%s"%len(content)
134
+            self.send_headers(headers2)
135
+            wfile.write(content)
105 136
 
106
-        CHUNK_SIZE = 4 * 1024
107
-        if code == 200:
108
-            #while True:
109
-                #chunk = r.read(CHUNK_SIZE)
110
-                #if not chunk:
111
-                    #break
112
-                #wfile.write(chunk)
113
-            #pass
114
-            #wfile.close()
115
-            for chunk in r.iter_content(1024):
116
-                try:
117
-                    #print "#",
118
-                    wfile.write(chunk)
119
-                except Exception as e:
120
-                    print "Exception: ", str(e)
121
-                    return
122
-            if DEBUG: print "  = file downloaded = "
123
-            time.sleep(2)
124
-            #self.wfile.close()
137
+        else:
138
+            self.send_headers(headers2)
139
+            CHUNK_SIZE = 4 * 1024
140
+            if code == 200:
141
+                #while True:
142
+                    #chunk = r.read(CHUNK_SIZE)
143
+                    #if not chunk:
144
+                        #break
145
+                    #wfile.write(chunk)
146
+                #pass
147
+                #wfile.close()
148
+                for chunk in r.iter_content(1024):
149
+                    try:
150
+                        #print "#",
151
+                        wfile.write(chunk)
152
+                    except Exception as e:
153
+                        print "Exception: ", str(e)
154
+                        return
155
+                if DEBUG: print "  = file downloaded = "
156
+                time.sleep(1)
157
+        self.wfile.close()
125 158
 
159
+    def send_headers(self,headers):
160
+        for h in headers:
161
+            self.send_header(h, headers[h])
162
+        self.end_headers()
126 163
 
127
-        else:
128
-            print code
129
-            self.fetch_offline(wfile)
130
-            pass
131 164
 
132 165
 class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
133 166
     """Handle requests in a separate thread."""

+ 3
- 1
plugin.py ファイルの表示

@@ -1,6 +1,7 @@
1 1
 from Plugins.Plugin import PluginDescriptor
2 2
 import PlayStream
3 3
 from . import _
4
+import traceback
4 5
 
5 6
 def main(session, **kwargs):
6 7
     try:
@@ -8,6 +9,7 @@ def main(session, **kwargs):
8 9
         session.open(PlayStream.MainScreen)
9 10
     except Exception as e:
10 11
         print "Error loading PlayStream - "+ e.message
12
+        traceback.print_exc()
11 13
 
12 14
 def menu(menuid, **kwargs):
13 15
     if menuid == "mainmenu":
@@ -17,5 +19,5 @@ def menu(menuid, **kwargs):
17 19
 def Plugins(**kwargs):
18 20
     return [
19 21
         PluginDescriptor(name = "Play Stream",description = _("Play online streams from various sources"),where = [PluginDescriptor.WHERE_PLUGINMENU,PluginDescriptor.WHERE_EXTENSIONSMENU], icon = "plugin.png", fnc = main),
20
-        PluginDescriptor(name="TV Play", description=_("Play online streams from various sources"), where = [PluginDescriptor.WHERE_MENU], fnc=menu)
22
+        PluginDescriptor(name="Play Stream", description=_("Play online streams from various sources"), where = [PluginDescriptor.WHERE_MENU], fnc=menu)
21 23
     ]

+ 1
- 5
resolver.py ファイルの表示

@@ -56,15 +56,11 @@ RESOLVERS = sorted(RESOLVERS, key=lambda m: -m.__priority__)
56 56
 def resolve(url):
57 57
     """
58 58
         resolves given url by asking all resolvers
59
-
60
-        returns None if no resolver advised to be able to resolve this url
61
-        returns False if resolver did his job, but did not return any value (thus failed)
62 59
         returns Array of resolved objects in positive usecase
63 60
     """
64 61
     url = util.decode_html(url)
65 62
     util.info('Resolving ' + url)
66 63
     resolver = _get_resolver(url)
67
-    value = None
68 64
     if resolver is None:
69 65
         return []
70 66
     util.info('Using resolver \'%s\'' % str(resolver.__name__));
@@ -87,7 +83,7 @@ def resolve(url):
87 83
                 if "=" in h:
88 84
                     i["headers"][h.split("=")[0]] = h.split("=")[1]
89 85
 
90
-    return sorted(value, key=lambda i: i['quality'], reverse=True)
86
+    return sorted(value, key=lambda i: i['quality'], reverse=True) # TODO sorted by order?
91 87
 
92 88
 
93 89
 def _get_resolver(url):

+ 3
- 1
resolvers/hdgo.py ファイルの表示

@@ -30,6 +30,8 @@ except:
30 30
     import util
31 31
 import urllib2
32 32
 import requests
33
+from requests.packages.urllib3.exceptions import InsecureRequestWarning
34
+requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
33 35
 #from aadecode import AADecoder
34 36
 
35 37
 if __name__ <> "__main__":
@@ -90,6 +92,6 @@ if __name__ == "__main__":
90 92
     util.play_video(streams)
91 93
 
92 94
 
93
-    #print streams[0]["url"]    
95
+    #print streams[0]["url"]
94 96
     #call([r"gst-launch-1.0.exe",'uri="%s""'%streams[0]["url"]])
95 97
     pass

バイナリ
resolvers/hdgo.pyc ファイルの表示


+ 2
- 0
resolvers/hqqresolver.py ファイルの表示

@@ -24,6 +24,8 @@ except:
24 24
     sys.path.insert(0, os.sep.join(pp.split(os.sep)[:-1]))
25 25
     import util
26 26
 import requests
27
+from requests.packages.urllib3.exceptions import InsecureRequestWarning
28
+requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
27 29
 
28 30
 __author__ = 'ivars777'
29 31
 if __name__ <> "__main__":

バイナリ
resolvers/hqqresolver.pyc ファイルの表示


+ 3
- 1
resolvers/kapnob.py ファイルの表示

@@ -29,6 +29,8 @@ except:
29 29
     sys.path.insert(0,os.sep.join(pp.split(os.sep)[:-1]))
30 30
     import util
31 31
 import requests
32
+from requests.packages.urllib3.exceptions import InsecureRequestWarning
33
+requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
32 34
 
33 35
 __author__ = 'ivars777'
34 36
 if __name__ <> "__main__":
@@ -89,6 +91,6 @@ if __name__ == "__main__":
89 91
         sys.exit()
90 92
     for s in streams:
91 93
         print s
92
-    print streams[0]["url"]    
94
+    print streams[0]["url"]
93 95
     util.play_video(streams)
94 96
     pass

バイナリ
resolvers/kapnob.pyc ファイルの表示


+ 3
- 1
resolvers/kodik.py ファイルの表示

@@ -29,6 +29,8 @@ except:
29 29
     sys.path.insert(0,os.sep.join(pp.split(os.sep)[:-1]))
30 30
     import util
31 31
 import requests
32
+from requests.packages.urllib3.exceptions import InsecureRequestWarning
33
+requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
32 34
 
33 35
 __author__ = 'ivars777'
34 36
 if __name__ <> "__main__":
@@ -90,6 +92,6 @@ if __name__ == "__main__":
90 92
         sys.exit()
91 93
     for s in streams:
92 94
         print s
93
-    print streams[0]["url"]    
95
+    print streams[0]["url"]
94 96
     util.play_video(streams)
95 97
     pass

バイナリ
resolvers/kodik.pyc ファイルの表示


+ 8
- 6
resolvers/openload3.py ファイルの表示

@@ -30,6 +30,8 @@ except:
30 30
     import util
31 31
 import urllib2
32 32
 import requests
33
+from requests.packages.urllib3.exceptions import InsecureRequestWarning
34
+requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
33 35
 #from aadecode import AADecoder
34 36
 
35 37
 __author__ = 'Jose Riha/Lubomir Kucera'
@@ -49,7 +51,7 @@ def resolve(url):
49 51
         'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
50 52
         'Accept-Encoding': 'none',
51 53
         'Accept-Language': 'en-US,en;q=0.8',
52
-        'Referer': url}  # 'Connection': 'keep-alive'    
54
+        'Referer': url}  # 'Connection': 'keep-alive'
53 55
 
54 56
     stream = util.item()
55 57
     m = re.search('https*://openload\.\w+/embed/([^/]+)', url)
@@ -68,11 +70,11 @@ def resolve(url):
68 70
     stream["url"] = res["url"]
69 71
     stream["name"]= res["url"]
70 72
     ### Retrieve subtitles ####
71
-    html = requests.get(url, headers=HTTP_HEADER).content 
73
+    html = requests.get(url, headers=HTTP_HEADER).content
72 74
     m = re.search('<track kind="captions" src="([^"]+)" srclang="([^"]+)" label="([^"]+)"', html)
73 75
     if m:
74 76
         stream["subs"] = m.group(1)
75
-        stream["lang"] = m.group(2)   
77
+        stream["lang"] = m.group(2)
76 78
 
77 79
     return [stream]
78 80
 
@@ -90,8 +92,8 @@ if __name__ == "__main__":
90 92
     #url = "https://kinostok.tv/embed/731f3437e3c53104dd56d04039a0b15a"
91 93
     #url = "http://vk.com/video_ext.php?oid=246066565&id=169244575&hash=d430ab0e76c9f7a1&hd=3"
92 94
     #url ="https://openload.co/embed/rPMXJYPTkw4/"
93
-    #url = "https://openload.co/embed/bE7WfZ-vz_A/" 
94
-    #url = "https://openload.co/embed/bE7WfZ/" 
95
+    #url = "https://openload.co/embed/bE7WfZ-vz_A/"
96
+    #url = "https://openload.co/embed/bE7WfZ/"
95 97
     #url = "https://openload.co/embed/OuskaKyC2GU/"
96 98
     url = "http://hqq.tv/player/embed_player.php?vid=235238210241210222228241233208212245&autoplay=no"
97 99
     url = "https://openload.co/embed/rmNcP-0QopE/"
@@ -104,6 +106,6 @@ if __name__ == "__main__":
104 106
     for s in streams:
105 107
         print s
106 108
 
107
-    print streams[0]["url"]    
109
+    print streams[0]["url"]
108 110
     call([r"c:\Program Files\VideoLAN\VLC\vlc.exe",streams[0]["url"]])
109 111
     pass

バイナリ
resolvers/openload3.pyc ファイルの表示


+ 19
- 6
util.py ファイルの表示

@@ -25,6 +25,8 @@ import datetime
25 25
 import traceback
26 26
 import cookielib
27 27
 import requests
28
+from requests.packages.urllib3.exceptions import InsecureRequestWarning
29
+requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
28 30
 from htmlentitydefs import name2codepoint as n2cp
29 31
 import HTMLParser
30 32
 import StringIO
@@ -109,12 +111,14 @@ def player(url,title="",suburl="",headers={}):
109 111
         #'location="%s"'%url,
110 112
         #'!decodebin!autovideosink'
111 113
     ]
114
+    cmd3 = ["ffplay.exe",url]
112 115
     cmd = cmd1 if url.startswith("https") else cmd2
113
-    ret = call(cmd)
116
+    ret = call(cmd3)
114 117
     #if ret:
115 118
         #a = raw_input("*** Error, continue")
116 119
     return
117 120
 
121
+
118 122
 SPLIT_CHAR = "~"
119 123
 SPLIT_CODE = urllib.quote(SPLIT_CHAR)
120 124
 EQ_CODE = urllib.quote("=")
@@ -122,11 +126,18 @@ COL_CODE = urllib.quote(":")
122 126
 SPACE_CODE = urllib.quote(" ")
123 127
 PROXY_URL = "http://localhost:88/"
124 128
 
129
+
130
+def make_fname(title):
131
+    "Make file name from title"
132
+    title = title.strip()
133
+    fname0 = re.sub("[/\n\r\t,:]"," ",title)
134
+    fname0 = re.sub("['""]","",fname0)
135
+    return fname0
136
+
125 137
 def stream_change(stream):
126 138
     #return stream # TODO
127
-    if stream["surl"]:
128
-        if not re.search("https*://(hqq|goo.\gl)",stream["surl"]):
129
-            return stream
139
+    if "resolver" in stream and stream["resolver"] in ("viaplay","hqq","filmas") or \
140
+        "surl" in stream and re.search("https*://(hqq|goo.\gl)",stream["surl"]):
130 141
         stream["url"] = streamproxy_encode(stream["url"],stream["headers"])
131 142
         stream["headers"] = {}
132 143
         return stream
@@ -271,8 +282,9 @@ def ttaf2srt(s):
271 282
 
272 283
 
273 284
 def item():
285
+    """Default item content"""
274 286
     stream0 = {
275
-        'name': '',
287
+        'name': '', #
276 288
         'url': '',
277 289
         'quality': '?',
278 290
         'surl': '',
@@ -283,7 +295,8 @@ def item():
283 295
         "lang":"",
284 296
         "type":"",
285 297
         "resolver":"",
286
-        "order":0
298
+        "order":0,
299
+        "live":False
287 300
         }
288 301
     return stream0
289 302