Ivars 7 年前
父节点
当前提交
42fa433da7
共有 13 个文件被更改,包括 822 次插入1240 次删除
  1. 115
    112
      PlayStream.py
  2. 537
    1014
      PlayStream.wpr
  3. 6
    0
      changelog.md
  4. 6
    2
      imake.bat
  5. 1
    1
      playstreamproxy
  6. 1
    1
      playstreamproxy.bat
  7. 4
    3
      playstreamproxy.py
  8. 二进制
      release/enigma2-plugin-extensions-playstream_0.5l.ipk
  9. 二进制
      release/enigma2-plugin-extensions-playstream_0.5o.ipk
  10. 11
    11
      resolver.py
  11. 37
    8
      resolvers/hqqresolver.py
  12. 56
    55
      sources/viaplay.py
  13. 48
    33
      util.py

+ 115
- 112
PlayStream.py 查看文件

@@ -65,11 +65,13 @@ def make_service(stream):
65 65
     url = url.encode("utf8")
66 66
     if "|" in url:
67 67
         url = url.replace("|","#")
68
-    #url = url.replace(":","%3a")
68
+    service_type = 4097
69 69
     if re.search("\.ts$",url.split("?")[0],re.IGNORECASE):
70 70
         service_type = 1
71
-    else:
72
-        service_type = 4097
71
+    if "resolver" in stream and stream["resolver"] in ("hqq","viaplay"):
72
+        url = util.streamproxy_encode(stream["url"], stream["headers"])
73
+        if os.path.exists("/usr/bin/exteplayer3"): # problem playing hqq streams with gstreamer, use exteplayer3
74
+            service_type = 5002
73 75
     print "service_type=",service_type
74 76
     print "stream_url=",url
75 77
     service = eServiceReference(service_type, 0, url)
@@ -91,8 +93,8 @@ class PSSubs(Screen):
91 93
              </screen>""" % (offset, desktopHeight-offset-140, screenWidth, screenWidth)
92 94
         self['subtitle'] = Label()
93 95
         Screen.__init__(self, session)
94
-        
95
- 
96
+
97
+
96 98
 #####################################################################################################################
97 99
 class PSPlayer(MoviePlayer):
98 100
     def __init__(self, session, streams):
@@ -103,24 +105,24 @@ class PSPlayer(MoviePlayer):
103 105
         self.selected = 0
104 106
         self.resume_pos = 0
105 107
         service = make_service(self.cur_stream)
106
-        
108
+
107 109
         MoviePlayer.__init__(self, session, service)
108
-        self.skinName = "MoviePlayer"        
110
+        self.skinName = "MoviePlayer"
109 111
         self["actions"] = ActionMap(["MediaPlayerActions","MediaPlayerSeekActions","MoviePlayerActions","InfobarSeekActions","MovieSelectionActions","ColorActions"], {
110 112
             "stop":self.leavePlayer,
111 113
             "leavePlayer":self.leavePlayer,
112
-            
114
+
113 115
             "audio":self.select_stream,
114 116
             "AudioSelection":self.select_stream,
115 117
             "green":self.select_stream,
116
-            
118
+
117 119
             "subtitles":self.select_captions,
118 120
             "text":self.select_captions,
119 121
             "yellow_key":self.select_captions,
120 122
             "yellow":self.select_captions,
121 123
             "pauseServiceYellow":self.select_captions,
122 124
             "pause":self.select_captions,
123
-            
125
+
124 126
             "showEventInfo":self.service_info,
125 127
             "info":self.service_info
126 128
         })
@@ -141,16 +143,16 @@ class PSPlayer(MoviePlayer):
141 143
         else:
142 144
             self.subs = []
143 145
             self.cur_subs = 0
144
-            self.svisible = False 
146
+            self.svisible = False
145 147
         self.subtitle_window = self.session.instantiateDialog (PSSubs)
146 148
         self.onLayoutFinish.append(self.start_subtitles_timer)
147
-        
149
+
148 150
     def start_subtitles_timer(self):
149 151
         if self.stimer:
150 152
             self.subtitle_window.show()
151 153
             print "start_subtitles_timer"
152 154
             self.stimer.start(self.stimer_step)
153
-        
155
+
154 156
     def get_sub_pts(self,pts):
155 157
         sc = self.get_sub_ind(self.sind) # current subbtitle
156 158
         while True:
@@ -166,14 +168,14 @@ class PSPlayer(MoviePlayer):
166 168
                 else:
167 169
                     txt = sc["text"] if sc["text"] else " "
168 170
                     return txt
169
-            
171
+
170 172
     def get_sub_ind(self,ind):
171 173
         subs_object = self.get_subs_current() # current subs object
172 174
         if subs_object:
173 175
             return subs_object.subs[ind] if ind<len(subs_object.subs) else None
174 176
         else:
175 177
             return None
176
-            
178
+
177 179
     def get_subs_current(self):
178 180
         "Return current sub_object"
179 181
         if not "subs" in self.subs[self.cur_subs]:
@@ -187,7 +189,7 @@ class PSPlayer(MoviePlayer):
187 189
                 return subs_object
188 190
         else:
189 191
             return self.subs[self.cur_subs]["subs"]
190
-        
192
+
191 193
     def update_subtitles(self):
192 194
         if not self.shown and self.svisible:
193 195
             seek = self.getSeek()
@@ -209,8 +211,8 @@ class PSPlayer(MoviePlayer):
209 211
         elif not self.svisible:
210 212
             if self.subtitle_window.shown:
211 213
                 self.subtitle_window.hide()
212
-            
213
-        
214
+
215
+
214 216
         # 	struct SubtitleTrack
215 217
         #	int type;
216 218
         #	int pid;
@@ -219,21 +221,21 @@ class PSPlayer(MoviePlayer):
219 221
         #	std::string language_code;
220 222
         #selectedSubtitle = ???
221 223
         #self.enableSubtitle(selectedSubtitle)
222
-        
224
+
223 225
     def start_subtitles_timer(self):
224 226
         self.stimer.start(self.stimer_step)
225
-       
227
+
226 228
     def play_service(self,service):
227 229
         self.movieSelected(service)
228
-       
230
+
229 231
     #def doShow(self):
230 232
         #self.svisible = False
231 233
         #InfoBarShowHide.doShow(self)
232
-        
234
+
233 235
     #def doHide(self):
234 236
         #self.svisible = True
235 237
         #InfoBarShowHide.doHide(self)
236
-    
238
+
237 239
     def service_info(self):
238 240
         print "########[MoviePlayer] service_info"
239 241
         text = "%s\n%s %s\n%s"%(self.cur_stream["name"],self.cur_stream["lang"],self.cur_stream["quality"],self.cur_stream["desc"])
@@ -241,19 +243,19 @@ class PSPlayer(MoviePlayer):
241 243
         #print text
242 244
         mtype = MessageBox.TYPE_INFO
243 245
         Notifications.AddPopup(text = text, type=mtype, timeout = 10)
244
-        #Notifications.MessageBox(self.session, text=text, type=MessageBox.TYPE_INFO, timeout=10, 
245
-                                #close_on_any_key=True, 
246
-                                #default=True, 
247
-                                #enable_input=True, 
248
-                                #msgBoxID=None, 
249
-                                #picon=False, 
250
-                                #simple=False, 
251
-                                #wizard=False, 
252
-                                #list=None, 
253
-                                #skin_name=None, 
246
+        #Notifications.MessageBox(self.session, text=text, type=MessageBox.TYPE_INFO, timeout=10,
247
+                                #close_on_any_key=True,
248
+                                #default=True,
249
+                                #enable_input=True,
250
+                                #msgBoxID=None,
251
+                                #picon=False,
252
+                                #simple=False,
253
+                                #wizard=False,
254
+                                #list=None,
255
+                                #skin_name=None,
254 256
                                 #timeout_default=None)
255 257
         #return True
256
- 
258
+
257 259
     def select_stream(self):
258 260
         print "########[MoviePlayer] select_stream"
259 261
         lst = []
@@ -268,7 +270,7 @@ class PSPlayer(MoviePlayer):
268 270
             return
269 271
         self.selected = answer[1]
270 272
         service = make_service(self.streams[self.selected])
271
-        self.resume_pos = self.getSeek().getPlayPosition()[1]        
273
+        self.resume_pos = self.getSeek().getPlayPosition()[1]
272 274
         self.play_service(service)
273 275
 
274 276
     def serviceStarted(self):
@@ -277,8 +279,8 @@ class PSPlayer(MoviePlayer):
277 279
             self.resume_pos = 0
278 280
             print "doSeek",self.resume_pos
279 281
             #self.doSeek(self.resume_pos)
280
-            
281
-            
282
+
283
+
282 284
     def select_captions(self):
283 285
         print "########[MoviePlayer] select_caption"
284 286
         lst = []
@@ -325,7 +327,7 @@ class PSPlayer(MoviePlayer):
325 327
     #def showMovies(self):
326 328
             #pass
327 329
 
328
-        
330
+
329 331
 #####################################################################################################################
330 332
 class MainScreen(Screen):
331 333
     skin = """
@@ -356,7 +358,7 @@ class MainScreen(Screen):
356 358
     <widget name="key_yellow" position="430,535" size="140,40" valign="center" halign="center" zPosition="4"  foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
357 359
     <ePixmap name="menu"   position="610,540" zPosition="2" size="140,40"  pixmap="skin_default/buttons/key_menu.png" transparent="1" alphatest="on" />
358 360
     <widget name="key_menu" position="610,535" size="140,40" valign="center" halign="center" zPosition="4"  backgroundColor="blue" foregroundColor="white" font="Regular;20" transparent="1" shadowColor="background" shadowOffset="-2,-2" />
359
-    
361
+
360 362
 </screen>"""
361 363
 
362 364
     def __init__(self, session):
@@ -369,7 +371,7 @@ class MainScreen(Screen):
369 371
         self["key_yellow"] = Button(_("Options"))
370 372
         self["key_menu"] = Button("Menu")
371 373
         self["key_exit"] = Button("Back")
372
-        
374
+
373 375
         self["actions"] = ActionMap(["OkCancelActions", "ColorActions","MenuActions", "NumberActions"],
374 376
                                     {
375 377
                                         #"cancel": self.Cancel,
@@ -401,13 +403,13 @@ class MainScreen(Screen):
401 403
         #self.defimage0.PictureData.get().append(boundFunction(self.FinishDecodeDef, os.path.join(self.cur_directory,"PlayStream.png")))
402 404
         #self.defimage0.setPara((self["pic"].instance.size().width(),self["pic"].instance.size().height(),sc[0], sc[1], False, 0, "#00000000"))
403 405
         #self.defimage0.startDecode("default")
404
-        
406
+
405 407
         self.activeDownloads = 0
406 408
         self.images = {}
407 409
         self.images_url = {}
408 410
         self.picloads = {}
409 411
         self.history = []
410
-        
412
+
411 413
         reload(ContentSources)
412 414
         self.sources = ContentSources.ContentSources(os.path.join(self.cur_directory,"sources"))
413 415
         self.config = self.sources.plugins["config"]
@@ -433,7 +435,7 @@ class MainScreen(Screen):
433 435
     def setTitle2(self,title):
434 436
         #print self.keys()
435 437
         self["title"].setText(title)
436
-        
438
+
437 439
     def ShowDefPic(self):
438 440
         if self.defimage:
439 441
             self["pic"].instance.setPixmap(self.defimage)
@@ -458,7 +460,7 @@ class MainScreen(Screen):
458 460
             else: # local file
459 461
                 image_path = os.path.join(self.cur_directory,image_url)
460 462
                 self.start_decode(image_path,image_url)
461
-            
463
+
462 464
     def start_decode(self,image_path,image_url):
463 465
         self.images[image_url] = -2
464 466
         self.images_url[image_path] = image_url
@@ -481,12 +483,12 @@ class MainScreen(Screen):
481 483
         if len(self.images)>30:
482 484
             del self.images[self.images.keys()[0]]
483 485
             # self.images.pop()
484
-            
486
+
485 487
     #def FinishDecodeDef(self, image_path,picInfo = None):
486 488
     #    self.defimage = self.defimage0.getData()
487 489
     #    del self.defimage0
488 490
     #    self["pic"].instance.setPixmap(self.defimage)
489
-        
491
+
490 492
     def download_image(self,image_path,image_url):
491 493
         #print "Image download started",self.downloading,image_path,image_url
492 494
         self.downloading += 1
@@ -496,7 +498,7 @@ class MainScreen(Screen):
496 498
     def downloadFinished(self, image_path, image_url, result):
497 499
         self.downloading -= 1
498 500
         #print "[ Play] Image downloaded finished ",self.downloading,image_path, image_url,result
499
-        self.start_decode(image_path,image_url)       
501
+        self.start_decode(image_path,image_url)
500 502
 
501 503
     def downloadFailed(self, image_path, image_url,result):
502 504
         self.downloading -= 1
@@ -513,7 +515,7 @@ class MainScreen(Screen):
513 515
         data = current[1].split("::")[1] if "::" in current[1] else current[1]
514 516
         if not data:
515 517
             return
516
-        
518
+
517 519
         elif self.sources.is_video(current[1]):
518 520
             if self.sources.stream_type(current[1]):
519 521
                 stream = stream0.copy()
@@ -521,7 +523,7 @@ class MainScreen(Screen):
521 523
                 stream["name"] = current[0]
522 524
                 streams = [stream]
523 525
             else:
524
-                try:    
526
+                try:
525 527
                     streams = self.sources.get_streams(current[1])
526 528
                 except Exception,e:
527 529
                     print str(e)
@@ -541,7 +543,7 @@ class MainScreen(Screen):
541 543
             else:
542 544
                 self.msg("No stream found - %s"%(self.current[1]))
543 545
                 return
544
-                        
546
+
545 547
         elif current[1] == "back":
546 548
             cur_menu_old = self.cur_menu
547 549
             self.cur_menu = self.history.pop()
@@ -552,38 +554,38 @@ class MainScreen(Screen):
552 554
                 index = 0
553 555
             self.setTitle2(self.cur_menu[0])
554 556
             self.show_content(new_content,index)
555
-            
557
+
556 558
         else:
557 559
             print "selected=",current
558 560
             if "{0}" in current[1]:
559
-                self.session.openWithCallback(self.cb_input,VirtualKeyBoard, title="Enter value", text="")                 
561
+                self.session.openWithCallback(self.cb_input,VirtualKeyBoard, title="Enter value", text="")
560 562
                 #a = raw_input("Enter value:")
561 563
                 #a = "big bang"
562 564
                 #current = (current[0],current[1].format(a),current[2],current[3])
563 565
                 #self.get_content(current)
564 566
             else:
565 567
                 self.get_content(current)
566
-                
567
-                
568
+
569
+
568 570
     def cb_input(self,value):
569 571
         if not value:
570 572
             return
571 573
         current = self.current
572 574
         current = (current[0],current[1].format(value),current[2],current[3])
573 575
         self.get_content(current)
574
-    
575
-    def get_content(self,current):            
576
+
577
+    def get_content(self,current):
576 578
             self.history.append(self.cur_menu)
577 579
             self.cur_menu = current
578 580
             try:
579 581
                 new_content = self.sources.get_content(self.cur_menu[1])
580 582
             except Exception,e:
581
-                self.cur_menu = self.history.pop()                
583
+                self.cur_menu = self.history.pop()
582 584
                 self.session. open(MessageBox, "Error - %s"%str(e) , MessageBox.TYPE_INFO)
583 585
                 return
584 586
             self.setTitle2(self.cur_menu[0])
585 587
             self.show_content(new_content)
586
- 
588
+
587 589
     def Back(self):
588 590
         self["list"].setIndex(0)
589 591
         self.Ok()
@@ -599,12 +601,12 @@ class MainScreen(Screen):
599 601
                 #os.remove(os.path.join(TMPDIR, name))
600 602
             #os.rmdir(TMPDIR)
601 603
         self.close()
602
-            
603
-    
604
+
605
+
604 606
     def item_menu(self):
605 607
         print "\n[PlayStream] options\n"
606 608
         self.current = self["list"].getCurrent()
607
-        self.index = self["list"].getIndex()        
609
+        self.index = self["list"].getIndex()
608 610
         #self.session. open(MessageBox, "Item options - %s"%current[0] , MessageBox.TYPE_INFO)
609 611
         #args=[current,self.cur_menu]
610 612
         #self.session.open(ItemMenuScreen,current,index,self)
@@ -622,13 +624,13 @@ class MainScreen(Screen):
622 624
         else:
623 625
             lst.extend([
624 626
             ("Download videos in folder","download","Download videos in folder (if any)"),
625
-            ])            
627
+            ])
626 628
         if "config::" in self.cur_menu[1]:
627 629
             lst.extend([
628 630
             ("Rename item","rename","Rename list item"),
629 631
             ("Move item","move","Move list item"),
630 632
             ("Delete item","delete","Delete list item"),
631
-            ("Add submenu","add_list","Add submenu before selected item"), 
633
+            ("Add submenu","add_list","Add submenu before selected item"),
632 634
             ])
633 635
         title = self.current[0]
634 636
         self.session.openWithCallback(self.cb_item_menu, ChoiceBox, title = title, list = lst) #TODO
@@ -641,18 +643,18 @@ class MainScreen(Screen):
641 643
         if answer[1] == "info":
642 644
             self.session.open(MessageBox, "Not yet implemented!", MessageBox.TYPE_INFO)
643 645
             pass # TODO parada papildus info
644
-        
646
+
645 647
         elif answer[1] == "bouquet":
646 648
             #if not e2:
647 649
                 #e2 = enigma2_api.DBServices()
648 650
             #print "load_buuquets - ",e2._load_bouquets()
649
-            self.session.open(MessageBox, "Not yet implemented!", MessageBox.TYPE_INFO)            
650
-            
651
+            self.session.open(MessageBox, "Not yet implemented!", MessageBox.TYPE_INFO)
652
+
651 653
         elif answer[1] == "favorites":
652 654
             lists = self.config.get_lists()
653
-            lists2 = [(l,l) for l in lists]            
654
-            self.session.openWithCallback(self.cb_favorites, ChoiceBox, title="Selected menu item will be added",list = lists2) 
655
-                        
655
+            lists2 = [(l,l) for l in lists]
656
+            self.session.openWithCallback(self.cb_favorites, ChoiceBox, title="Selected menu item will be added",list = lists2)
657
+
656 658
         elif answer[1] == 'download':
657 659
             current = self.current
658 660
             if not self.sources.is_video(current[1]):
@@ -665,36 +667,36 @@ class MainScreen(Screen):
665 667
                 if n>0:
666 668
                     self.msg("%s videos download started"%n)
667 669
                 else:
668
-                    self.msg("No videos to download")   
670
+                    self.msg("No videos to download")
669 671
             else:
670 672
                 if self.download_video(current):
671 673
                     self.msg("Video download started")
672
-                                 
673
-                     
674
+
675
+
674 676
         elif answer[1] == 'download_list':
675 677
             self.download_list()
676
-            
678
+
677 679
         elif answer[1] == 'download_folder':
678 680
             #downloadDir = "/media/hdd/movie" #config.plugins.playstream.downloadDir.value TODO
679 681
             self.session.openWithCallback(self.select_download_dir, LocationBox,"Select download folder","",config.playstream.download_dir.value,config.playstream.locations,False,"Select folder",None,True,True)
680
-                  
682
+
681 683
         elif answer[1] == "delete":
682 684
             lst = self.cur_menu[1].replace("config::","")
683 685
             #print lst
684 686
             self.config.del_item(lst,self.index)
685 687
             self.config.write_streams()
686 688
             txt = "'%s' deleted from favourite stream list '%s'"%(self.current[0],lst)
687
-            self.session.open(MessageBox, txt, MessageBox.TYPE_INFO,timeout=5)  
688
-            
689
+            self.session.open(MessageBox, txt, MessageBox.TYPE_INFO,timeout=5)
690
+
689 691
         elif answer[1] == "rename":
690 692
             #name2 = "Renamed"
691
-            self.session.openWithCallback(self.cb_rename,VirtualKeyBoard, title="Enter new item name", text=self.current[0]) 
692
-            
693
+            self.session.openWithCallback(self.cb_rename,VirtualKeyBoard, title="Enter new item name", text=self.current[0])
694
+
693 695
         elif answer[1] == "add_list":
694
-            self.session.open(MessageBox, "Not yet implemented!", MessageBox.TYPE_INFO,timeout=5)            
695
-            pass #TODO    
696
+            self.session.open(MessageBox, "Not yet implemented!", MessageBox.TYPE_INFO,timeout=5)
697
+            pass #TODO
696 698
         return
697
-    
699
+
698 700
     def select_download_dir(self, downloadDir, select=None):
699 701
         if not downloadDir:
700 702
             return
@@ -702,11 +704,11 @@ class MainScreen(Screen):
702 704
         config.playstream.download_dir.setValue(downloadDir)
703 705
         config.playstream.download_dir.save()
704 706
         config.playstream.locations.save()
705
-        config.save()        
707
+        config.save()
706 708
 
707 709
     def download_list(self):
708 710
         self.session.open(VideoDownloadList)
709
-        
711
+
710 712
     def download_video(self,current):
711 713
         if self.sources.stream_type(current[1]):
712 714
             stream = stream0.copy()
@@ -714,7 +716,7 @@ class MainScreen(Screen):
714 716
             stream["name"] = current[0]
715 717
             streams = [stream]
716 718
         else:
717
-            try:    
719
+            try:
718 720
                 streams = self.sources.get_streams(current[1])
719 721
             except Exception,e:
720 722
                 print "Error - %s"%str(e)
@@ -727,11 +729,12 @@ class MainScreen(Screen):
727 729
             if not s["name"]: s["name"] = current[0]
728 730
             if not s["img"]: s["img"] = current[2]
729 731
             if not s["desc"]: s["desc"] = current[3]
730
-        
732
+
731 733
         if len(streams)>1:
732 734
             stream = streams[0] # TODO iespeja izvelēties strīmu, ja to ir vairāki
733 735
         else:
734 736
             stream = streams[0]
737
+        stream = util.stream_change(stream)
735 738
         return self.download_stream(stream)
736 739
 
737 740
     def download_stream(self,stream):
@@ -739,11 +742,11 @@ class MainScreen(Screen):
739 742
         #self.msg("Start downloading..")
740 743
         self.stream = stream
741 744
         stream_type = self.stream["type"] #self.sources.stream_type(stream["url"])
742
-        if not stream_type: # 
745
+        if not stream_type: #
743 746
             print "Not supported stream type found to download - %s"%(self.current[1])
744 747
             self.msg("Not supported stream type found to download - %s"%(self.current[1]))
745 748
             return
746
-        
749
+
747 750
         title = self.stream["name"].strip()
748 751
         url = self.stream["url"]
749 752
         stream_type = self.stream["type"] #self.sources.stream_type(stream["url"])
@@ -759,55 +762,55 @@ class MainScreen(Screen):
759 762
         #print "Trying to download - ", current
760 763
         if self.stream["subs"]:
761 764
             suburl = self.stream["subs"][0]["url"]
762
-            print "\n**Download subtitles %s - %s"%(title,suburl)  
765
+            print "\n**Download subtitles %s - %s"%(title,suburl)
763 766
             subs = urllib2.urlopen(suburl).read()
764 767
             if subs:
765
-                #fname0 = re.sub("[/\n\r\t,:]"," ",title)                
768
+                #fname0 = re.sub("[/\n\r\t,:]"," ",title)
766 769
                 subext = ".srt"
767 770
                 subfile = os.path.join(downloadDir,fname0+subext)
768 771
                 if ".xml" in suburl:
769
-                    subs = util.ttaf2srt(subs) 
772
+                    subs = util.ttaf2srt(subs)
770 773
                 with open(subfile,"w") as f:
771 774
                     f.write(subs)
772 775
             else:
773 776
                 print "\n Error downloading subtitle %s"%suburl
774
-                
777
+
775 778
         if os.path.exists(outputfile):
776 779
             self.msg( _('Sorry, this file already exists:\n%s') % outputfile)
777 780
             return False
778 781
             #os.remove(outputfile)
779
-            
780
-        if stream_type in ("http","https"):  
781
-            print "\n**Download %s - %s"%(title,url)                
782
+
783
+        if stream_type in ("http","https"):
784
+            print "\n**Download %s - %s"%(title,url)
782 785
             #reload(downloadJob)
783 786
             job_manager.AddJob(downloadJob(url, outputfile, title[:20], self.video_download_stop))
784 787
             self.activeDownloads += 1
785 788
             #self.msg(_('Video download started!'))
786 789
             return True
787
-            
790
+
788 791
         elif stream_type == "hls":
789 792
             #self.msg("HLS stream download not yet implemented!")
790
-            print "\n**Download %s - %s"%(title,url)                
793
+            print "\n**Download %s - %s"%(title,url)
791 794
             #reload(HLSDownloadJob)
792 795
             print "HLSDownload", url,outputfile
793 796
             job_manager.AddJob(HLSDownloadJob(url, outputfile, title[:20], self.video_download_stop))
794 797
             self.activeDownloads += 1
795 798
             #self.msg(_('Video download started!'))
796 799
             return True
797
-            
800
+
798 801
         elif stream_type == "rstp":
799 802
             self.msg("RSTP stream download not yet implemented!")
800 803
             return False
801 804
         else:
802 805
             self.msg("Unkown stream type!")
803 806
             return False
804
-        
805
-    
807
+
808
+
806 809
     def cb_rename(self,value):
807 810
         if not value:
808 811
             return
809 812
         lst = self.cur_menu[1].replace("config::","")
810
-        pos = self.index        
813
+        pos = self.index
811 814
         print value
812 815
         item2 = list(self.current)
813 816
         item2[0]=value
@@ -815,19 +818,19 @@ class MainScreen(Screen):
815 818
         self.config.replace_item(lst,item2,pos)
816 819
         self.config.write_streams()
817 820
         txt = "'%s' renamed to '%s'"%(self.current[0],value)
818
-        self.session.open(MessageBox, txt, MessageBox.TYPE_INFO,timeout=5)     
819
-        
821
+        self.session.open(MessageBox, txt, MessageBox.TYPE_INFO,timeout=5)
822
+
820 823
     def cb_favorites(self,answer):
821 824
         print "cb_favorites",answer,self.current
822 825
         if not answer:
823
-            return 
826
+            return
824 827
         value = answer[1]
825 828
         self.config.add_item(value,self.current)
826 829
         self.config.write_streams()
827 830
         txt = "'%s' added to favourite stream list '%s'"%(self.current[0],value)
828 831
         self.session.open(MessageBox, txt, MessageBox.TYPE_INFO,timeout=3)
829 832
         #self.session.openWithCallback(self.callMyMsg, MessageBox, _("Do you want to exit the plugin?"), MessageBox.TYPE_INFO)
830
-        
833
+
831 834
     def options_screen(self):
832 835
         source = self.cur_menu[1].split("::")[0]
833 836
         options = self.sources.options_read(source)
@@ -835,17 +838,17 @@ class MainScreen(Screen):
835 838
         if not options:
836 839
             self.session. open(MessageBox, "No options available for source %s (%s)"%(self.cur_menu[0],source) , MessageBox.TYPE_INFO)
837 840
         else:
838
-            self.session.open(OptionsScreen,self)        
839
-        
841
+            self.session.open(OptionsScreen,self)
842
+
840 843
     def video_download_stop(self,title):
841 844
         #self.activeDownloads -= 1
842 845
         #self.msg("Download '%s'finished!"%title)
843 846
         print "video_download_stop ", title
844
-        
847
+
845 848
     def msg2(self,msg,timeout=10,mtype = None):
846
-        mtype=mtype if mtype else MessageBox.TYPE_INFO 
849
+        mtype=mtype if mtype else MessageBox.TYPE_INFO
847 850
         Notifications.AddPopup(text = msg, type=mtype, timeout=timeout)
848
-        
851
+
849 852
     def msg(self,msg,timeout=10):
850 853
         self.session.open(MessageBox, msg, MessageBox.TYPE_INFO, timeout)
851 854
 ##########################################################################
@@ -878,7 +881,7 @@ class OptionsScreen(ConfigListScreen,Screen):
878 881
         self.setTitle(self.main.cur_menu[0]+" options")
879 882
         self.source = self.main.cur_menu[1].split("::")[0]
880 883
         self.cfg = config.plugins.playstream
881
-        self.list = []       
884
+        self.list = []
882 885
         self.options = self.main.sources.options_read(self.source)
883 886
         if not self.options:
884 887
             #self.session. open(MessageBox, "No options available for source %s (%s)"%(self.main.cur_menu[0],self.source) , MessageBox.TYPE_INFO)
@@ -887,7 +890,7 @@ class OptionsScreen(ConfigListScreen,Screen):
887 890
             self.cfg[k]=ConfigText(default=self.options[k],fixed_size=False)
888 891
             self.list.append(getConfigListEntry(k, self.cfg[k]))
889 892
         ConfigListScreen.__init__(self, self.list, session = self.session)
890
-        
893
+
891 894
         self["key_red"] = Button(_("Cancel"))
892 895
         self["key_green"] = Button("Save")
893 896
         self["key_yellow"] = Button("")
@@ -913,7 +916,7 @@ class OptionsScreen(ConfigListScreen,Screen):
913 916
             #folder  = config.plugins.getpicons.folder.value
914 917
             #self.session.openWithCallback(self.change_dir, LocationBox,"Select Folder")
915 918
         #else:
916
-            
919
+
917 920
 
918 921
     #def change_dir(self, folder, select=None):
919 922
         #if folder:

+ 537
- 1014
PlayStream.wpr
文件差异内容过多而无法显示
查看文件


+ 6
- 0
changelog.md 查看文件

@@ -1,3 +1,9 @@
1
+**0.5p** (15.01.2016):
2
+- movieplace.lv saturs (daļēji, nav meklēšanas, seariālu, ne visi video hostingi,)
3
+- hqq hostētus strīmus spēlē ar stream_type=5002 (ja ir exteplayer3) + proxy, jo gstreamrim ir problēmas
4
+- kodik, kapnob resolveri priekš movieplace.lv
5
+- u.c. labojumi
6
+
1 7
 **0.5n** (15.01.2016):
2 8
 - salabots filmix (tagad filmix.me)
3 9
 - .ts strīmus spēlē ar service_type = 1 (nevis 4097)

+ 6
- 2
imake.bat 查看文件

@@ -2,7 +2,7 @@
2 2
 :=== Parameters ===
3 3
 
4 4
 if ()==(%1%) (
5
-    set ver=0.5n
5
+    set ver=0.5o
6 6
 	rem echo Please provide version
7 7
 	rem pause
8 8
 	rem GOTO:EOF
@@ -51,7 +51,8 @@ sources\euronews.py
51 51
 sources\filmix.py            
52 52
 sources\filmon.py            
53 53
 sources\iplayer.py           
54
-sources\kinofilmnet.py       
54
+sources\kinofilmnet.py
55
+sources\movieplace.py       
55 56
 sources\ltc.py               
56 57
 sources\mtgplay.py           
57 58
 sources\play24.py            
@@ -68,6 +69,9 @@ resolvers\__init__.py
68 69
 resolvers\aadecode.py
69 70
 resolvers\hqqresolver.py
70 71
 resolvers\openload3.py
72
+resolvers\hdgo.py
73
+resolvers\kapnob.py
74
+resolver\kodik.py
71 75
 resolvers\youtuberesolver.py
72 76
 picons\*.*
73 77
 ) do echo f | xcopy /y /q %%f %ipk_dir%data\%ext_dir%%prog%\%%f

+ 1
- 1
playstreamproxy 查看文件

@@ -1,5 +1,5 @@
1 1
 #!/bin/sh
2
-DAEMON=/usr/lib/enigma2/python/Plugins/Extensions/PlayStream/streamproxy.py 
2
+DAEMON=/usr/lib/enigma2/python/Plugins/Extensions/PlayStream/playstreamproxy.py 
3 3
 NAME=streamproxy
4 4
 DESC="StreamProxy"
5 5
 

+ 1
- 1
playstreamproxy.bat 查看文件

@@ -1 +1 @@
1
-python streamproxy.py manualstart
1
+python playstreamproxy.py manualstart

+ 4
- 3
playstreamproxy.py 查看文件

@@ -78,7 +78,7 @@ class StreamHandler(BaseHTTPRequestHandler):
78 78
             #sessions[base_url] = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))    
79 79
         else:
80 80
             pass
81
-        ses=sessions[base_url]
81
+        ses = sessions[base_url]
82 82
         if DEBUG: print "**Request headers: "
83 83
         ses.headers.update(headers)
84 84
         #ses.addheaders=[]
@@ -93,9 +93,10 @@ class StreamHandler(BaseHTTPRequestHandler):
93 93
         for h in r.headers: 
94 94
             if DEBUG: print h,"=",r.headers[h]
95 95
         self.send_response(code)
96
+        if DEBUG: print "**Return headers:"
96 97
         for h in r.headers:
97
-            if h in ("user-agent","server"):continue
98
-            if h=="connection":
98
+            if h.lower() in ("user-agent","server"):continue
99
+            if h.lower()=="connection":
99 100
                 if DEBUG: print h," skipped"
100 101
                 continue
101 102
             self.send_header(h, r.headers[h])

二进制
release/enigma2-plugin-extensions-playstream_0.5l.ipk 查看文件


二进制
release/enigma2-plugin-extensions-playstream_0.5o.ipk 查看文件


+ 11
- 11
resolver.py 查看文件

@@ -41,7 +41,7 @@ for module in os.listdir(os.path.join(os.path.dirname(__file__), server_path)):
41 41
     #resolver = eval(module)
42 42
     resolver = __import__(module)
43 43
     #reload(resolver)
44
-    
44
+
45 45
     if not hasattr(resolver, 'resolve'):
46 46
         continue
47 47
     print 'found %s %s' % (resolver, dir(resolver))
@@ -53,7 +53,7 @@ for module in os.listdir(os.path.join(os.path.dirname(__file__), server_path)):
53 53
 RESOLVERS = sorted(RESOLVERS, key=lambda m: -m.__priority__)
54 54
 
55 55
 def item():
56
-    stream0 = {'name': '', 'url': '', 'quality': '???', 'surl': '', 'subs': '', 'headers': {},"desc":"","img":"","lang":"","type":"","order":0}            
56
+    stream0 = {'name': '', 'url': '', 'quality': '???', 'surl': '', 'subs': '', 'headers': {},"desc":"","img":"","lang":"","type":"","order":0}
57 57
     return stream0
58 58
 
59 59
 def resolve(url):
@@ -69,20 +69,20 @@ def resolve(url):
69 69
     resolver = _get_resolver(url)
70 70
     value = None
71 71
     if resolver is None:
72
-        return None
72
+        return []
73 73
     util.info('Using resolver \'%s\'' % str(resolver.__name__));
74 74
     value = resolver.resolve(url)
75
-    if value is None:
76
-        return False
75
+    if not value:
76
+        return []
77 77
     default = item()
78 78
     for i in value:
79
+        i["resolver"] = resolver.__name__
79 80
         if 'name' not in i.keys():
80 81
             i['name'] = resolver.__name__
81
-        if 'surl' not in i.keys():
82
-            i['surl'] = url
82
+        i['surl'] = url
83 83
         for key in default.keys():
84 84
             if key not in i.keys():
85
-                i[key] = default[key]   
85
+                i[key] = default[key]
86 86
         if "|" in i["url"]:
87 87
             headers = i["url"].split("|")[1]
88 88
             i["url"]=i["url"].split("|")[0]
@@ -118,8 +118,8 @@ if __name__ == "__main__":
118 118
     #url = "https://kinostok.tv/embed/731f3437e3c53104dd56d04039a0b15a"
119 119
     #url = "http://vk.com/video_ext.php?oid=246066565&id=169244575&hash=d430ab0e76c9f7a1&hd=3"
120 120
     #url ="https://openload.co/embed/rPMXJYPTkw4/"
121
-    #url = "https://openload.co/embed/bE7WfZ-vz_A/" 
122
-    #url = "https://openload.co/embed/bE7WfZ/" 
121
+    #url = "https://openload.co/embed/bE7WfZ-vz_A/"
122
+    #url = "https://openload.co/embed/bE7WfZ/"
123 123
     #url = "https://openload.co/embed/OuskaKyC2GU/"
124 124
     url = "http://hqq.tv/player/embed_player.php?vid=235238210241210222228241233208212245&autoplay=no"
125 125
     url = "https://hqq.tv/player/embed_player.php?vid=235242211228257255206246241253244213194271217261258"
@@ -138,7 +138,7 @@ if __name__ == "__main__":
138 138
     for s in streams:
139 139
         print s
140 140
 
141
-    print streams[0]["url"] 
141
+    print streams[0]["url"]
142 142
     util.play_video(streams)
143 143
     ##call([r"c:\Program Files\VideoLAN\VLC\vlc.exe",streams[0]["url"]])
144 144
     pass

+ 37
- 8
resolvers/hqqresolver.py 查看文件

@@ -13,11 +13,21 @@
13 13
 from StringIO import StringIO
14 14
 import json
15 15
 import re
16
-import util
17 16
 import base64
18 17
 import urllib
18
+import sys,os
19 19
 
20
-__name__ = 'hqq'
20
+try:
21
+    import util
22
+except:
23
+    pp = os.path.dirname(os.path.abspath(__file__))
24
+    sys.path.insert(0,os.sep.join(pp.split(os.sep)[:-1]))
25
+    import util
26
+import requests
27
+
28
+__author__ = 'ivars777'
29
+if __name__ <> "__main__":
30
+    __name__ = 'hqq'
21 31
 
22 32
 
23 33
 def supports(url):
@@ -149,8 +159,12 @@ def resolve(url):
149 159
                 vid_link = re.search(r'var\s*%s\s*=\s*"([^"]*?)"'%link_1, data)
150 160
                 at = re.search(r'var\s*at\s*=\s*"([^"]*?)"', data)
151 161
                 vid = re.search('vid: "([^"]+)"',data)
152
-                subs = re.search('sub:"(.+?)"',data).group(1) if re.search('sub:"(.+?)"',data) else ""
162
+                sub_url = re.search('sub:"(.+?)"',data).group(1) if re.search('sub:"(.+?)"',data) else ""
153 163
                 subs_lang = re.search('sublangs:"(.+?)"',data).group(1) if re.search('sub:"(.+?)"',data) else ""
164
+                if sub_url:
165
+                    subs=[{"url":sub_url,'name':subs_lang,"lang":subs_lang}]
166
+                else:
167
+                    subs = []
154 168
                 if vid_server and vid_link and at:
155 169
                     get_data = {'server_1': vid_server.group(1),
156 170
                                 'link_1': vid_link.group(1),
@@ -166,9 +180,11 @@ def resolve(url):
166 180
                         file_url = _decode2(data['file'])
167 181
                         file_url = re.sub(r'\?socket=?$', '.mp4.m3u8',file_url)
168 182
                         stream  = {
169
-                            'url': file_url, 
170
-                            'subs':[{"url":subs,'name':subs_lang,"lang":subs_lang}],
171
-                            'quality': '?',
183
+                            'url': file_url,
184
+                            'name': file_url,
185
+                            'subs':subs,
186
+                            'quality': 'hqq',
187
+                            'resolver': 'hqq',
172 188
                             "headers":{"User-Agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 9_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/47.0.2526.70 Mobile/13C71 Safari/601.1.46"}
173 189
                         }
174 190
                         return [stream]
@@ -180,7 +196,7 @@ def _regex(url):
180 196
     match = re.search("(hqq|netu)\.tv/watch_video\.php\?v=(?P<vid>[0-9A-Z]+)", url)
181 197
     if match:
182 198
         return match
183
-    match = re.search(r'(hqq|netu)\.tv/player/embed_player\.php\?vid=(?P<vid>[0-9A-Z]+)', url)
199
+    match = re.search(r'(hqq|netu)\.tv/player/embed_player\.php\?vid=(?P<vid>[0-9A-Za-z]+)', url)
184 200
     if match:
185 201
         return match
186 202
     match = re.search(r'(hqq|netu)\.tv/player/hash\.php\?hash=\d+', url)
@@ -192,7 +208,7 @@ def _regex(url):
192 208
     match = re.search("(goo)\.gl/(?P<vid>[\w]+)", url)
193 209
     if match:
194 210
         return match
195
-    
211
+
196 212
     b64enc = re.search(r'data:text/javascript\;charset\=utf\-8\;base64([^\"]+)', url)
197 213
     b64dec = b64enc and base64.decodestring(b64enc.group(1))
198 214
     enc = b64dec and re.search(r"\'([^']+)\'", b64dec).group(1)
@@ -203,3 +219,16 @@ def _regex(url):
203 219
                      decoded) and match:
204 220
             return match
205 221
     return None
222
+
223
+if __name__ == "__main__":
224
+
225
+    url = "http://hqq.tv/player/embed_player.php?vid=nYAKgzBAf7ll"
226
+    streams = resolve(url)
227
+    if not streams:
228
+        print "No streams found"
229
+        sys.exit()
230
+    for s in streams:
231
+        print s
232
+    print streams[0]["url"]
233
+    util.play_video(streams)
234
+    pass

+ 56
- 55
sources/viaplay.py 查看文件

@@ -23,9 +23,9 @@ except:
23 23
     import util
24 24
 
25 25
 headers2dict = lambda  h: dict([l.strip().split(": ") for l in h.strip().splitlines()])
26
-    
26
+
27 27
 class Source(SourceBase):
28
-    
28
+
29 29
     def __init__(self,language="en"):
30 30
         self.name = "viaplay"
31 31
         self.title = "viaplay.lv"
@@ -47,13 +47,13 @@ Upgrade-Insecure-Requests: 1
47 47
         self.r = None # requests
48 48
         self.play_session = None
49 49
         self.s = None
50
-        
50
+
51 51
     def login(self,user="",password=""):
52 52
         self.options_read()
53 53
         if not user: user=self.options["user"]
54 54
         if not password: password = self.options["password"]
55 55
         self.s = requests.Session()
56
-        
56
+
57 57
         ### Dabu sesijas ID ===
58 58
         headers = headers2dict("""
59 59
 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
@@ -61,17 +61,17 @@ Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
61 61
 Accept-Language: en-US,en;q=0.5
62 62
 Accept-Encoding: gzip, deflate, br
63 63
 Referer: https://viaplay.lv/
64
-Cookie: ott_cookies_confirmed=1; 
64
+Cookie: ott_cookies_confirmed=1;
65 65
 DNT: 1
66 66
 Connection: keep-alive
67 67
 Upgrade-Insecure-Requests: 1
68
-""")   
68
+""")
69 69
         r = requests.get(self.url,headers=headers)
70 70
         if not "PLAY_SESSION" in r.cookies:
71 71
             return False
72 72
         self.play_session = r.cookies["PLAY_SESSION"]
73 73
         self.csrfToken = re.search("csrfToken=(.+)",self.play_session).group(1)
74
-        
74
+
75 75
         ### Ielogojamies ###
76 76
         headers = headers2dict("""
77 77
 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
@@ -96,7 +96,7 @@ Content-Type: application/x-www-form-urlencoded
96 96
             self.play_session = None
97 97
             return False
98 98
         self.ott = r.cookies["ott_web_sac"]
99
-        
99
+
100 100
         ### Dabu iekārtas ID ###
101 101
         if not self.device:
102 102
             headers = headers2dict("""
@@ -121,10 +121,10 @@ Connection: keep-alive    """)
121 121
             self.options["device"] = self.device
122 122
             self.options_write(self.options)
123 123
         return True
124
-    
124
+
125 125
     def logout(self):
126 126
         return True
127
-    
127
+
128 128
     def is_logedin(self):
129 129
         if self.play_session:
130 130
             return True
@@ -144,7 +144,7 @@ X-Requested-With: XMLHttpRequest
144 144
 DNT: 1
145 145
 Connection: keep-alive
146 146
 Referer: https://viaplay.lv/
147
-""")   
147
+""")
148 148
         url = "https://viaplay.lv/prehravac/init?_infuse=1&productId=%s"%vid #t110623
149 149
         headers["Cookie"] = "ott_cookies_confirmed=1; ott_dids=%s; PLAY_SESSION=%s"%(self.device,self.play_session)
150 150
         r = requests.get(url,headers=headers,allow_redirects=False)
@@ -164,17 +164,17 @@ Referer: https://viaplay.lv/
164 164
         js = demjson.decode(txt)
165 165
         return js
166 166
         #return txt
167
-            
168
-    
167
+
168
+
169 169
     def get_content(self, data):
170 170
         print "[%s] get_content:"%self.name, data
171 171
         source,data,path,plist,clist,params,qs = self.parse_data(data)
172 172
         content=[]
173 173
         content.append(("..return", "back","","Return back"))
174
-        
174
+
175 175
         if clist=="home":
176 176
             content.extend([
177
-                ("Search", "viaplay::search-results-all?query={0}",self.img,"Meklēt"),                
177
+                ("Search", "viaplay::search-results-all?query={0}",self.img,"Meklēt"),
178 178
                 ("Filmas", "viaplay::movies",self.img,"Filmas"),
179 179
                 ("Seriāli", "viaplay::series",self.img,"Seriāli"),
180 180
                 ("Bērniem", "viaplay::kids",self.img,"Bērniem"),
@@ -182,7 +182,7 @@ Referer: https://viaplay.lv/
182 182
                 ("Sports", "viaplay::live",self.img,"Sports"),
183 183
              ])
184 184
             return content
185
-        
185
+
186 186
         ### Meklēt ###
187 187
         elif clist=="search-results-all":
188 188
             url = "https://viaplay.lv/"+data
@@ -202,10 +202,10 @@ Referer: https://viaplay.lv/
202 202
                 else:
203 203
                     title = "%s - %s%s"%(title,seas,ep)
204 204
                 desc = "%s\n%s\n%s"%(title,desc2,desc)
205
-                content.append((title,self.name+"::"+data2,img,desc))             
205
+                content.append((title,self.name+"::"+data2,img,desc))
206 206
             return content
207
-        
208
-        ### Sadalas ##  
207
+
208
+        ### Sadalas ##
209 209
         elif data in ["movies","series","kids","documentary"]:
210 210
             r = self._http_request(self.url+data)
211 211
             # https://viaplay.lv/tdi/movies/next?sections[]=MOVIES&genres[]=a3591&sort[]=latest&offset=0
@@ -220,26 +220,26 @@ Referer: https://viaplay.lv/
220 220
                 if data in ("movies","series"):
221 221
                     title = "%s - %s"%(nosaukums[data],sort[s])
222 222
                     data2 = "%s/next?sections[]=%s&sort[]=%s"%(data,sections[data],s)
223
-                    content.append((title,self.name+"::"+data2,self.img,title)) 
223
+                    content.append((title,self.name+"::"+data2,self.img,title))
224 224
                 else:
225 225
                     title = "%s filmas - %s"%(nosaukums[data],sort[s])
226 226
                     data2 = "%s/next?sections[]=%s&cat[]=MOVIE&sort[]=%s"%(data,sections[data],s)
227
-                    content.append((title,self.name+"::"+data2,self.img,title)) 
227
+                    content.append((title,self.name+"::"+data2,self.img,title))
228 228
                     title = "%s seriāli - %s"%(nosaukums[data],sort[s])
229 229
                     data2 = "%s/next?sections[]=%s&cat[]=SERIES&sort[]=%s"%(data,sections[data],s)
230
-                    content.append((title,self.name+"::"+data2,self.img,title))             
231
-                    
232
-            # Pievienojam žanru sarakstu 
230
+                    content.append((title,self.name+"::"+data2,self.img,title))
231
+
232
+            # Pievienojam žanru sarakstu
233 233
             result = re.findall(r'name="genres\[\]" value="([^"]+)">.+?class="">([^<]+)</label>', r, re.DOTALL)
234 234
             for item in result:
235 235
                 s = "latest"
236 236
                 genre = item[1].replace("&amp;","&")
237 237
                 title = "%s: %s"%(nosaukums[data],genre)
238 238
                 data2 = "%s/next?sections[]=%s&genres[]=%s&sort[]=%s"%(data,sections[data],item[0],s)
239
-                content.append((title,self.name+"::"+data2,self.img,title))                 
240
-                
239
+                content.append((title,self.name+"::"+data2,self.img,title))
240
+
241 241
             return content
242
-        
242
+
243 243
         ### Filmu/seriālu/sēriju saraksts ###
244 244
         elif clist in ("movies","series","kids","documentary") and plist[1] == "next":
245 245
             url = "https://viaplay.lv/tdi/"+data
@@ -257,7 +257,7 @@ Referer: https://viaplay.lv/
257 257
                     desc2 = item[7]
258 258
                     title = "%s - %s%s"%(title,seas,ep)
259 259
                     desc = "%s\n%s\n%s"%(title,desc2,desc)
260
-                    content.append((title,self.name+"::"+data2,img,desc))  
260
+                    content.append((title,self.name+"::"+data2,img,desc))
261 261
             else: # filmas
262 262
                 result = re.findall(r'<div id="product-(\w+)".+?<a href="([^"]+)">.+?<img data-srcset="([^ ]+).+?alt="([^"]+)">.+?<p>([^<]+)</p>.+?<p class="promo-notice">([^<]+).+?<p class="is-strong detail">(.+?)</p>.+?<p class="info">([^<]+)</p>', r, re.DOTALL)
263 263
                 for item in result:
@@ -273,13 +273,13 @@ Referer: https://viaplay.lv/
273 273
                     genre = ("".join(genre)).replace("&amp;","&")
274 274
                     desc2 = item[7]
275 275
                     desc = "%s\n%s\n%s"%(genre,desc2,desc)
276
-                    content.append((title,self.name+"::"+data2, img,desc))   
276
+                    content.append((title,self.name+"::"+data2, img,desc))
277 277
             m = re.search(r"data\('href', 'https://viaplay\.lv/tdi/([^']+)'\)", r, re.DOTALL)
278 278
             if m:
279 279
                 data2 = m.group(1)
280
-                content.append(("Next page",self.name+"::"+data2,img,"Next page"))                 
280
+                content.append(("Next page",self.name+"::"+data2,img,"Next page"))
281 281
             return content
282
-        
282
+
283 283
         ### Seriāls ###
284 284
         elif clist == "series" and len(plist)==2:
285 285
             url = "https://viaplay.lv/"+data
@@ -296,16 +296,16 @@ Referer: https://viaplay.lv/
296 296
                 if "availability=" in data2: continue
297 297
                 content.append((title,self.name+"::"+data2,self.img,title)) #TODO bilde
298 298
             return content
299
-                              
299
+
300 300
     def is_video(self,data):
301
-        source,data,path,plist,clist,params,qs = self.parse_data(data)        
301
+        source,data,path,plist,clist,params,qs = self.parse_data(data)
302 302
         if clist in ("movies","documentary","kids") and len(plist)>1 and plist[1]<>"next":
303 303
             return True
304 304
         elif clist == "series"  and len(plist)>1 and plist[1] == "episode":
305 305
             return True
306 306
         else:
307 307
             return False
308
-        
308
+
309 309
     def get_streams(self, data):
310 310
         print "[viaplay] get_streams:", data
311 311
         if not self.is_video(data):
@@ -315,7 +315,7 @@ Referer: https://viaplay.lv/
315 315
             self.login()
316 316
         if not self.is_logedin():
317 317
             raise Exception("Could not login to viaplay.lv, check username/password in options")
318
-        
318
+
319 319
         streams = []
320 320
         url = "https://viaplay.lv/"+data
321 321
         r = self._http_request(url)
@@ -343,15 +343,15 @@ Referer: https://viaplay.lv/
343 343
             desc2 = desc2.replace("\n"," ").replace("\t","")
344 344
             desc = "%s\n%s"%(desc2,desc)
345 345
             vid = m.group(1)
346
-        
346
+
347 347
         js = self.get_video_info(vid)
348
-        #for m in re.finditer(r"lang: '(?P<lang>\w+)',\s+src: '(?P<url>[^']+)',\s+type: '(?P<mime>[^']+)',\s+drm: \[(?P<drm>.+?)\]\s*\}", r, re.DOTALL):               
348
+        #for m in re.finditer(r"lang: '(?P<lang>\w+)',\s+src: '(?P<url>[^']+)',\s+type: '(?P<mime>[^']+)',\s+drm: \[(?P<drm>.+?)\]\s*\}", r, re.DOTALL):
349 349
         if not js:
350 350
             return []
351 351
         tracks = js["tracks"]
352 352
         #if not tracks["HLS"]:
353 353
         #    raise Exception("Encrypted DASH playing not yet implemented")
354
-        
354
+
355 355
         captions = []
356 356
         llist = ["fr","en","ru","lv"]
357 357
         for st in js["plugins"]["settings"]["subtitles"]:
@@ -360,19 +360,20 @@ Referer: https://viaplay.lv/
360 360
             sub["lang"] = st["srclang"]
361 361
             sub["name"] = st["label"]
362 362
             sub["type"] = "vtt"
363
-            sub["order"] = llist.index(sub["lang"])*10 if sub["lang"] in llist else 0            
364
-            captions.append(sub)       
365
-        captions = sorted(captions,key=lambda item: item["order"],reverse=True) 
366
-        
363
+            sub["order"] = llist.index(sub["lang"])*10 if sub["lang"] in llist else 0
364
+            captions.append(sub)
365
+        captions = sorted(captions,key=lambda item: item["order"],reverse=True)
366
+
367 367
         for s in tracks["HLS"] if tracks["HLS"]  else tracks["DASH"] :
368 368
             stype = "DASH" if "dash" in s["type"] else "HLS"
369
-            if "drm" in s: ### 
369
+            if "drm" in s: ###
370 370
                 # TODO, encrypted stream
371 371
                 continue
372 372
             url = s["src"]
373
-            urlp = util.streamproxy_encode(s["src"])
373
+            #urlp = util.streamproxy_encode(s["src"])
374 374
             stream = util.item()
375
-            stream["url"]=urlp
375
+            stream["url"]=url
376
+            stream["resolver"] = "viaplay"
376 377
             stream["lang"]=s["lang"]
377 378
             stream["quality"]="variant"
378 379
             stream["bitrate"]= "1000000"
@@ -380,12 +381,12 @@ Referer: https://viaplay.lv/
380 381
             stream["desc"]=desc
381 382
             stream["type"]=stype
382 383
             stream["subs"] = captions
383
-            print urlp
384
+            print url
384 385
             if stype=="DASH": streams.append(stream)
385
-            
386
+
386 387
             if stype == "HLS": # izvelkam individuālos strimus
387 388
                 r = requests.get(url)
388
-                result = re.findall("#EXT-X-STREAM-INF:BANDWIDTH=(\d+),RESOLUTION=(\d+x\d+)\n(\w+.m3u8)", r.content)            
389
+                result = re.findall("#EXT-X-STREAM-INF:BANDWIDTH=(\d+),RESOLUTION=(\d+x\d+)\n(\w+.m3u8)", r.content)
389 390
                 if not result:
390 391
                     continue
391 392
                 for s2 in result:
@@ -400,7 +401,7 @@ Referer: https://viaplay.lv/
400 401
                     #if "set-cookie" in r2.headers:
401 402
                         #headers = {"Cookie":r2.headers["set-cookie"]}
402 403
                     #else:
403
-                        #headers={}                   
404
+                        #headers={}
404 405
                     url2p=util.streamproxy_encode(url2,headers)
405 406
                     stream = util.item()
406 407
                     stream["url"]=url2p
@@ -411,26 +412,26 @@ Referer: https://viaplay.lv/
411 412
                     stream["bitrate"]=s2[0]
412 413
                     stream["type"]="DASH" if "dash" in s["type"] else "HLS"
413 414
                     streams.append(stream)
414
-                        
415
+
415 416
         ### TODO - sakārtot sarakstu, lai pirmais ir labakais video
416 417
         qlist = ["","512","640","758","1024","variant"]
417
-        llist = ["lt","et","fr","en","ru","lv"]        
418
+        llist = ["lt","et","fr","en","ru","lv"]
418 419
         for s in streams:
419 420
             lv = llist.index(s["lang"])*10000000 if s["lang"] in llist else 0
420 421
             #qv=qlist.index(s["quality"]) if s["quality"] in qlist else 0
421 422
             qv = int(s["bitrate"]) if s["bitrate"] else 0
422 423
             s["order"] = lv+qv
423 424
             #print s["lang"],s["quality"],s["bitrate"],s["order"]
424
-            
425
+
425 426
         streams = sorted(streams,key=lambda item: item["order"],reverse=True)
426 427
         return streams
427
-        
428
+
428 429
     def call(self, data,params = None, headers=None):
429 430
         if not headers: headers = self.headers
430 431
         #if not lang: lang = self.country
431 432
         url = "https://viaplay.lv/tdi/" + data
432 433
         content = self._http_request(url, params, headers)
433
-        return content        
434
+        return content
434 435
 
435 436
 if __name__ == "__main__":
436 437
     if len(sys.argv)>1:
@@ -465,7 +466,7 @@ if __name__ == "__main__":
465 466
         if "HLS" in vinfo["tracks"]:
466 467
             for s in vinfo["tracks"]["HLS"]:
467 468
                 print "HLS %s: \n%s"%(s["lang"],s["src"])
468
-                
469
+
469 470
         if "DASH" in vinfo["tracks"]:
470 471
             for s in vinfo["tracks"]["DASH"]:
471 472
                 print "DASH %s: \n%s"%(s["lang"],s["src"])

+ 48
- 33
util.py 查看文件

@@ -50,7 +50,7 @@ CACHE_COOKIES = 'cookies'
50 50
 def play_video(streams):
51 51
     if len(streams)>1:
52 52
         for i,s in enumerate(streams):
53
-            
53
+
54 54
             print "%s: [%s,%s,%s] %s"%(i,s["quality"],s["lang"].encode("utf8"),s["type"],s["name"])
55 55
         a = raw_input("Select stram to play: ")
56 56
         try:
@@ -64,27 +64,28 @@ def play_video(streams):
64 64
     else:
65 65
         stream = streams[0]
66 66
 
67
+    stream = stream_change(stream)
67 68
     title = stream["name"]
68 69
     url = stream["url"]
69 70
     suburl = ""
70 71
     print url
71 72
     if "subs" in stream and stream["subs"]:
72 73
         suburl = stream["subs"][0]["url"]
73
-        print "\n**Download subtitles %s - %s"%(title,suburl)  
74
+        print "\n**Download subtitles %s - %s"%(title,suburl)
74 75
         subs = urllib2.urlopen(suburl).read()
75 76
         if subs:
76
-            fname0 = re.sub("[/\n\r\t,]","_",title)                
77
+            fname0 = re.sub("[/\n\r\t,]","_",title)
77 78
             subext = ".srt"
78 79
             subfile = os.path.join("",fname0+subext)
79 80
             if ".xml" in suburl:
80
-                subs = ttaf2srt(subs) 
81
+                subs = ttaf2srt(subs)
81 82
             with open(subfile,"w") as f:
82 83
                 f.write(subs)
83 84
         else:
84 85
             print "\n Error downloading subtitle %s"%suburl
85
-    return player(url,stream["name"],suburl)
86
-            
87
-def player(url,title="",suburl=""):
86
+    return player(url,stream["name"],suburl,stream["headers"])
87
+
88
+def player(url,title="",suburl="",headers={}):
88 89
     from subprocess import call
89 90
     print "\n**Play stream %s\n%s"%(title,url.encode("utf8"))
90 91
     cmd1 = [r"c:\Program Files\VideoLAN\VLC\vlc.exe",url,
@@ -95,7 +96,7 @@ def player(url,title="",suburl=""):
95 96
     cmd2 = [
96 97
         r"C:\gstreamer\1.0\x86_64\bin\gst-launch-1.0","-v",
97 98
         "playbin", 'uri="%s"'%url,
98
-        #"souphttpsrc", "ssl-strict=false",       
99
+        #"souphttpsrc", "ssl-strict=false",
99 100
         #"proxy=127.0.0.1:8888",
100 101
         #'location="%s"'%url,
101 102
         #'!decodebin!autovideosink'
@@ -107,20 +108,32 @@ def player(url,title="",suburl=""):
107 108
     return
108 109
 
109 110
 SPLIT_CHAR = "~"
110
-SPLIT_CODE = "%7E"
111
-EQ_CODE = "%3D"
112
-COL_CODE = "%3A"
111
+SPLIT_CODE = urllib.quote(SPLIT_CHAR)
112
+EQ_CODE = urllib.quote("=")
113
+COL_CODE = urllib.quote(":")
114
+SPACE_CODE = urllib.quote(" ")
113 115
 PROXY_URL = "http://localhost:88/"
114 116
 
117
+def stream_change(stream):
118
+    #return stream # TODO
119
+    if stream["surl"]:
120
+        if not re.search("https*://(hqq|goo.\gl)",stream["surl"]):
121
+            return stream
122
+        stream["url"] = streamproxy_encode(stream["url"],stream["headers"])
123
+        stream["headers"] = {}
124
+        return stream
125
+    else:
126
+        return stream
127
+
115 128
 def streamproxy_encode(url,headers=[]):
116 129
     if not "?" in url:
117 130
         url = url+"?"
118
-    url2 = url.replace(SPLIT_CHAR,SPLIT_CODE).replace(":",COL_CODE)
131
+    url2 = url.replace(SPLIT_CHAR,SPLIT_CODE).replace(":",COL_CODE).replace(" ",SPACE_CODE)
119 132
     url2 = PROXY_URL + url2
120 133
     if headers:
121 134
         headers2 = []
122 135
         for h in headers:
123
-            headers2.append("%s=%s"%(h,headers[h].replace("=",EQ_CODE).replace(SPLIT_CHAR,SPLIT_CODE)))
136
+            headers2.append("%s=%s"%(h,headers[h].replace("=",EQ_CODE).replace(SPLIT_CHAR,SPLIT_CODE).replace(" ",SPACE_CODE)))
124 137
         headers2 = SPLIT_CHAR.join(headers2)
125 138
         url2 = url2+SPLIT_CHAR+headers2
126 139
     return url2
@@ -130,10 +143,11 @@ def streamproxy_decode(urlp):
130 143
     path = urlp.replace(re.search("http://[^/]+",urlp).group(0),"")
131 144
     p = path.split(SPLIT_CHAR)
132 145
     url = urllib.unquote(p[0][1:])
133
-    #headers = {"User-Agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 9_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/47.0.2526.70 Mobile/13C71 Safari/601.1.46"}    
146
+    #headers = {"User-Agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 9_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/47.0.2526.70 Mobile/13C71 Safari/601.1.46"}
134 147
     headers={}
135 148
     if len(p)>1:
136 149
         for h in p[1:]:
150
+            #h = urllib.unquote()
137 151
             headers[h.split("=")[0]]=urllib.unquote(h.split("=")[1])
138 152
     return url,headers
139 153
 
@@ -145,15 +159,16 @@ class Captions(object):
145 159
             r = requests.get(uri)
146 160
         if r.status_code == 200:
147 161
             self.loads(r.content)
148
-            
162
+
149 163
     def loads(self,s):
150 164
         if "WEBVTT" in s[:s.find("\n")]: # vtt captions
151 165
             self.load_vtt(s)
152 166
         elif "<?xml" in s[:s.find("\n")]:
153 167
             self.load_ttaf(s)
154 168
         else:
155
-            return
156
-        
169
+            self.load_vtt(s) # TODO
170
+
171
+
157 172
     def load_ttaf(self,s):
158 173
         for r2 in re.findall("<style .+?/>", s):
159 174
             st = {}
@@ -161,7 +176,7 @@ class Captions(object):
161 176
                 st[a[0]] = a[1]
162 177
                 if a[0] == "id":
163 178
                     sid = a[1]
164
-            self.styles[sid] = st  
179
+            self.styles[sid] = st
165 180
         for r2 in re.findall("<p .+?</p>", s):
166 181
             sub = {}
167 182
             sub["begin"] = str2sec(re.search('begin="([^"]+)"', r2).group(1)) if re.search('begin="([^"]+)"', r2) else -1
@@ -170,9 +185,9 @@ class Captions(object):
170 185
             sub["text"] = re.search("<p[^>]+>(.+)</p>", r2).group(1).replace("\n","")
171 186
             sub["text"] = re.sub("<br\s*?/>","\n",sub["text"])
172 187
             sub["text"] = re.sub("<.+?>"," ",sub["text"])
173
-            self.subs.append(sub)  
188
+            self.subs.append(sub)
174 189
         pass
175
-                  
190
+
176 191
     def load_vtt(self,s):
177 192
         f = StringIO.StringIO(s)
178 193
         while True:
@@ -194,23 +209,23 @@ class Captions(object):
194 209
                     sub["text"].append(txt)
195 210
                     line = f.readline()
196 211
                 sub["text"] = "\n".join(sub["text"])
197
-                self.subs.append(sub)                    
212
+                self.subs.append(sub)
198 213
             else:
199 214
                 continue
200 215
         pass
201
-            
216
+
202 217
 def str2sec(r):
203 218
     # Convert str time to miliseconds
204 219
     r= r.replace(",",".")
205 220
     m = re.search(r"(\d+\:)*(\d+)\:(\d+\.\d+)", r)
206 221
     if m:
207
-        sec = int(m.group(1)[:-1])*60*60*1000 if m.group(1) else 0 
222
+        sec = int(m.group(1)[:-1])*60*60*1000 if m.group(1) else 0
208 223
         sec += int(m.group(2))*60*1000 + int(float(m.group(3))*1000)
209 224
         return sec
210 225
     else:
211 226
         return -1
212 227
 
213
-#c = Captions("http://195.13.216.2/mobile-vod/mp4:lb_barbecue_fr_lq.mp4/lb_barbecue_lv.vtt")  
228
+#c = Captions("http://195.13.216.2/mobile-vod/mp4:lb_barbecue_fr_lq.mp4/lb_barbecue_lv.vtt")
214 229
 #c = Captions("http://www.bbc.co.uk/iplayer/subtitles/ng/modav/bUnknown-0edd6227-0f38-411c-8d46-fa033c4c61c1_b05ql1s3_1479853893356.xml")
215 230
 #url = "http://195.13.216.2/mobile-vod/mp4:ac_now_you_see_me_2_en_lq.mp4/ac_now_you_see_me_2_lv.vtt"
216 231
 #c = Captions(url)
@@ -229,11 +244,11 @@ def ttaf2srt(s):
229 244
         end = end.replace(".",",")
230 245
         txt2 = re.sub("<br */>","\n",txt)
231 246
         out += "%s\n%s --> %s\n%s\n\n"%(i,begin,end,txt2)
232
-    return out    
247
+    return out
233 248
 
234 249
 
235 250
 def item():
236
-    stream0 = {'name': '', 'url': '', 'quality': '???', 'surl': '', 'subs': '', 'headers': {},"desc":"","img":"","lang":"","type":"","order":0}            
251
+    stream0 = {'name': '', 'url': '', 'quality': '???', 'surl': '', 'subs': '', 'headers': {},"desc":"","img":"","lang":"","type":"","order":0}
237 252
     return stream0
238 253
 
239 254
 class _StringCookieJar(cookielib.LWPCookieJar):
@@ -278,7 +293,7 @@ def request0(url, headers={}):
278 293
         data = response.read()
279 294
         response.close()
280 295
     except urllib2.HTTPError, error:
281
-        data = error.read()    
296
+        data = error.read()
282 297
 
283 298
     debug('len(data) %s' % len(data))
284 299
     return data
@@ -293,7 +308,7 @@ def request(url, headers={}):
293 308
         r = requests.get(url, headers=headers)
294 309
         data = r.content
295 310
     except:
296
-        data = r.content   
311
+        data = r.content
297 312
 
298 313
     debug('len(data) %s' % len(data))
299 314
     return data
@@ -304,12 +319,12 @@ def post(url, data, headers={}):
304 319
     #req.add_header('User-Agent', UA)
305 320
     import requests
306 321
     if 'User-Agent' not in headers:
307
-        headers['User-Agent']= UA    
322
+        headers['User-Agent']= UA
308 323
     try:
309 324
         r = requests.post(url, data=postdata,headers=headers)
310 325
         data = r.content
311 326
     except urllib2.HTTPError, error:
312
-        data = r.content   
327
+        data = r.content
313 328
     return data
314 329
 
315 330
 def post0(url, data, headers={}):
@@ -321,7 +336,7 @@ def post0(url, data, headers={}):
321 336
         data = response.read()
322 337
         response.close()
323 338
     except urllib2.HTTPError, error:
324
-        data = error.read()    
339
+        data = error.read()
325 340
     return data
326 341
 
327 342
 
@@ -546,7 +561,7 @@ if __name__ == "__main__":
546 561
     urlp = streamproxy_encode(url,headers)
547 562
     print urlp
548 563
     player(urlp)
549
-    
564
+
550 565
     pass
551
-    
566
+
552 567