diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..5008ddf
Binary files /dev/null and b/.DS_Store differ
diff --git a/addon.xml b/addon.xml
deleted file mode 100644
index f1f1208..0000000
--- a/addon.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- Kodi CZ/SK plugins common python modules mainly for resolving stream URLs 2025
- Common python modules pack that is used by kodi cz/sk plugins
- GNU GPL
- all
-
-
diff --git a/changelog.txt b/changelog.txt
deleted file mode 100644
index b8e90ff..0000000
--- a/changelog.txt
+++ /dev/null
@@ -1,208 +0,0 @@
-[B]1.6.62:[/B]
-- fix dailymotion auto quality stream
-[B]1.6.61:[/B]
-- fix youtube signature
-[B]1.6.60:[/B]
-- fix cloudflare scrape protection
-[B]1.6.59:[/B]
-- fix youtube signature
-[B]1.6.58:[/B]
-- preserve compatibility with older kodi versions
-[B]1.6.57:[/B]
-- youtube: age content
-[B]1.6.56:[/B]
-- fix youtube signature
-- recognize youtu.be scheme
-[B]1.6.55:[/B]
-- duration is now recognized as infolabels attribute
-[B]1.6.54:[/B]
-- add dailymotion resolver
-[B]1.6.52:[/B]
-- fix streamujtv resolver
-[B]1.6.48:[/B]
-- fixed video download code which was failing when there were subtitles to
-download
-[B]1.6.45:[/B]
-- support for filtering by language (needs to be passed by addon as 'lang' setting)
-[B]1.6.40:[/B]
-- add on_init hook to ContentProvider
-- fix hqq & nahnoji parsers, added sk translations (jose1711)
-[B]1.6.39:[/B]
-- Fixed Exashare, Openload and Youwatch resolvers
-- New resolver for Videram
-[B]1.6.37:[/B]
-- (for all plugins) search items can be now edited (Search Similar)
-[B]1.6.36:[/B]
-- fix streamujtv resolver to play videos with missing lang
-[B]1.6.34:[/B]
-- fix usage tracker issue on windows
-[B]1.6.30:[/B]
-- fix froto compatibility issue
-[B]1.6.29:[/B]
-- providers have now injected 'lang' - current language of xbmc/kodi user
-[B]1.6.24:[/B]
-- resolvers: support for displaying additional info (audio track language, etc)
-- streamujtv: return all possible streams (incl. audio track combinations) #223
-[B]1.6.16:[/B]
-- support for disabled subtitles by plugin setting
-- #217 - incorrect item title on some skins
-[B]1.6.15:[/B]
-- fix streamujtv resolver to correctly handle subtitles
-- another possible fix of showing captcha on windows
-[B]1.6.14:[/B]
-- fixed playedto resolver
-[B]1.6.12:[/B]
-- fixed streamujtv resolver
-- better support for dynamic context menu items
-[B]1.6.11:[/B]
-- fixed putlocker and flashx resolvers (ibv)
-[B]1.6.10:[/B]
-- attempt to fix showing captcha image on windows (when there are special
-chars in profile path)
-[B]1.6.9:[/B]
-- attempt to fix showing captcha image on windows (when there are special
-chars in xbmc profile path)
-- added anyfiles resolver
-[B]1.6.8:[/B]
-- added streamujtv resolver
-[B]1.6.7:[/B]
-- add ContentProvider.findstreams - wrapper for resolver.findstreams
-[B]1.6.6:[/B]
-- added koukejse resolver
-- improved @cached decorator
-- captcha image is now downloaded to file before showing up captcha dialog
-[B]1.6.5:[/B]
-- fixed youtube resolver (mx3L)
-- download is now more robust #174
-[B]1.6.4:[/B]
-- fixed youtube resolver (by mx3L)
-- added concurrent function (by mx3L)
-[B]1.6.2:[/B]
-- updated zkouknito resolver, added kset, publicvideohost resolvers (by mx3L)
-[B]1.6.1:[/B]
-- fixed downloading of files with special chars
-- support for @cached decorator for provider methods
-[B]1.5.6:[/B]
-- fixed koukni - works back with mp4
-[B]1.5.5:[/B]
-- contentprovider fixes (does not fail when item title starts with $, supports
-infolabels
-[B]1.5.4:[/B]
-- fixed koukni resolver to properly resolve rtmp
-- removed providers - moved to plugins
-[B]1.5.2:[/B]
-- fixed youtube resolver
-[B]1.5.1:[/B]
-- when downloaded file does not have extension, it is autoappened (.mp4)
-[B]1.5.0:[/B]
-- added resolvers flashx, videomail (ivo, mx3L)
-- resolvers can now return headers (if required for playing/downloading)
-- ContentProviders can now raise ResolveException
-- ulozto provider raises ResolveException when ulozto server is overloaded
-[B]1.4.6:[/B]
-- fixed youtube resolver
-- subtitles now work in munkvideo resolver
-[B]1.4.5:[/B]
-- ulozto provider can now search for all file types
-[B]1.4.4:[/B]
-- added munkvideo resolver
-[B]1.4.3:[/B]
-- fixed eserial resolver to load subs correctly #136
-[B]1.3.12:[/B]
-- fixed eserial resolver to support subtitles and work for more streams
-- fixed quality filtering: we always return exactly 1 stream unless user wants to select himself
-[B]1.3.11:[/B]
-- sledujuserialy resolver resolves mp4 videos as well
-- fixed #127 - searching does not work on frodo beta1
-- added eserialresolver
-- resolvers have now priority (higher=resolver is asked fist)
-[B]1.3.10:[/B]
-- fixed #127 - searching does not work on frodo beta1
-- fixed ulozto to show search results again
-- fixed sledujuserialy resolver (to resolve mp4 videos)
-[B]1.3.9:[/B]
-- got rid of old resolver API
-- fixed ulozto provider to be able to retrieve non-VIP files again
-- hellspy provider has now configurable server url and supports http://stiahnito.sk (slovak mirror)
-[B]1.3.8:[/B]
-- resolver.findstreams - prevent multiple resolving same url
-- added sledujuserialy resolver
-[B]1.3.7:[/B]
-- fixed vkontakte resolver
-[B]1.3.6:[/B]
-- fixed vkontakte resolver
-[B]1.3.4:[/B]
-- fixed youtube resolver
-- added streamcloud & gosuparg resolvers (Ivo)
-[B]1.3.3:[/B]
-- ulozto and hellspy fixed: login() failed when called repeatedly
-[B]1.3.2:[/B]
-- fixed bezvadata content provider
-- added support for delayed file download (bezvadata uses it)
-[B]1.3.1:[/B]
-- vkontakte resolver now supports 720p videos
-- added videonet resolver (thanks to Ivo Brhel), rutube resolver
-[B]1.3.0:[/B]
-- introduced ContentProvider API
-- util.py splitted to util.py and xbmcutil.py (so we're now able to run tests in non-xbmc environment)
-[B]1.2.8:[/B]
-- added nahnoji and moevideo resolvers by Ivo Brhel
-- fixed putlocker (by Ivo), videozer & videobb resolvers
-[B]1.2.7:[/B]
-- youtube resolver fixes
-- all resolvers now return non-empty 'subs' key within resolve2 or findstreams
-[B]1.2.6:[/B]
-- resolvers can now retrieve subtitles
-- added koukni.cz resovler (supports subtitles)
-[B]1.2.2:[/B]
-- bugfixes
-- search.py now supports multiple search items within one addon
-[B]1.2.0:[/B]
-- added method to prelace czech diaktitic chars
-- fixed divByZero when downloading, made notifications more robust
-[B]1.1.7:[/B]
-- new API for stream resolving - quality aware API
-- youtube and vkontakte now implement quality aware API, others have dummy
-impl only
-[B]1.1.6:[/B]
-- another small fix of youtuberesolver
-- fixed videobb and videozer resovlers, thanks to Lynx187
-[B]1.1.5:[/B]
-- added higher level searching API
-- fixed youtuberesolver
-[B]1.1.4:[/B]
-- added dependency on script.usage.tracker
-[B]1.1.3:[/B]
-- download notification: added EST
-[B]1.1.2:[/B]
-- saved searches can be removed now
-[B]1.1.0:[/B]
-- added new API for retrieving common icons from github
-- fixed downloading to report dialog on finish (when not playing)
-[B]1.0.8:[/B]
-- added new API for downloading, browsing local folders
-- fixed string encoding issues
-- fixed zideo resolver
-[B]1.0.7:[/B]
-- added servertip.cz resolver
-- fixed youtube
-- added api for search history
-- added simplejson dependency
-[B]1.0.6:[/B]
-- added zideo.nl
-- stagevu - do not fail if movie was removed
-- videobb - proper resolving
-[B]1.0.5:[/B]
-- added novamov, youtube, trivial - special does nothing
-- fixed megavideo and videozer
-[B]1.0.4:[/B]
-- added megavideo, videozer resolvers
-- fixed zkouknito
-[B]1.0.3:[/B]
-- added other resolvers
-- added simple debug logging
-- all resovlers renamed not to collide with other 3rd party on Camelot
-[B]1.0.1:[/B]
- - added putlocker resolver
-[B]1.0.0:[/B]
-Initial version
diff --git a/install.sh b/install.sh
deleted file mode 100644
index dd30da9..0000000
--- a/install.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#/bin/sh
-# do NOT use this script from Kodi addons directory, it is intented for development only
-DESTDIR=~/.kodi/addons/script.module.stream.resolver
-
-rm -rf ${DESTDIR}
-mkdir -p ${DESTDIR}
-cp -a * ${DESTDIR}
diff --git a/lib/__init__.py b/lib/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/lib/__pycache__/aadecode.cpython-38.opt-1.pyc b/lib/__pycache__/aadecode.cpython-38.opt-1.pyc
deleted file mode 100644
index e82e104..0000000
Binary files a/lib/__pycache__/aadecode.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/__pycache__/cloudflare.cpython-38.opt-1.pyc b/lib/__pycache__/cloudflare.cpython-38.opt-1.pyc
deleted file mode 100644
index dbf9106..0000000
Binary files a/lib/__pycache__/cloudflare.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/__pycache__/resolver.cpython-38.opt-1.pyc b/lib/__pycache__/resolver.cpython-38.opt-1.pyc
deleted file mode 100644
index f9334f9..0000000
Binary files a/lib/__pycache__/resolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/__pycache__/search.cpython-38.opt-1.pyc b/lib/__pycache__/search.cpython-38.opt-1.pyc
deleted file mode 100644
index f201d3c..0000000
Binary files a/lib/__pycache__/search.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/__pycache__/util.cpython-38.opt-1.pyc b/lib/__pycache__/util.cpython-38.opt-1.pyc
deleted file mode 100644
index 9383f77..0000000
Binary files a/lib/__pycache__/util.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/__pycache__/xbmcutil.cpython-38.opt-1.pyc b/lib/__pycache__/xbmcutil.cpython-38.opt-1.pyc
deleted file mode 100644
index bdcf05a..0000000
Binary files a/lib/__pycache__/xbmcutil.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/aadecode.py b/lib/aadecode.py
deleted file mode 100644
index 92135a2..0000000
--- a/lib/aadecode.py
+++ /dev/null
@@ -1,209 +0,0 @@
-#-*- coding: utf-8 -*-
-#
-# author : Djeman
-# Updated by Shani-08 (https://github.com/Shani-08/ShaniXBMCWork2)
-
-import re
-
-class AADecoder(object):
- def __init__(self, aa_encoded_data):
- self.encoded_str = aa_encoded_data.replace('/*´∇`*/','')
-
- self.b = ["(c^_^o)", "(゚Θ゚)", "((o^_^o) - (゚Θ゚))", "(o^_^o)",
- "(゚ー゚)", "((゚ー゚) + (゚Θ゚))", "((o^_^o) +(o^_^o))", "((゚ー゚) + (o^_^o))",
- "((゚ー゚) + (゚ー゚))", "((゚ー゚) + (゚ー゚) + (゚Θ゚))", "(゚Д゚) .゚ω゚ノ", "(゚Д゚) .゚Θ゚ノ",
- "(゚Д゚) ['c']", "(゚Д゚) .゚ー゚ノ", "(゚Д゚) .゚Д゚ノ", "(゚Д゚) [゚Θ゚]"]
-
- def is_aaencoded(self):
- idx = self.encoded_str.find("゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); ")
- if idx == -1:
- return False
-
- if self.encoded_str.find("(゚Д゚)[゚o゚]) (゚Θ゚)) ('_');", idx) == -1:
- return False
-
- return True
-
- def base_repr(self, number, base=2, padding=0):
- digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
- if base > len(digits):
- base = len(digits)
-
- num = abs(number)
- res = []
- while num:
- res.append(digits[num % base])
- num //= base
- if padding:
- res.append('0' * padding)
- if number < 0:
- res.append('-')
- return ''.join(reversed(res or '0'))
-
- def decode_char(self, enc_char, radix):
- end_char = "+ "
- str_char = ""
- while enc_char != '':
- found = False
-
- if not found:
- for i in range(len(self.b)):
- enc_char=enc_char.replace(self.b[i], str(i))
-
- startpos=0
- findClose=True
- balance=1
- result=[]
- if enc_char.startswith('('):
- l=0
-
- for t in enc_char[1:]:
- l+=1
- if findClose and t==')':
- balance-=1;
- if balance==0:
- result+=[enc_char[startpos:l+1]]
- findClose=False
- continue
- elif not findClose and t=='(':
- startpos=l
- findClose=True
- balance=1
- continue
- elif t=='(':
- balance+=1
-
-
- if result is None or len(result)==0:
- return ""
- else:
-
- for r in result:
- value = self.decode_digit(r, radix)
- if value == "":
- return ""
- else:
- str_char += value
-
- return str_char
-
- enc_char = enc_char[len(end_char):]
-
- return str_char
-
-
-
- def decode_digit(self, enc_int, radix):
-
- rr = '(\(.+?\)\))\+'
- rerr=enc_int.split('))+')
- v = ''
-
- #new mode
-
- for c in rerr:
-
- if len(c)>0:
- if c.strip().endswith('+'):
- c=c.strip()[:-1]
-
- startbrackets=len(c)-len(c.replace('(',''))
- endbrackets=len(c)-len(c.replace(')',''))
-
- if startbrackets>endbrackets:
- c+=')'*startbrackets-endbrackets
-
- c = c.replace('!+[]','1')
- c = c.replace('-~','1+')
- c = c.replace('[]','0')
-
- v+=str(eval(c))
-
- return v
-
- mode = 0
- value = 0
-
- while enc_int != '':
- found = False
- for i in range(len(self.b)):
- if enc_int.find(self.b[i]) == 0:
- if mode == 0:
- value += i
- else:
- value -= i
- enc_int = enc_int[len(self.b[i]):]
- found = True
- break
-
- if not found:
- return ""
-
- enc_int = re.sub('^\s+|\s+$', '', enc_int)
- if enc_int.find("+") == 0:
- mode = 0
- else:
- mode = 1
-
- enc_int = enc_int[1:]
- enc_int = re.sub('^\s+|\s+$', '', enc_int)
-
- return self.base_repr(value, radix)
-
- def decode(self):
-
- self.encoded_str = re.sub('^\s+|\s+$', '', self.encoded_str)
-
- # get data
- pattern = (r"\(゚Д゚\)\[゚o゚\]\+ (.+?)\(゚Д゚\)\[゚o゚\]\)")
- result = re.search(pattern, self.encoded_str, re.DOTALL)
- if result is None:
- print("AADecoder: data not found")
- return False
-
- data = result.group(1)
-
- # hex decode string
- begin_char = "(゚Д゚)[゚ε゚]+"
- alt_char = "(o゚ー゚o)+ "
-
- out = ''
-
- while data != '':
- # Check new char
- if data.find(begin_char) != 0:
- print("AADecoder: data not found")
- return False
-
- data = data[len(begin_char):]
-
- # Find encoded char
- enc_char = ""
- if data.find(begin_char) == -1:
- enc_char = data
- data = ""
- else:
- enc_char = data[:data.find(begin_char)]
- data = data[len(enc_char):]
-
-
- radix = 8
- # Detect radix 16 for utf8 char
- if enc_char.find(alt_char) == 0:
- enc_char = enc_char[len(alt_char):]
- radix = 16
-
- str_char = self.decode_char(enc_char, radix)
-
- if str_char == "":
- print("no match : ")
- print(data + "\nout = " + out + "\n")
- return False
-
- out += chr(int(str_char, radix))
-
- if out == "":
- print("no match : " + data)
- return False
-
- return out
diff --git a/lib/cloudflare.py b/lib/cloudflare.py
deleted file mode 100644
index 855d90d..0000000
--- a/lib/cloudflare.py
+++ /dev/null
@@ -1,189 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2015 tknorris (Derived from Mikey1234's & Lambda's)
-#
-# This Program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This Program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with XBMC; see the file COPYING. If not, write to
-# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-# http://www.gnu.org/copyleft/gpl.html
-#
-# This code is a derivative of the YouTube plugin for XBMC and associated works
-# released under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 3
-
-import re
-import urllib.request, urllib.parse, urllib.error
-import urllib.parse
-import util
-import xbmc
-
-MAX_TRIES = 3
-COMPONENT = __name__
-
-
-class NoRedirection(urllib.request.HTTPErrorProcessor):
-
- def http_response(self, request, response):
- util.info('[CF] Stopping Redirect')
- return response
-
- https_response = http_response
-
-def solve_equation(equation):
- try:
- offset = (1 if equation[0] == '+' else 0)
- ev = equation.replace('!+[]', '1').replace('!![]',
- '1').replace('[]', '0').replace('(', 'str(')[offset:]
- ev = re.sub(r'^str', 'float', re.sub(r'\/(.)str', r'/\1float', ev))
- # util.debug('[CF] eval: {0}'.format(ev))
- return float(eval(ev))
- except:
- pass
-
-
-def solve(url, cj, user_agent=None, wait=True):
- if user_agent is None:
- user_agent = util.UA
- headers = {'User-Agent': user_agent, 'Referer': url}
- if cj is not None:
- try:
- cj.load(ignore_discard=True)
- except:
- pass
- opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
- urllib.request.install_opener(opener)
-
- scheme = urllib.parse.urlparse(url).scheme
- domain = urllib.parse.urlparse(url).hostname
- request = urllib.request.Request(url)
- for key in headers:
- request.add_header(key, headers[key])
- try:
- response = urllib.request.urlopen(request)
- html = response.read()
- except urllib.error.HTTPError as e:
- html = e.read()
-
- tries = 0
- while tries < MAX_TRIES:
- solver_pattern = \
- 'var (?:s,t,o,p,b,r,e,a,k,i,n,g|t,r,a),f,\s*([^=]+)'
- solver_pattern += \
- '={"([^"]+)":([^}]+)};.+challenge-form\'\);'
- vc_pattern = \
- 'input type="hidden" name="jschl_vc" value="([^"]+)'
- pass_pattern = 'input type="hidden" name="pass" value="([^"]+)'
- s_pattern = 'input type="hidden" name="s" value="([^"]+)'
- init_match = re.search(solver_pattern, html, re.DOTALL)
- vc_match = re.search(vc_pattern, html)
- pass_match = re.search(pass_pattern, html)
- s_match = re.search(s_pattern, html)
-
- if not init_match or not vc_match or not pass_match or not s_match:
- msg = \
- "[CF] Couldn't find attribute: init: |%s| vc: |%s| pass: |%s| No cloudflare check?"
- util.info(msg % (init_match, vc_match, pass_match))
- return False
-
- (init_dict, init_var, init_equation) = \
- init_match.groups()
- vc = vc_match.group(1)
- password = pass_match.group(1)
- s = s_match.group(1)
-
- equations = re.compile(r"challenge-form\'\);\s*(.*)a.v").findall(html)[0]
- # util.info("[CF] VC is: %s" % (vc))
- varname = (init_dict, init_var)
- # util.info('[CF] init: [{0}]'.format((init_equation.rstrip())))
- result = float(solve_equation(init_equation.rstrip()))
- util.info('[CF] Initial value: [ {0} ] Result: [ {1} ]'.format(init_equation,
- result))
-
- for equation in equations.split(';'):
- equation = equation.rstrip()
- if len(equation) > len('.'.join(varname)):
- # util.debug('[CF] varname {0} line {1}'.format('.'.join(varname), equation))
- if equation[:len('.'.join(varname))] != '.'.join(varname):
- util.info('[CF] Equation does not start with varname |%s|'
- % equation)
- else:
- equation = equation[len('.'.join(varname)):]
-
- expression = equation[2:]
- operator = equation[0]
- if operator not in ['+', '-', '*', '/']:
- util.info('[CF] Unknown operator: |%s|' % equation)
- continue
-
- result = float(str(eval(str(result) + operator + str(solve_equation(
- expression)))))
- #util.info('[CF] intermediate: %s = %s' % (equation, result))
-
- #util.debug('[CF] POCET: {0} {1}'.format(result, len(domain)))
- result = '{0:.10f}'.format(eval('float({0} + {1})'.format(result, len(domain))))
- util.info('[CF] Final Result: |%s|' % result)
-
- if wait:
- util.info('[CF] Sleeping for 5 Seconds')
- xbmc.sleep(5000)
-
- url = \
- '%s://%s/cdn-cgi/l/chk_jschl?s=%s&jschl_vc=%s&pass=%s&jschl_answer=%s' \
- % (scheme, domain, urllib.parse.quote(s), urllib.parse.quote(vc), urllib.parse.quote(password), urllib.parse.quote(result))
- # util.info('[CF] url: %s' % url)
- # util.debug('[CF] headers: {0}'.format(headers))
- request = urllib.request.Request(url)
- for key in headers:
- request.add_header(key, headers[key])
-
- try:
- opener = urllib.request.build_opener(NoRedirection)
- urllib.request.install_opener(opener)
- response = urllib.request.urlopen(request)
- # util.info('[CF] code: {}'.format(response.getcode()))
- while response.getcode() in [301, 302, 303, 307]:
- if cj is not None:
- cj.extract_cookies(response, request)
-
- redir_url = response.info().getheader('location')
- if not redir_url.startswith('http'):
- base_url = '%s://%s' % (scheme, domain)
- redir_url = urllib.parse.urljoin(base_url, redir_url)
-
- request = urllib.request.Request(redir_url)
- for key in headers:
- request.add_header(key, headers[key])
- if cj is not None:
- cj.add_cookie_header(request)
-
- response = urllib.request.urlopen(request)
- final = response.read()
- if 'cf-browser-verification' in final:
- util.info('[CF] Failure: html: %s url: %s' % (html, url))
- tries += 1
- html = final
- else:
- break
- except urllib.error.HTTPError as e:
- util.info('[CF] HTTP Error: %s on url: %s' % (e.code,
- url))
- return False
- except urllib.error.URLError as e:
- util.info('[CF] URLError Error: %s on url: %s' % (e,
- url))
- return False
-
- if cj is not None:
- util.cache_cookies()
-
- return final
diff --git a/lib/contentprovider/__pycache__/provider.cpython-38.opt-1.pyc b/lib/contentprovider/__pycache__/provider.cpython-38.opt-1.pyc
deleted file mode 100644
index a2599ca..0000000
Binary files a/lib/contentprovider/__pycache__/provider.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/contentprovider/__pycache__/xbmcprovider.cpython-38.opt-1.pyc b/lib/contentprovider/__pycache__/xbmcprovider.cpython-38.opt-1.pyc
deleted file mode 100644
index 11d95fb..0000000
Binary files a/lib/contentprovider/__pycache__/xbmcprovider.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/contentprovider/provider.py b/lib/contentprovider/provider.py
deleted file mode 100644
index 8536a39..0000000
--- a/lib/contentprovider/provider.py
+++ /dev/null
@@ -1,230 +0,0 @@
-# * Copyright (C) 2012 Libor Zoubek
-# *
-# *
-# * This Program is free software; you can redistribute it and/or modify
-# * it under the terms of the GNU General Public License as published by
-# * the Free Software Foundation; either version 2, or (at your option)
-# * any later version.
-# *
-# * This Program is distributed in the hope that it will be useful,
-# * but WITHOUT ANY WARRANTY; without even the implied warranty of
-# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# * GNU General Public License for more details.
-# *
-# * You should have received a copy of the GNU General Public License
-# * along with this program; see the file COPYING. If not, write to
-# * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-# * http://www.gnu.org/copyleft/gpl.html
-# *
-# */
-from collections import defaultdict
-
-import util
-import resolver
-
-
-try:
- import StorageServer
-except ImportError:
- print('Using dummy storage server')
- import storageserverdummy as StorageServer
-
-
-class ResolveException(Exception):
- pass
-
-
-class ContentProvider(object):
- """
- ContentProvider class provides an internet content. It should NOT have any xbmc-related imports
- and must be testable without XBMC runtime. This is a basic/dummy implementation.
- """
-
- def __init__(self, name='dummy', base_url='/', username=None, password=None, filter=None, tmp_dir='.'):
- """
- ContentProvider constructor
- Args:
- name (str): name of provider
- base_url (str): base url of site being accessed
- username (str): login username
- password (str): login password
- filter (func{item}): function to filter results returned by search or list methods
- tmp_dir (str): temporary dir where provider can store/cache files
- """
- self.name = name
- self.username = username
- self.password = password
- if not base_url[-1] == '/':
- base_url += '/'
- self.base_url = base_url
- self.filter = filter
- self.tmp_dir = tmp_dir
- self.cache = StorageServer.StorageServer(self.name, 24)
- self.lang = 'cs' # initialize, current language could be set by XBMContentProvider
-
- def __str__(self):
- return 'ContentProvider' + self.name
-
- def on_init(self):
- """
- This function gets called by XbmcContentProvider after it initializes itself
- and sets eveything up (especially 'lang' property of ContentProvider which gets detected
- from kodi)
- """
- pass
-
- def capabilities(self):
- """
- This way class defines which capabilities it provides ['login','search','resolve','categories']
- It may also contain '!download' when provider does not support downloading
- """
- return []
-
- def video_item(self, url='', img='', quality='???'):
- """
- Returns empty video item - contains all required fields
- """
- return {'type': 'video', 'title': '', 'rating': 0, 'year': 0, 'size': '0MB', 'url': url, 'img': img,
- 'length': '', 'quality': quality, 'subs': '', 'surl': '', 'lang': ''}
-
- def dir_item(self, title='', url='', type='dir'):
- """
- Returns empty directory item
- """
- return {'type': type, 'title': title, 'size': '0', 'url': url}
-
- def login(self):
- """
- A login method returns True on successfull login, False otherwise
- """
- return False
-
- def search(self, keyword):
- """
- Search for a keyword on a site
- Args:
- keyword (str)
-
- returns:
- array of video or directory items
- """
- return []
-
- def list(self, url):
- """
- Lists content on given url
- Args:
- url (str): either relative or absolute provider URL
-
- Returns:
- array of video or directory items
-
- """
- return []
-
- def categories(self):
- """
- Lists categories on provided site
-
- Returns:
- array of video or directory items
- """
- return []
-
- def findstreams(self, data, regexes=None):
- """
- Finds streams in given data (see resovler.findstreams for more details)
-
- :param data: A string (piece of HTML, for example) or an array of URLs
- :param regexes: An array of regexes to be used for extracting URLs from
- 'data' of type 'string'
- :returns: An array of video items
- """
- resolved = resolver.findstreams(data, regexes)
- if resolved is None:
- raise ResolveException(
- 'Nelze ziskat video link [CR]zkontrolujte jestli video nebylo odstraneno')
- elif isinstance(resolved, list) and not resolved:
- raise ResolveException('Video je na serveru, ktery neni podporovan')
- elif not resolved:
- raise ResolveException(
- 'Nebyl nalezen zadny video embed [CR]zkontrolujte stranku pripadne nahlaste chybu pluginu')
- result = []
- for j in resolved:
- i = defaultdict(lambda: '', j)
- item = self.video_item()
- item['title'] = i['name']
- item['url'] = i['url']
- item['quality'] = i['quality']
- item['surl'] = i['surl']
- item['subs'] = i['subs']
- item['headers'] = i['headers']
- item['lang'] = i['lang']
- item['info'] = i['info']
- result.append(item)
- return result
-
- def resolve(self, item, captcha_cb=None, select_cb=None, wait_cb=None):
- """
- Resolves given video item to a downloable/playable file/stream URL
-
- Args:
- url (str): relative or absolute URL to be resolved
- captcha_cb(func{obj}): callback function when user input is required (captcha, one-time passwords etc).
- function implementation must be Provider-specific
- select_cb(func{array}): callback function for cases when given url resolves to multiple streams,
- provider class may call this function and require user interaction
- wait_cb(func{obj}): callback function for cases when url resolves to stream which becomes available
- somewhere in future (typically in several seconds). Provider may call this and require waiting.
- Returns:
- None - if ``url`` was not resolved. Video item with 'url' key pointing to resolved target
- """
- return None
-
- def _url(self, url):
- """
- Transforms relative to absolute url based on ``base_url`` class property
- """
- if url.startswith('http'):
- return url
- return self.base_url + url.lstrip('./')
-
- def _filter(self, result, item):
- """
- Applies filter, if filter passes `item` is appended to `result`
-
- Args:
- result (array) : target array
- item (obj) : item that is being applied filter on
- """
- if self.filter:
- if self.filter(item):
- result.append(item)
- else:
- result.append(item)
-
- def info(self, msg):
- util.info('[%s] %s' % (self.name, msg))
-
- def error(self, msg):
- util.error('[%s] %s' % (self.name, msg))
-
-
-class cached(object):
- """
- A method decorator that can be used on any ContentProvider method
- Having this decorator means that results of such method are going
- to be cached for 24hours by default. You can pass number argument
- to decorator, for example @cached(1) would cache for 1 hour.
- """
-
- def __init__(self, ttl=24):
- self.ttl = ttl
-
- def __call__(self, f):
- def wrap(*args):
- provider = args[0]
- cache = StorageServer.StorageServer(provider.name + str(self.ttl), self.ttl)
- return cache.cacheFunction(f, *args)
-
- return wrap
diff --git a/lib/contentprovider/xbmcprovider.py b/lib/contentprovider/xbmcprovider.py
deleted file mode 100644
index f7e1401..0000000
--- a/lib/contentprovider/xbmcprovider.py
+++ /dev/null
@@ -1,464 +0,0 @@
-# * Copyright (C) 2012 Libor Zoubek
-# *
-# *
-# * This Program is free software; you can redistribute it and/or modify
-# * it under the terms of the GNU General Public License as published by
-# * the Free Software Foundation; either version 2, or (at your option)
-# * any later version.
-# *
-# * This Program is distributed in the hope that it will be useful,
-# * but WITHOUT ANY WARRANTY; without even the implied warranty of
-# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# * GNU General Public License for more details.
-# *
-# * You should have received a copy of the GNU General Public License
-# * along with this program; see the file COPYING. If not, write to
-# * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-# * http://www.gnu.org/copyleft/gpl.html
-# *
-# */
-
-import sys
-import os
-import re
-import traceback
-import util
-import xbmcutil
-import resolver
-import time
-import xbmcplugin
-import xbmc
-import xbmcvfs
-import xbmcgui
-import urllib.parse
-import urllib.request, urllib.parse, urllib.error
-from collections import defaultdict
-from provider import ResolveException
-
-
-class XBMContentProvider(object):
- '''
- ContentProvider class provides an internet content. It should NOT have any xbmc-related imports
- and must be testable without XBMC runtime. This is a basic/dummy implementation.
- '''
-
- def __init__(self, provider, settings, addon):
- '''
- XBMContentProvider constructor
- Args:
- name (str): name of provider
- '''
- self.provider = provider
- # inject current user language
- try: # not fully supported on Frodo
- provider.lang = xbmc.getLanguage(xbmc.ISO_639_1)
- except:
- provider.lang = None
- pass
- self.settings = settings
- # lang setting is optional for plugins
- if not 'lang' in self.settings:
- self.settings['lang'] = '0'
-
- util.info('Initializing provider %s with settings %s' % (provider.name, settings))
- self.addon = addon
- self.addon_id = addon.getAddonInfo('id')
- if '!download' not in self.provider.capabilities():
- self.check_setting_keys(['downloads'])
- self.cache = provider.cache
- provider.on_init()
-
- def check_setting_keys(self, keys):
- for key in keys:
- if not key in list(self.settings.keys()):
- raise Exception('Invalid settings passed - [' + key + '] setting is required')
-
- def params(self):
- return {'cp': self.provider.name}
-
- def run(self, params):
- if params == {} or params == self.params():
- return self.root()
- if 'list' in list(params.keys()):
- self.list(self.provider.list(params['list']))
- return xbmcplugin.endOfDirectory(int(sys.argv[1]))
- if 'down' in list(params.keys()):
- return self.download({'url': params['down'], 'title': params['title']})
- if 'play' in list(params.keys()):
- return self.play({'url': params['play'], 'info': params})
- if 'search-list' in list(params.keys()):
- return self.search_list()
- if 'search' in list(params.keys()):
- return self.do_search(params['search'])
- if 'search-remove' in list(params.keys()):
- return self.search_remove(params['search-remove'])
- if 'search-edit' in list(params.keys()):
- return self.search_edit(params['search-edit'])
- if self.run_custom:
- return self.run_custom(params)
-
- def search_list(self):
- params = self.params()
- params.update({'search': '#'})
- menu1 = self.params()
- menu2 = self.params()
- xbmcutil.add_dir(xbmcutil.__lang__(30004), params, xbmcutil.icon('search.png'))
- for what in xbmcutil.search_list(self.cache):
- params['search'] = what
- menu1['search-remove'] = what
- menu2['search-edit'] = what
- xbmcutil.add_dir(what, params, menuItems={xbmcutil.__lang__(
- 30016): menu2, xbmc.getLocalizedString(117): menu1})
- xbmcplugin.endOfDirectory(int(sys.argv[1]))
-
- def search_remove(self, what):
- xbmcutil.search_remove(self.cache, what)
- xbmc.executebuiltin('Container.Refresh')
-
- def search_edit(self, what):
- kb = xbmc.Keyboard(what, xbmcutil.__lang__(30003), False)
- kb.doModal()
- if kb.isConfirmed():
- replacement = kb.getText()
- xbmcutil.search_replace(self.cache, what, replacement)
- params = self.params()
- params.update({'search': replacement})
- action = xbmcutil._create_plugin_url(params)
- xbmc.executebuiltin('Container.Update(%s)' % action)
-
- def do_search(self, what):
- if what == '' or what == '#':
- kb = xbmc.Keyboard('', xbmcutil.__lang__(30003), False)
- kb.doModal()
- if kb.isConfirmed():
- what = kb.getText()
- if not what == '':
- maximum = 20
- try:
- maximum = int(self.settings['keep-searches'])
- except:
- util.error('Unable to parse convert addon setting to number')
- pass
- xbmcutil.search_add(self.cache, what, maximum)
- self.search(what)
-
- def root(self):
- searches = xbmcutil.get_searches(self.addon, self.provider.name)
- if len(searches) > 0:
- self.provider.info('Upgrading to new saved search storage...')
- for s in searches:
- self.provider.info('Moving item %s' % s)
- xbmcutil.search_add(self.cache, s, 9999999)
- xbmcutil.delete_search_history(self.addon, self.provider.name)
-
- if 'search' in self.provider.capabilities():
- params = self.params()
- params.update({'search-list': '#'})
- xbmcutil.add_dir(xbmcutil.__lang__(30003), params, xbmcutil.icon('search.png'))
- if not '!download' in self.provider.capabilities():
- xbmcutil.add_local_dir(xbmcutil.__lang__(30006), self.settings[
- 'downloads'], xbmcutil.icon('download.png'))
- self.list(self.provider.categories())
- return xbmcplugin.endOfDirectory(int(sys.argv[1]))
-
- def download(self, item):
- downloads = self.settings['downloads']
- if '' == downloads:
- xbmcgui.Dialog().ok(self.provider.name, xbmcutil.__lang__(30009))
- return
- stream = self.resolve(item['url'])
- if stream:
- if not 'headers' in list(stream.keys()):
- stream['headers'] = {}
- xbmcutil.reportUsage(self.addon_id, self.addon_id + '/download')
- # clean up \ and /
- name = item['title'].replace('/', '_').replace('\\', '_')
- if not stream['subs'] == '':
- xbmcutil.save_to_file(stream['subs'], os.path.join(
- downloads, name + '.srt'), stream['headers'])
- dot = name.find('.')
- if dot <= 0:
- # name does not contain extension, append some
- name += '.mp4'
- xbmcutil.download(self.addon, name, self.provider._url(
- stream['url']), os.path.join(downloads, name), headers=stream['headers'])
-
- def play(self, item):
- stream = self.resolve(item['url'])
- if stream:
- xbmcutil.reportUsage(self.addon_id, self.addon_id + '/play')
- if 'headers' in list(stream.keys()):
- headerStr = '|' + urllib.parse.urlencode(stream['headers'])
- if len(headerStr) > 1:
- stream['url'] += headerStr.encode('utf-8')
- print('Sending %s to player' % stream['url'])
- li = xbmcgui.ListItem(path=stream['url'])
- li.setArt({'icon': 'DefaulVideo.png'})
- il = self._extract_infolabels(item['info'])
- if len(il) > 0: # only set when something was extracted
- li.setInfo('video', il)
- try:
- local_subs = xbmcutil.set_subtitles(li, stream['subs'], stream.get('headers'))
- except:
- xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, li)
- xbmcutil.load_subtitles(stream['subs'], stream.get('headers'))
- else:
- xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, li)
-
- def _handle_exc(self, e):
- msg = e.message
- if msg.find('$') == 0:
- try:
- msg = self.addon.getLocalizedString(int(msg[1:]))
- except:
- try:
- msg = xbmcutil.__lang__(int(msg[1:]))
- except:
- pass
- xbmcgui.Dialog().ok(self.provider.name, msg)
-
- def resolve(self, url):
- item = self.provider.video_item()
- item.update({'url': url})
- try:
- return self.provider.resolve(item)
- except ResolveException as e:
- self._handle_exc(e)
-
- def search(self, keyword):
- self.list(self.provider.search(keyword))
- return xbmcplugin.endOfDirectory(int(sys.argv[1]))
-
- def list(self, items):
- params = self.params()
- for item in items:
- if item['type'] == 'dir':
- self.render_dir(item)
- elif item['type'] == 'next':
- params.update({'list': item['url']})
- xbmcutil.add_dir(xbmcutil.__lang__(30007), params, xbmcutil.icon('next.png'))
- elif item['type'] == 'prev':
- params.update({'list': item['url']})
- xbmcutil.add_dir(xbmcutil.__lang__(30008), params, xbmcutil.icon('prev.png'))
- elif item['type'] == 'new':
- params.update({'list': item['url']})
- xbmcutil.add_dir(xbmcutil.__lang__(30012), params, xbmcutil.icon('new.png'))
- elif item['type'] == 'top':
- params.update({'list': item['url']})
- xbmcutil.add_dir(xbmcutil.__lang__(30013), params, xbmcutil.icon('top.png'))
- elif item['type'] == 'video':
- self.render_video(item)
- else:
- self.render_default(item)
-
- def render_default(self, item):
- raise Exception("Unable to render item " + str(item))
-
- def render_dir(self, item):
- params = self.params()
- params.update({'list': item['url']})
- title = item['title']
- img = None
- if 'img' in list(item.keys()):
- img = item['img']
- if title.find('$') == 0:
- try:
- title = self.addon.getLocalizedString(int(title[1:]))
- except:
- pass
- menuItems = {}
- if 'menu' in list(item.keys()):
- for ctxtitle, value in item['menu'].items():
- if ctxtitle.find('$') == 0:
- try:
- ctxtitle = self.addon.getLocalizedString(int(ctxtitle[1:]))
- except:
- pass
- menuItems[ctxtitle] = value
- xbmcutil.add_dir(title, params, img, infoLabels=self._extract_infolabels(
- item), menuItems=menuItems)
-
- def _extract_infolabels(self, item):
- infoLabels = {}
- for label in ['title', 'plot', 'year', 'genre', 'rating', 'director',
- 'votes', 'cast', 'trailer', 'tvshowtitle', 'season',
- 'episode', 'duration']:
- if label in list(item.keys()):
- infoLabels[label] = util.decode_html(item[label])
- return infoLabels
-
- def render_video(self, item):
- params = self.params()
- params.update({'play': item['url']})
- downparams = self.params()
- downparams.update({'title': item['title'], 'down': item['url']})
- def_item = self.provider.video_item()
- if item['size'] == def_item['size']:
- item['size'] = ''
- else:
- item['size'] = ' (%s)' % item['size']
- title = '%s%s' % (item['title'], item['size'])
- menuItems = {}
- if "!download" not in self.provider.capabilities():
- menuItems[xbmc.getLocalizedString(33003)] = downparams
- if 'menu' in list(item.keys()):
- for ctxtitle, value in item['menu'].items():
- if ctxtitle.find('$') == 0:
- try:
- ctxtitle = self.addon.getLocalizedString(int(ctxtitle[1:]))
- except:
- pass
- menuItems[ctxtitle] = value
- xbmcutil.add_video(title,
- params,
- item['img'],
- infoLabels=self._extract_infolabels(item),
- menuItems=menuItems
- )
-
- def categories(self):
- self.list(self.provider.categories(keyword))
- return xbmcplugin.endOfDirectory(int(sys.argv[1]))
-
-
-class XBMCMultiResolverContentProvider(XBMContentProvider):
-
- def __init__(self, provider, settings, addon):
- XBMContentProvider.__init__(self, provider, settings, addon)
- self.check_setting_keys(['quality'])
-
- def resolve(self, url):
- item = self.provider.video_item()
- item.update({'url': url})
-
- def select_cb(resolved):
-
- quality = self.settings['quality'] or '0'
- filtered = resolver.filter_by_quality(resolved, quality)
- lang = self.settings['lang'] or '0'
- filtered = resolver.filter_by_language(filtered, lang)
- # if user requested something but 'ask me' or filtered result is exactly 1
- if len(filtered) == 1 or (int(quality) > 0 and int(lang) == 0):
- return filtered[0]
- # if user requested particular language and we have it
- if len(filtered) > 0 and int(lang) > 0:
- return filtered[0]
- dialog = xbmcgui.Dialog()
- opts = []
- for r in resolved:
- d = defaultdict(lambda: '', r)
- opts.append('%s [%s] %s' % (d['title'], d['quality'], d['lang']))
- ret = dialog.select(xbmcutil.__lang__(30005), opts)
- if ret >= 0:
- return resolved[ret]
- try:
- return self.provider.resolve(item, select_cb=select_cb)
- except ResolveException as e:
- self._handle_exc(e)
-
-
-class XBMCLoginRequiredContentProvider(XBMContentProvider):
-
- def root(self):
- if not self.provider.login():
- xbmcgui.Dialog().ok(self.provider.name, xbmcutil.__lang__(30011))
- else:
- return XBMContentProvider.root(self)
-
-
-class XBMCLoginOptionalContentProvider(XBMContentProvider):
-
- def __init__(self, provider, settings, addon):
- XBMContentProvider.__init__(self, provider, settings, addon)
- self.check_setting_keys(['vip'])
-
- def ask_for_captcha(self, params):
- img = os.path.join(str(xbmcvfs.translatePath(
- self.addon.getAddonInfo('profile'))), 'captcha.png')
- util.save_to_file(params['img'], img)
- cd = CaptchaDialog('captcha-dialog.xml',
- xbmcutil.__addon__.getAddonInfo('path'), 'default', '0')
- cd.image = img
- xbmc.sleep(3000)
- cd.doModal()
- del cd
- kb = xbmc.Keyboard('', self.addon.getLocalizedString(200), False)
- kb.doModal()
- if kb.isConfirmed():
- print('got code ' + kb.getText())
- return kb.getText()
-
- def ask_for_account_type(self):
- if len(self.provider.username) == 0:
- util.info('Username is not set, NOT using VIP account')
- return False
- if self.settings['vip'] == '0':
- util.info('Asking user whether to use VIP account')
- ret = xbmcgui.Dialog().yesno(self.provider.name, xbmcutil.__lang__(30010))
- return ret == 1
- return self.settings['vip'] == '1'
-
- def resolve(self, url):
- item = self.provider.video_item()
- item.update({'url': url})
- if not self.ask_for_account_type():
- # set user/pass to null - user does not want to use VIP at this time
- self.provider.username = None
- self.provider.password = None
- else:
- if not self.provider.login():
- xbmcgui.Dialog().ok(self.provider.name, xbmcutil.__lang__(30011))
- return
- try:
- return self.provider.resolve(item, captcha_cb=self.ask_for_captcha)
- except ResolveException as e:
- self._handle_exc(e)
-
-
-class XBMCLoginOptionalDelayedContentProvider(XBMCLoginOptionalContentProvider):
-
- def wait_cb(self, wait):
- left = wait
- msg = xbmcutil.__lang__(30014).encode('utf-8')
- while left > 0:
- xbmc.executebuiltin("XBMC.Notification(%s,%s,1000,%s)" %
- (self.provider.name, msg % str(left), ''))
- left -= 1
- time.sleep(1)
-
- def resolve(self, url):
- item = self.video_item()
- item.update({'url': url})
- if not self.ask_for_account_type():
- # set user/pass to null - user does not want to use VIP at this time
- self.provider.username = None
- self.provider.password = None
- else:
- if not self.provider.login():
- xbmcgui.Dialog().ok(self.provider.name, xbmcutil.__lang__(30011))
- return
- try:
- return self.provider.resolve(item, captcha_cb=self.ask_for_captcha, wait_cb=self.wait_cb)
- except ResolveException as e:
- self._handle_exc(e)
-
-
-class CaptchaDialog (xbmcgui.WindowXMLDialog):
-
- def __init__(self, *args, **kwargs):
- super(xbmcgui.WindowXMLDialog, self).__init__(args, kwargs)
- self.image = None
-
- def onFocus(self, controlId):
- self.controlId = controlId
-
- def onInit(self):
- self.getControl(101).setImage(self.image)
-
- def onAction(self, action):
- if action.getId() in [9, 10]:
- self.close()
-
- def onClick(self, controlId):
- if controlId == 102:
- self.close()
diff --git a/lib/crypto/__init__.py b/lib/crypto/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/lib/crypto/__pycache__/__init__.cpython-38.opt-1.pyc b/lib/crypto/__pycache__/__init__.cpython-38.opt-1.pyc
deleted file mode 100644
index ea61905..0000000
Binary files a/lib/crypto/__pycache__/__init__.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/crypto/__pycache__/md5crypt.cpython-38.opt-1.pyc b/lib/crypto/__pycache__/md5crypt.cpython-38.opt-1.pyc
deleted file mode 100644
index dcc6efa..0000000
Binary files a/lib/crypto/__pycache__/md5crypt.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/crypto/md5crypt.py b/lib/crypto/md5crypt.py
deleted file mode 100644
index 8023187..0000000
--- a/lib/crypto/md5crypt.py
+++ /dev/null
@@ -1,75 +0,0 @@
-import hashlib
-
-MAGIC = '$1$'
-ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
-
-def to64(v, n):
- ret = ''
- while n > 0:
- ret += ITOA64[v & 0x3f]
- v >>= 6
- n -= 1
- return ret
-
-def apache_md5_crypt(pw, salt):
- return unix_md5_crypt(pw, salt, '$apr1$')
-
-def unix_md5_crypt(pw, salt, magic=None):
- if magic is None:
- magic = MAGIC
-
- if salt.startswith(magic):
- salt = salt[len(magic):]
-
- salt = salt.split('$', 1)[0][:8]
-
- pw_bytes = pw.encode('utf-8')
- salt_bytes = salt.encode('utf-8')
- magic_bytes = magic.encode('utf-8')
-
- ctx = pw_bytes + magic_bytes + salt_bytes
- final = hashlib.md5(pw_bytes + salt_bytes + pw_bytes).digest()
-
- for pl in range(len(pw_bytes), 0, -16):
- ctx += final[:min(16, pl)]
-
- i = len(pw_bytes)
- while i:
- if i & 1:
- ctx += b'\x00'
- else:
- ctx += pw_bytes[:1]
- i >>= 1
-
- final = hashlib.md5(ctx).digest()
-
- for i in range(1000):
- ctx1 = b''
- if i & 1:
- ctx1 += pw_bytes
- else:
- ctx1 += final
- if i % 3:
- ctx1 += salt_bytes
- if i % 7:
- ctx1 += pw_bytes
- if i & 1:
- ctx1 += final
- else:
- ctx1 += pw_bytes
- final = hashlib.md5(ctx1).digest()
-
- passwd = ''
- passwd += to64((final[0] << 16) | (final[6] << 8) | final[12], 4)
- passwd += to64((final[1] << 16) | (final[7] << 8) | final[13], 4)
- passwd += to64((final[2] << 16) | (final[8] << 8) | final[14], 4)
- passwd += to64((final[3] << 16) | (final[9] << 8) | final[15], 4)
- passwd += to64((final[4] << 16) | (final[10] << 8) | final[5], 4)
- passwd += to64(final[11], 2)
-
- return magic + salt + '$' + passwd
-
-md5crypt = unix_md5_crypt
-
-if __name__ == "__main__":
- print(unix_md5_crypt("cat", "hat"))
diff --git a/lib/resolver.py b/lib/resolver.py
deleted file mode 100644
index 063f107..0000000
--- a/lib/resolver.py
+++ /dev/null
@@ -1,289 +0,0 @@
-# -*- coding: UTF-8 -*-
-# * Copyright (C) 2011 Libor Zoubek
-# *
-# *
-# * This Program is free software; you can redistribute it and/or modify
-# * it under the terms of the GNU General Public License as published by
-# * the Free Software Foundation; either version 2, or (at your option)
-# * any later version.
-# *
-# * This Program is distributed in the hope that it will be useful,
-# * but WITHOUT ANY WARRANTY; without even the implied warranty of
-# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# * GNU General Public License for more details.
-# *
-# * You should have received a copy of the GNU General Public License
-# * along with this program; see the file COPYING. If not, write to
-# * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-# * http://www.gnu.org/copyleft/gpl.html
-# *
-# */
-
-import sys
-import os
-import re
-import traceback
-
-import util
-
-sys.path.append(os.path.join(os.path.dirname(__file__), 'server'))
-
-RESOLVERS = []
-util.debug('%s searching for modules' % __name__)
-for module in os.listdir(os.path.join(os.path.dirname(__file__), 'server')):
- if module == '__init__.py' or module[-3:] != '.py':
- continue
- module = module[:-3]
- exec('import %s' % module)
- resolver = eval(module)
- util.debug('found %s %s' % (resolver, dir(resolver)))
-
- if not hasattr(resolver, '__priority__'):
- resolver.__priority__ = 0
- RESOLVERS.append(resolver)
- del module
-RESOLVERS = sorted(RESOLVERS, key=lambda m: -m.__priority__)
-util.debug('done')
-
-
-def item():
- return {'name': '', 'url': '', 'quality': '???', 'surl': '', 'subs': '', 'headers': {}}
-
-
-def resolve(url):
- """
- resolves given url by asking all resolvers
-
- returns None if no resolver advised to be able to resolve this url
- returns False if resolver did his job, but did not return any value (thus failed)
- returns Array of resolved objects in positive usecase
- """
- url = util.decode_html(url)
- util.info('Resolving ' + url)
- resolver = _get_resolver(url)
- value = None
- if resolver is None:
- return None
- util.info('Using resolver \'%s\'' % str(resolver.__name__));
- try:
- value = resolver.resolve(url)
- except:
- traceback.print_exc()
- if value is None:
- return False
- default = item()
-
- def fix_stream(i, url, resolver, default):
- """ fix missing but required values """
- if 'name' not in list(i.keys()):
- i['name'] = resolver.__name__
- if 'surl' not in list(i.keys()):
- i['surl'] = url
- for key in list(default.keys()):
- if key not in list(i.keys()):
- i[key] = default[key]
-
- [fix_stream(i, url, resolver, default) for i in value]
- return sorted(value, key=lambda i: i['quality'])
-
-
-def _get_resolver(url):
- util.debug('Get resolver for ' + url)
- for r in RESOLVERS:
- util.debug('querying %s' % r)
- if r.supports(url):
- return r
-
-
-def can_resolve(url):
- """ Returns true if we are able to resolve stream by given URL """
- return _get_resolver(url) is not None
-
-
-def filter_resolvable(url):
- if url.find('facebook') > 0 or url.find('yield') > 0:
- return
- return url.strip('\'\"')
-
-
-def findstreams(data, regexes=None):
- """
- Finds streams in given data. Respects caller add-on settings about
- quality and asks user if necessary.
-
- :param data: A string (piece of text / HTML code), an array of URLs or an
- array of dictionaries, where 'url' key stores actual URL and
- all other keys not present in item() are being copied to the
- resolved stream dictionary
- :param regexes: An array of strings - regular expressions, each MUST define
- named group called 'url', which retrieves resolvable URL
- (that one is passed to resolve operation); only used
- with 'data' of type 'string'
- :returns: An array of resolved objects, None if at least 1 resolver failed
- to resolve and nothing else was found, an empty array if no
- resolvers for URLs has been found or False if none of regexes
- found anything
- """
-
- def get_url(obj):
- return obj['url'] if isinstance(obj, dict) else obj
-
- urls = []
- resolvables = []
- resolved = []
- not_found = False
- if isinstance(data, str) and regexes:
- for regex in regexes:
- for match in re.finditer(regex, data, re.IGNORECASE | re.DOTALL):
- urls.append(match.group('url'))
- elif isinstance(data, list):
- urls = data
- else:
- raise TypeError
- for url in urls:
- if isinstance(url, dict):
- url['url'] = filter_resolvable(url['url'])
- else:
- url = filter_resolvable(url)
- if url and url not in resolvables:
- util.info('Found resolvable ' + get_url(url))
- resolvables.append(url)
- if len(resolvables) == 0:
- util.info('No resolvables found!')
- return False
- for url in resolvables:
- streams = resolve(get_url(url))
- if streams is None:
- util.info('No resolver found for ' + get_url(url))
- not_found = True
- elif not streams:
- util.info('There was an error resolving ' + get_url(url))
- elif len(streams) > 0:
- for stream in streams:
- if isinstance(url, dict):
- for key in list(url.keys()):
- if key not in stream:
- stream[key] = url[key]
- elif key not in item():
- if isinstance(stream[key], str) and \
- isinstance(url[key], str):
- stream[key] = url[key] + ' +' + stream[key]
- elif isinstance(stream[key], list) and \
- isinstance(url[key], list):
- stream[key] = url[key] + stream[key]
- elif isinstance(stream[key], dict) and \
- isinstance(url[key], dict):
- stream[key].update(url[key])
- resolved.append(stream)
- if len(resolved) == 0:
- if not_found:
- return []
- return None
- resolved = sorted(resolved, key=lambda i: i['quality'])
- resolved = sorted(resolved, key=lambda i: len(i['quality']))
- resolved.reverse()
- return resolved
-
-
-q_map = {'3': '720p', '4': '480p', '5': '360p'}
-
-
-def filter_by_quality(resolved, q):
- util.info('filtering by quality setting ' + q)
- if q == '0':
- return resolved
- sources = {}
- ret = []
- # first group streams by source url
- for item in resolved:
- if item['surl'] in list(sources.keys()):
- sources[item['surl']].append(item)
- else:
- sources[item['surl']] = [item]
- if q == '1':
- # always return best quality from each source
- for key in list(sources.keys()):
- ret.append(sources[key][0])
- elif q == '2':
- # always return worse quality from each source
- for key in list(sources.keys()):
- ret.append(sources[key][-1])
- else:
- # we try to select sources of desired qualities
- quality = q_map[q]
- # 3,4,5 are 720,480,360
- for key in list(sources.keys()):
- added = False
- for item in sources[key]:
- if quality == item['quality']:
- ret.append(item)
- added = True
- if not added:
- util.debug('Desired quality %s not found, adding best found' % quality)
- ret.append(sources[key][-1])
- # sort results again, so best quality streams appear first
- ret = sorted(ret, key=lambda i: i['quality'])
- if not q == '2':
- ret.reverse()
- return ret
-
-def filter_by_language(resolved, lang):
- util.info('filtering by language setting ' + lang)
- if lang == '0':
- return resolved
- ret = []
- # first group streams by source url
- for item in resolved:
- if 'lang' in item and item['lang'] != '':
- util.info(item)
- if lang == '1' and re.match('en', item['lang'], re.IGNORECASE):
- ret.append(item)
- if lang == '2' and re.match('cs|cz|čeština', item['lang'], re.IGNORECASE):
- ret.append(item)
- return ret
-
-def findstreams_multi(data, regexes):
- """
- Finds streams in given data according to given regexes
- respects caller addon's setting about desired quality, asks user if needed
- assumes, that all resolvables need to be returned, but in particular quality
- @param data piece of text (HTML code) to search in
- @param regexes - array of strings - regular expressions, each MUST define named group called 'url'
- which retrieves resolvable URL (that one is passsed to resolve operation)
- @return array of dictionaries with keys: name,url,quality,surl
- @return None if at least 1 resoler failed to resolve and nothing else has been found
- @return [] if no resolvable URLs or no resolvers for URL has been found
- """
- resolved = []
- # keep list of found urls to aviod having duplicates
- urls = []
- error = False
- for regex in regexes:
- for match in re.finditer(regex, data, re.IGNORECASE | re.DOTALL):
- print('Found resolvable %s ' % match.group('url'))
- streams = resolve(match.group('url'))
- if isinstance(streams, list) and streams:
- util.debug('There was an error resolving ' + match.group('url'))
- error = True
- if streams is not None:
- if len(streams) > 0:
- for stream in streams:
- resolved.append(stream)
- if error and len(resolved) == 0:
- return None
- if len(resolved) == 0:
- return []
- resolved = sorted(resolved, key=lambda i: i['quality'])
- resolved = sorted(resolved, key=lambda i: len(i['quality']))
- resolved2 = resolved
- resolved2.reverse()
- qualities = {}
- for item in resolved2:
- if item['quality'] in list(qualities.keys()):
- qualities[item['quality']].append(item)
- else:
- qualities[item['quality']] = [item]
- # now .. we must sort items to be in same order as they were found on page
- for q in list(qualities.keys()):
- qualities[q] = sorted(qualities[q], key=lambda i: resolved.index(i))
- return qualities
diff --git a/lib/search.py b/lib/search.py
deleted file mode 100644
index 69b727f..0000000
--- a/lib/search.py
+++ /dev/null
@@ -1,76 +0,0 @@
-
-# -*- coding: UTF-8 -*-
-#/*
-# * Copyright (C) 2011 Libor Zoubek
-# *
-# *
-# * This Program is free software; you can redistribute it and/or modify
-# * it under the terms of the GNU General Public License as published by
-# * the Free Software Foundation; either version 2, or (at your option)
-# * any later version.
-# *
-# * This Program is distributed in the hope that it will be useful,
-# * but WITHOUT ANY WARRANTY; without even the implied warranty of
-# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# * GNU General Public License for more details.
-# *
-# * You should have received a copy of the GNU General Public License
-# * along with this program; see the file COPYING. If not, write to
-# * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-# * http://www.gnu.org/copyleft/gpl.html
-# *
-# */
-import os,re,sys
-import xbmcplugin,xbmcaddon,xbmc
-import xbmcutil,util
-
-def _list(addon,history,key,value):
- params = {}
- menuItems = {}
- if key:
- params[key] = value
- menuItems[key] = value
- params['search'] = '#'
- xbmcutil.add_dir(xbmcutil.__lang__(30004),params,xbmcutil.icon('search.png'))
- for what in xbmcutil.get_searches(addon,history):
- params['search'] = what
- menuItems['search-remove'] = what
- xbmcutil.add_dir(what,params,menuItems={xbmc.getLocalizedString(117):menuItems})
- xbmcplugin.endOfDirectory(int(sys.argv[1]))
-
-def _remove(addon,history,search):
- xbmcutil.remove_search(addon,history,search)
- xbmc.executebuiltin('Container.Refresh')
-
-def _search(addon,history,what,update_history,callback):
- if what == '' or what == '#':
- kb = xbmc.Keyboard('',xbmcutil.__lang__(30003),False)
- kb.doModal()
- if kb.isConfirmed():
- what = kb.getText()
- if not what == '':
- maximum = 20
- try:
- maximum = int(addon.getSetting('keep-searches'))
- except:
- util.error('Unable to parse convert addon setting to number')
- pass
- if update_history:
- xbmcutil.add_search(addon,history,what,maximum)
- callback(what)
-
-def item(items={},label=xbmcutil.__lang__(30003)):
- items['search-list'] = '#'
- xbmcutil.add_dir(label,items,xbmcutil.icon('search.png'))
-
-def main(addon,history,p,callback,key=None,value=None):
- if (key==None) or (key in p and p[key] == value):
- if 'search-list' in list(p.keys()):
- _list(addon,history,key,value)
- if 'search' in list(p.keys()):
- update_history=True
- if 'search-no-history' in list(p.keys()):
- update_history=False
- _search(addon,history,p['search'],update_history,callback)
- if 'search-remove' in list(p.keys()):
- _remove(addon,history,p['search-remove'])
diff --git a/lib/server/__init__.py b/lib/server/__init__.py
deleted file mode 100644
index 56e0887..0000000
--- a/lib/server/__init__.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#/*
-# * Copyright (C) 2011 Libor Zoubek
-# *
-# *
-# * This Program is free software; you can redistribute it and/or modify
-# * it under the terms of the GNU General Public License as published by
-# * the Free Software Foundation; either version 2, or (at your option)
-# * any later version.
-# *
-# * This Program is distributed in the hope that it will be useful,
-# * but WITHOUT ANY WARRANTY; without even the implied warranty of
-# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# * GNU General Public License for more details.
-# *
-# * You should have received a copy of the GNU General Public License
-# * along with this program; see the file COPYING. If not, write to
-# * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-# * http://www.gnu.org/copyleft/gpl.html
-# *
-# */
-
-
-##########################################################3
-# all resolvers modules in this directory must have following methods:
-
-# __name__ - name of the resolver module - can override module filename
-# def supports(url) - returns true iff resolver is able to resolve url to stream otherwise false
-# def resolve(url) - returns array of all hashmaps that were resolved
-# - if resolving fails, nothing is returned
-# - a hash MUST contain key 'url' - it's value is stream URL
-# - optional keys are 'subs' (link to subtitle), 'quality' (quality string like '240p' or just 'HD'
diff --git a/lib/server/__pycache__/anyfilesresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/anyfilesresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 5d00482..0000000
Binary files a/lib/server/__pycache__/anyfilesresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/dailymotionresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/dailymotionresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index a522930..0000000
Binary files a/lib/server/__pycache__/dailymotionresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/divxstageresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/divxstageresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 503d788..0000000
Binary files a/lib/server/__pycache__/divxstageresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/eserialresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/eserialresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 0335f11..0000000
Binary files a/lib/server/__pycache__/eserialresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/exashareresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/exashareresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 3fe3e38..0000000
Binary files a/lib/server/__pycache__/exashareresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/flashxresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/flashxresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index aef6817..0000000
Binary files a/lib/server/__pycache__/flashxresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/gosuparkresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/gosuparkresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 9394260..0000000
Binary files a/lib/server/__pycache__/gosuparkresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/hqqresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/hqqresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 2b06755..0000000
Binary files a/lib/server/__pycache__/hqqresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/koukejseresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/koukejseresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index da93aaf..0000000
Binary files a/lib/server/__pycache__/koukejseresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/koukniresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/koukniresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 73fdbb3..0000000
Binary files a/lib/server/__pycache__/koukniresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/ksetresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/ksetresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 5e7dd9b..0000000
Binary files a/lib/server/__pycache__/ksetresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/letwatch.cpython-38.opt-1.pyc b/lib/server/__pycache__/letwatch.cpython-38.opt-1.pyc
deleted file mode 100644
index 600508d..0000000
Binary files a/lib/server/__pycache__/letwatch.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/mixturevideoresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/mixturevideoresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index a7cf04c..0000000
Binary files a/lib/server/__pycache__/mixturevideoresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/moevideoresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/moevideoresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index a9409da..0000000
Binary files a/lib/server/__pycache__/moevideoresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/mojevideosk.cpython-38.opt-1.pyc b/lib/server/__pycache__/mojevideosk.cpython-38.opt-1.pyc
deleted file mode 100644
index e42f064..0000000
Binary files a/lib/server/__pycache__/mojevideosk.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/movshareresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/movshareresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index aed5b98..0000000
Binary files a/lib/server/__pycache__/movshareresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/munkvideoresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/munkvideoresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 24adaeb..0000000
Binary files a/lib/server/__pycache__/munkvideoresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/myviruresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/myviruresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index f538c42..0000000
Binary files a/lib/server/__pycache__/myviruresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/nahnojiresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/nahnojiresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index d7f5911..0000000
Binary files a/lib/server/__pycache__/nahnojiresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/novamovresovler.cpython-38.opt-1.pyc b/lib/server/__pycache__/novamovresovler.cpython-38.opt-1.pyc
deleted file mode 100644
index 944d12d..0000000
Binary files a/lib/server/__pycache__/novamovresovler.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/openload.cpython-38.opt-1.pyc b/lib/server/__pycache__/openload.cpython-38.opt-1.pyc
deleted file mode 100644
index fd96ad2..0000000
Binary files a/lib/server/__pycache__/openload.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/playedtoresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/playedtoresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 04ba62f..0000000
Binary files a/lib/server/__pycache__/playedtoresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/playmdresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/playmdresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 481c619..0000000
Binary files a/lib/server/__pycache__/playmdresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/publicvideohostresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/publicvideohostresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index c216658..0000000
Binary files a/lib/server/__pycache__/publicvideohostresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/putlockerresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/putlockerresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index df68aca..0000000
Binary files a/lib/server/__pycache__/putlockerresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/rutuberesolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/rutuberesolver.cpython-38.opt-1.pyc
deleted file mode 100644
index d117486..0000000
Binary files a/lib/server/__pycache__/rutuberesolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/servertipczresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/servertipczresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index d3f48c5..0000000
Binary files a/lib/server/__pycache__/servertipczresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/sledujuserialyresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/sledujuserialyresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index a0fb6cc..0000000
Binary files a/lib/server/__pycache__/sledujuserialyresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/stagevuresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/stagevuresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 4aa8c81..0000000
Binary files a/lib/server/__pycache__/stagevuresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/streamcloudresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/streamcloudresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 592973e..0000000
Binary files a/lib/server/__pycache__/streamcloudresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/streamintoresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/streamintoresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 5f8114b..0000000
Binary files a/lib/server/__pycache__/streamintoresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/streamujtvresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/streamujtvresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 9b170a8..0000000
Binary files a/lib/server/__pycache__/streamujtvresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/trivialresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/trivialresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 4e20ed5..0000000
Binary files a/lib/server/__pycache__/trivialresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/videobbresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/videobbresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 16ce114..0000000
Binary files a/lib/server/__pycache__/videobbresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/videomailresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/videomailresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 35820c9..0000000
Binary files a/lib/server/__pycache__/videomailresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/videonetresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/videonetresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index da71741..0000000
Binary files a/lib/server/__pycache__/videonetresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/videoweedresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/videoweedresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 2e4d672..0000000
Binary files a/lib/server/__pycache__/videoweedresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/videozerresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/videozerresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 547c3f2..0000000
Binary files a/lib/server/__pycache__/videozerresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/videram.cpython-38.opt-1.pyc b/lib/server/__pycache__/videram.cpython-38.opt-1.pyc
deleted file mode 100644
index bfeed34..0000000
Binary files a/lib/server/__pycache__/videram.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/vimeoresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/vimeoresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 13ba13f..0000000
Binary files a/lib/server/__pycache__/vimeoresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/vkontakteresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/vkontakteresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 5cf3ed8..0000000
Binary files a/lib/server/__pycache__/vkontakteresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/vuuzlaresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/vuuzlaresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 1970332..0000000
Binary files a/lib/server/__pycache__/vuuzlaresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/youtuberesolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/youtuberesolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 7fa170c..0000000
Binary files a/lib/server/__pycache__/youtuberesolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/youwatch.cpython-38.opt-1.pyc b/lib/server/__pycache__/youwatch.cpython-38.opt-1.pyc
deleted file mode 100644
index 63e4e6e..0000000
Binary files a/lib/server/__pycache__/youwatch.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/zideonlresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/zideonlresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 08a0b43..0000000
Binary files a/lib/server/__pycache__/zideonlresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/__pycache__/zkouknitoresolver.cpython-38.opt-1.pyc b/lib/server/__pycache__/zkouknitoresolver.cpython-38.opt-1.pyc
deleted file mode 100644
index 53df311..0000000
Binary files a/lib/server/__pycache__/zkouknitoresolver.cpython-38.opt-1.pyc and /dev/null differ
diff --git a/lib/server/anyfilesresolver.py b/lib/server/anyfilesresolver.py
deleted file mode 100644
index c6fec63..0000000
--- a/lib/server/anyfilesresolver.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# -*- coding: UTF-8 -*-
-# * GNU General Public License for more details.
-# *
-# *
-# * You should have received a copy of the GNU General Public License
-# * along with this program; see the file COPYING. If not, write to
-# * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-# * http://www.gnu.org/copyleft/gpl.html
-# *
-# *
-# * thanks to http://code.google.com/p/sd-xbmc/
-# */
-
-import re
-import urllib.request, urllib.parse, urllib.error
-import urllib.request, urllib.error, urllib.parse
-import random
-import decimal
-
-import util
-
-__name__='anyfiles'
-
-BASE_URL = 'http://video.anyfiles.pl'
-
-def supports(url):
- return not _regex(url) == None
-
-def _gen_random_decimal(i, d):
- return decimal.Decimal('%d.%d' % (random.randint(0, i), random.randint(0, d)))
-
-
-def _decode(param):
- #-- define variables
- loc_3 = [0,0,0,0]
- loc_4 = [0,0,0]
- loc_2 = ''
- #-- define hash parameters for decoding
- dec = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
- hash1 = ["L", "y", "c", "X", "2", "M", "a", "l", "p", "5", "Q", "e", "R", "t", "Z", "Y", "9", "m", "d", "0", "s", "V", "b", "3", "7", "="]
- hash2 = ["i", "B", "v", "U", "H", "4", "D", "n", "k", "8", "x", "T", "u", "G", "w", "f", "N", "J", "6", "W", "1", "g", "z", "o", "I", "r"]
- hash1 = ["c", "u", "4", "V", "z", "5", "k", "m", "y", "p", "L", "J", "I", "d", "0", "M", "9", "e", "3", "8", "v", "l", "i", "7", "n", "="];
- hash2 = ["t", "Y", "T", "x", "B", "g", "G", "b", "2", "X", "1", "R", "a", "N", "w", "Q", "f", "W", "U", "D", "Z", "s", "6", "H", "o", "r"]
-
- #-- decode
- for i in range(0, len(hash1)):
- re1 = hash1[i]
- re2 = hash2[i]
-
- param = param.replace(re1, '___')
- param = param.replace(re2, re1)
- param = param.replace('___', re2)
-
- i = 0
- while i < len(param):
- j = 0
- while j < 4 and i+j < len(param):
- loc_3[j] = dec.find(param[i+j])
- j = j + 1
-
- loc_4[0] = (loc_3[0] << 2) + ((loc_3[1] & 48) >> 4);
- loc_4[1] = ((loc_3[1] & 15) << 4) + ((loc_3[2] & 60) >> 2);
- loc_4[2] = ((loc_3[2] & 3) << 6) + loc_3[3];
-
- j = 0
- while j < 3:
- if loc_3[j + 1] == 64:
- break
- try:
- loc_2 += chr(loc_4[j])
- except:
- pass
- j = j + 1
-
- i = i + 4;
-
- return loc_2
-
-def resolve(url):
- m = _regex(url)
- if m:
- resp = urllib.request.urlopen(url)
- sessc = resp.headers.get('Set-Cookie').split(';')[0]
- resp.close()
- furl = "%s/w.jsp?id=%s&width=620&height=349&pos=&skin=0" % (BASE_URL,m.group('id'))
- headers = {'Cookie':sessc, 'Referer':url}
- data = util.request(furl,headers)
- m1 = re.search('document.cookie = "([^"]+?)"',data)
- m2 = re.search('src="(\/pcsevlet\?code=[^"]+)', data)
- if m1 and m2:
- headers['Cookie'] = headers['Cookie'] + '; ' + m1.group(1)
- headers['Referer'] = BASE_URL + '/flowplayer/flowplayer.commercial-3.2.16.swf'
- data = util.request(BASE_URL + m2.group(1),headers)
- m_vurl = re.search("'url':.*?'(http[^']+?mp4)'", data, re.DOTALL)
- m_surl = re.search("'captionUrl':.*?'(http[^']+)'",data, re.DOTALL)
- if m_vurl:
- resolved = {'url':m_vurl.group(1).strip(),'quality':'???'}
- if m_surl:
- resolved['subs'] = m_surl.group(1).strip()
- return [resolved]
- else:
- return []
-def _regex(url):
- return re.search('video\.anyfiles\.pl/w\.jsp\?id=(?P\d+)',url,re.IGNORECASE | re.DOTALL)
diff --git a/lib/server/dailymotionresolver.py b/lib/server/dailymotionresolver.py
deleted file mode 100644
index 538db52..0000000
--- a/lib/server/dailymotionresolver.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# -*- coding: UTF-8 -*-
-# *
-# *
-# * This Program is free software; you can redistribute it and/or modify
-# * it under the terms of the GNU General Public License as published by
-# * the Free Software Foundation; either version 2, or (at your option)
-# * any later version.
-# *
-# * This Program is distributed in the hope that it will be useful,
-# * but WITHOUT ANY WARRANTY; without even the implied warranty of
-# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# * GNU General Public License for more details.
-# *
-# * You should have received a copy of the GNU General Public License
-# * along with this program; see the file COPYING. If not, write to
-# * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-# * http://www.gnu.org/copyleft/gpl.html
-# *
-
-import re
-from xml.etree import ElementTree
-import util
-from copy import deepcopy
-import json
-
-__name__ = 'dailymotion'
-
-
-def supports(url):
- return re.search(r'dailymotion.com/embed', url) is not None
-
-
-def resolve(url):
- print('The url is ::', url)
- id = re.search(r'dailymotion.com/embed/video/(.+)', url).group(1)
- print('The id is ::', id)
- headers = {'User-Agent': 'Android'}
- cookie = {'Cookie': "lang=en; ff=off"}
- r = util.request("http://www.dailymotion.com/player/metadata/video/" + id,
- headers)
- content = json.loads(r)
- cc = content['qualities']
- cc = list(cc.items())
-
- cc = sorted(cc, reverse=True)
- m_url = ''
- other_playable_url = []
-
- items = []
- result = []
-
- for source, json_source in cc:
- source = source.split("@")[0]
- for item in json_source:
-
- m_url = item.get('url', None)
- # xbmc.log("DAILYMOTION - m_url = %s" % m_url, xbmc.LOGNOTICE)
- if m_url:
- if source == "auto":
- continue
-
- elif '.mnft' in m_url:
- continue
-
- if 'video' in item.get('type', None):
- item = {}
- item['url'] = m_url
- item['quality'] = source
- item['title'] = 'video'
- items.append(item)
-
- other_playable_url.append(m_url)
-
- if items:
- for item in items:
- newitem = deepcopy(item)
- item['lang'] = '???'
- item['headers'] = headers
- result.append(newitem)
- if not result and cc[0][0]=='auto':
- json_source=cc[0][1]
- m_url=json_source[0].get('url', None)
- r = util.request(m_url)
- streams = re.compile(r'RESOLUTION=\d+x(\d+).*\n([^\s]+)').findall(r)
- for quality, url in streams:
- item = {}
- item['url'] = url
- item['quality'] = quality + 'p'
- item['title'] = 'video'
- result.append(item)
- return result
diff --git a/lib/server/divxstageresolver.py b/lib/server/divxstageresolver.py
deleted file mode 100644
index 44d520d..0000000
--- a/lib/server/divxstageresolver.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# -*- coding: UTF-8 -*-
-#/*
-# * Copyright (C) 2011 Libor Zoubek
-# *
-# *
-# * This Program is free software; you can redistribute it and/or modify
-# * it under the terms of the GNU General Public License as published by
-# * the Free Software Foundation; either version 2, or (at your option)
-# * any later version.
-# *
-# * This Program is distributed in the hope that it will be useful,
-# * but WITHOUT ANY WARRANTY; without even the implied warranty of
-# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# * GNU General Public License for more details.
-# *
-# * You should have received a copy of the GNU General Public License
-# * along with this program; see the file COPYING. If not, write to
-# * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-# * http://www.gnu.org/copyleft/gpl.html
-# *
-# */
-import re,util,resolver
-__name__ = 'divxstage'
-def supports(url):
- return not _regex(url) == None
-
-# returns the steam url
-def resolve(url):
- if not _regex(url) == None:
- data = util.substr(util.request(url),'