#!/usr/bin/env python # coding=utf8 # # This file is part of PlayStream - enigma2 plugin to play video streams from various sources # Copyright (c) 2016 ivars777 (ivars777@gmail.com) # Distributed under the GNU GPL v3. For full terms see http://www.gnu.org/licenses/gpl-3.0.en.html # try: import json except: import simplejson as json import urllib2, urllib import datetime, re, sys,os import ConfigParser from SourceBase import SourceBase import base64 from collections import OrderedDict import sys import ssl if "_create_unverified_context" in dir(ssl): ssl._create_default_https_context = ssl._create_unverified_context try: import util except: sys.path.insert(0,'..') import util headers2dict = lambda h: dict([l.strip().split(": ") for l in h.strip().splitlines()]) class Source(SourceBase): def __init__(self,country="",cfg_path=None): self.name = "filmix" self.title = "filmix.co" self.img = "filmix.png" self.desc = "filmix.co satura skatīšanās" self.country=country self.headers = headers2dict(""" Host: filmix.co User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 """) self.headers2 = headers2dict(""" User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0 X-Requested-With: XMLHttpRequest Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 """) self.url = "https://filmix.co/" #self.login() def login(self,user="",password=""): return True def get_content(self, data): print "[filmix] get_content:", data source, data, path, plist, clist, params, qs = self.parse_data(data) content=[] content.append(("..return", "back","back.png","Return back")) if clist=="home": content.extend([ ("Search", "filmix::search/{0}","","Search"), ("Movies", "filmix::movies","","Movies"), ("Series", "filmix::series","","TV Series"), ("Cartoons", "filmix::cartoons","","Cartoons"), ]) return content elif clist=="search": if len(plist) < 2: return content import requests #ses = requests.session() r = requests.get(self.url+data) cookie = r.cookies["FILMIXNET"] url = "https://filmix.co/engine/ajax/sphinx_search.php" headers = headers2dict(""" User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With: XMLHttpRequest Cookie: FILMIXNET=%s; """% cookie) #data = "scf=fx&story=%s&search_start=0&do=search&subaction=search" % (plist[1].replace(" ", "+")) #data = "sdc=fx&story=%s&do=search&subaction=search"% (plist[1].replace(" ", "+")) data = "scf=fx&story=%s&subaction=search" % (plist[1].replace(" ", "+")) r = requests.post(url, data, headers=headers) #r = r.content.decode("cp1251").encode("utf8") content = self.process_list(r.content, content) return content elif data in ("movies","series","cartoons"): r = self.call("") if not r: raise Exception("Can not read content") r = r.decode("cp1251").encode("utf8") if data == "movies": sname = "Фильмы" elif data=="series": sname = "Сериалы" else: sname = "Мультфильмы" # Фильмы m = re.search('%s(.+?)
  • \s+?([^<]+)', r, re.DOTALL) duration = "(%s)"%m.group(1) if m else "" m = re.search('

    ]+>([^<]+)<', r, re.DOTALL) desc = desc0 = util.unescape(m.group(1).strip()) if m else "" vid = plist[-1] m = re.search(r"meta_key = \['(\w+)', '(\w+)', '(\w+)'\]", r, re.IGNORECASE) key = m.group(3) if m else "" js = self.get_movie_info(vid,key) #translations = js["message"]["translations"]["html5"] if "html5" in js["message"]["translations"]: translations = js["message"]["translations"]["html5"] else: translations = js["message"]["translations"] translations = js["message"]["translations"]["video"] items = [] for pl in translations: if translations[pl].startswith("http"): continue pl_link = translations[pl] lang = pl.encode("utf8") pl_link = self.decode_direct_media_url(pl_link) stxt = self._http_request(pl_link) stxt = self.decode_direct_media_url(stxt) js = json.loads(stxt) if "s" in qs: # season, enumerate episodes s = int(qs["s"]) if s > len(js): continue for i,ep in enumerate(js[s-1]["folder"]): title2 = js[s-1]["folder"][i]["title"].encode("utf8") title = title0+" - "+ title2 title_season = js[s-1]["title"].encode("utf8") data2 = data+"&e=%s"%(i+1) desc = title2 +"\n"+desc0 if data2 not in items: items.append(data2) content.append((title,self.name+"::"+data2,img,desc)) else: # enumerate seasons for i, se in enumerate(js): title2 = se["title"].encode("utf8") title = title0 +" - " + title2 if "file" in se and se["file"]: data2 = data+"?e=%s"%(i+1) else: data2 = data+"?s=%s"%(i+1) desc = title2 +"\n"+desc0 if data2 not in items: items.append(data2) content.append((title,self.name+"::"+data2,img,desc)) return content #r = self._http_request(url) ### saraksts ### else: r = self.call(data) r = r.decode("cp1251").encode("utf8") content = self.process_list(r, content) if '

    (\d+)<', r2, re.DOTALL) if m: title = "%s (%s)"%(title,m.group(1)) title = util.unescape(title) m = re.search('

    ([^<]+)

    ', r2, re.DOTALL) desc0 = util.unescape(m.group(1)) if m else "" props = [] genre = re.findall('
    ]+?">([^<]+)', r2, re.DOTALL) genre = ",".join(genre) if genre: props.append(genre) m = re.search('
    ([^<]+)
    ', r2, re.DOTALL) if m: props.append(m.group(1)) m = re.search('
    ([^<]+)<', r2) if m: props.append(m.group(1)) m = re.search('itemprop="director">([^<]+)
    ', r2) if m: props.append(m.group(1)) m = re.search('
    (.+?)
    ', r2) if m: result = re.findall("(.+?)( )*", m.group(1)) if result: actors = [] for a in zip(*result)[0]: actors.append(re.sub("<.+?>", "", a)) props.append(" ".join(actors)) else: x = 1 pass desc="%s\n%s\n\n%s"%(title, desc0, "\n".join(props)) content.append((title,self.name+"::"+data2,img,desc)) return content def is_video(self,data): source,data,path,plist,clist,params,qs = self.parse_data(data) if clist == "play" and "e=" in data: return True elif clist == "play" and "s=" in data: return False elif clist=="play": vid = path.split("/")[1] js = self.get_movie_info(vid) pl = js["message"]["translations"]["pl"] if pl == "no": return True else: return False else: return False def get_streams(self, data): print "[filmix] get_streams:", data source,data,path,plist,clist,params,qs = self.parse_data(data) r = self.call(path) if not r: return [] streams = [] r = r.decode("cp1251").encode("utf8") try: title = title0 = util.unescape(re.search("titlePlayer = '([^']+)'", r, re.DOTALL).group(1)) m = re.search('', r, re.DOTALL) duration = "(%s)"%m.group(1) if m else "" m = re.search('

    ]+>([^<]+)<', r, re.DOTALL) desc = desc0 = util.unescape(m.group(1).strip()) if m else "" except: raise Exception("No stream found") #m = re.search('itemprop="contentUrl" content="(.+?)"', r, re.IGNORECASE | re.DOTALL) #if not m: # raise Exception("Can not find video link") # #return [] #video_link = m.group(1) vid = plist[1] m = re.search(r"meta_key = \['(\w+)', '(\w+)', '(\w+)'\]", r, re.IGNORECASE) key = m.group(3) if m else "" js = self.get_movie_info(vid, key) series = True if js["message"]["translations"]["pl"] == "yes" else False if "html5" in js["message"]["translations"]: translations = js["message"]["translations"]["html5"] else: translations = js["message"]["translations"] translations = js["message"]["translations"]["video"] if not series : # Filma for pl in translations: if translations[pl].startswith("http"): continue pl_link = translations[pl] lang = pl.encode("utf8") pl_link = self.decode_direct_media_url(pl_link) streams2 = self.get_streams2(pl_link) for st in streams2: stream = util.item() stream["url"]=st[1] stream["lang"]=lang stream["quality"]=st[0] stream["name"]= title stream["desc"]=desc stream["img"] = img m = re.search("\d+", st[0]) stream["order"] = int(m.group(0)) if m else 0 streams.append(stream) #return streams else: # Seriāls for pl in translations: if translations[pl].startswith("http"): continue pl_link = translations[pl] lang = pl.encode("utf8") pl_link = self.decode_direct_media_url(pl_link) #pl_link = video_link js = self._http_request(pl_link) js = self.decode_direct_media_url(js) js = json.loads(js) playlist = js if "e" in qs: if "s" in qs: s = int(qs["s"]) else: s = None e = int(qs["e"]) if s: # sezona + epizode if s > len(js) or e > len(js[s-1]["folder"]): continue title2 = js[s-1]["folder"][e-1]["title"].encode("utf8") title = title0+" - " + title2 url0 = js[s-1]["folder"][e-1]["file"].encode("utf8") else: # tikai epizode, nav sezonas if e > len(js["playlist"]): continue title = title0 +" - "+js["playlist"][e-1]["comment"].encode("utf8") serie = js["playlist"][e-1]["comment"].encode("utf8") url0 = js["playlist"][e-1]["file"].encode("utf8") streams2 = self.get_streams2(url0) for st in streams2: stream = util.item() stream["url"]=st[1] stream["lang"]=lang stream["quality"]=st[0] stream["name"]= title stream["img"] = img stream["desc"]=desc m = re.search("\d+", st[0]) stream["order"] = int(m.group(0)) if m else 0 streams.append(stream) streams = sorted(streams,key=lambda item: item["order"],reverse=True) return streams def call(self, data,params=None,headers=None,lang=""): if not headers: headers = self.headers url = self.url+data result = self._http_request(url,params,headers=headers) return result def get_movie_info(self,vid,key=""): headers = headers2dict(""" User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0 Accept: application/json, text/javascript, */*; q=0.01 Accept-Language: en-US,en;q=0.5 Content-Type: application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With: XMLHttpRequest Referer: https://filmix.co/play/%s Cookie: ad_win12=1; """%vid ) post_data = {"post_id":vid,"key=":key} r = util.post("https://filmix.co/api/movies/player_data", data=post_data, headers = headers) if not r: raise Exception("Can not get movie info") #return [] if r.startswith(""): import time time.sleep(0.1) r = util.post("https://filmix.co/api/movies/player_data", data=post_data, headers = headers) try: js = json.loads(r) except Exception as e: raise Exception("Can not get movie info") return js def decode_base64(self, encoded_url): codec_a = ("l", "u", "T", "D", "Q", "H", "0", "3", "G", "1", "f", "M", "p", "U", "a", "I", "6", "k", "d", "s", "b", "W", "5", "e", "y", "=") codec_b = ("w", "g", "i", "Z", "c", "R", "z", "v", "x", "n", "N", "2", "8", "J", "X", "t", "9", "V", "7", "4", "B", "m", "Y", "o", "L", "h") i = 0 for a in codec_a: b = codec_b[i] i += 1 encoded_url = encoded_url.replace(a, '___') encoded_url = encoded_url.replace(b, a) encoded_url = encoded_url.replace('___', b) return base64.b64decode(encoded_url) def decode_base64_2(self, encoded_url): tokens = ("//Y2VyY2EudHJvdmEuc2FnZ2V6emE=", "//c2ljYXJpby4yMi5tb3ZpZXM=", "//a2lub2NvdmVyLnc5OC5uamJo") clean_encoded_url = encoded_url[2:].replace("\/","/") for token in tokens: clean_encoded_url = clean_encoded_url.replace(token, "") return base64.b64decode(clean_encoded_url) def decode_unicode(self, encoded_url): from itertools import izip_longest def grouper(n, iterable, fillvalue=None): "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" args = [iter(iterable)] * n return izip_longest(fillvalue=fillvalue, *args) _ = (encoded_url[1:] if encoded_url.find('#') != -1 else encoded_url) tokens = map(lambda items: '\u0'+''.join(items), grouper(3, _)) return ''.join(tokens).decode('unicode_escape') def decode_direct_media_url(self, encoded_url, checkhttp=False): if(checkhttp == True and (encoded_url.find('http://') != -1 or encoded_url.find('https://') != -1)): return False try: if encoded_url.find('#') != -1: if encoded_url[:2] == '#2': return self.decode_base64_2(encoded_url) else: return self.decode_unicode(encoded_url) else: return self.decode_base64(encoded_url) except: return False def decode_uppod_text(self, text): Client_codec_a = ["l", "u", "T", "D", "Q", "H", "0", "3", "G", "1", "f", "M", "p", "U", "a", "I", "6", "k", "d", "s", "b", "W", "5", "e", "y", "="] Client_codec_b = ["w", "g", "i", "Z", "c", "R", "z", "v", "x", "n", "N", "2", "8", "J", "X", "t", "9", "V", "7", "4", "B", "m", "Y", "o", "L", "h"] text = text.replace("\n", "").strip() for i in range(len(Client_codec_a)): char1 = Client_codec_b[i] char2 = Client_codec_a[i] text = text.replace(char1, "___") text = text.replace(char2, char1) text = text.replace("___", char2) result = base64.b64decode(text) print result return result def get_streams2_(self,url0): # Old version m = re.search("\[([\d\w,]+)\]",url0) if not m: return [("?",url0)] res = m.group(1) streams=[] for res in res.split(","): if not res: continue if res in ["1080p"]: continue #TODO fullhd only in PRO+ version url=re.sub("\[[\d\w,]+\]",res,url0) streams.append((res,url)) return streams def get_streams2(self,url0): m = re.search("\[([\d\w]+)\]",url0) if not m: return [("?",url0)] streams=[] for st in url0.split(","): if not st: continue m = re.search(r"\[([\d\w]+)\]", st) if not m: continue res = m.group(1) if res in ["1080p"]: continue #TODO fullhd only in PRO+ version url=st.replace(m.group(0), "") streams.append((res,url)) return streams if __name__ == "__main__": sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) import run source = Source() data= sys.argv[1] if len(sys.argv)>1 else source.name+"::home" run.run(source, data) sys.exit()