parent
48c993a4e7
commit
bc82711886
@ -4,7 +4,9 @@ pytest
|
|||||||
pytest-cov
|
pytest-cov
|
||||||
pytest-timeout
|
pytest-timeout
|
||||||
python-dateutil
|
python-dateutil
|
||||||
|
pysocks
|
||||||
requests
|
requests
|
||||||
git+https://github.com/tamland/kodi-plugin-routing@master#egg=routing
|
git+https://github.com/tamland/kodi-plugin-routing@master#egg=routing
|
||||||
six
|
six
|
||||||
sakee
|
sakee
|
||||||
|
win-inet-pton; platform_system=="Windows"
|
@ -17,6 +17,7 @@ try: # Python 3
|
|||||||
from html import unescape
|
from html import unescape
|
||||||
except ImportError: # Python 2
|
except ImportError: # Python 2
|
||||||
from HTMLParser import HTMLParser
|
from HTMLParser import HTMLParser
|
||||||
|
|
||||||
unescape = HTMLParser().unescape
|
unescape = HTMLParser().unescape
|
||||||
|
|
||||||
ADDON = xbmcaddon.Addon()
|
ADDON = xbmcaddon.Addon()
|
||||||
@ -478,6 +479,67 @@ def set_global_setting(key, value):
|
|||||||
return jsonrpc(method='Settings.SetSettingValue', params={'setting': key, 'value': value})
|
return jsonrpc(method='Settings.SetSettingValue', params={'setting': key, 'value': value})
|
||||||
|
|
||||||
|
|
||||||
|
def has_socks():
|
||||||
|
"""Test if socks is installed, and use a static variable to remember"""
|
||||||
|
if hasattr(has_socks, 'cached'):
|
||||||
|
return getattr(has_socks, 'cached')
|
||||||
|
try:
|
||||||
|
import socks # noqa: F401; pylint: disable=unused-variable,unused-import
|
||||||
|
except ImportError:
|
||||||
|
has_socks.cached = False
|
||||||
|
return None # Detect if this is the first run
|
||||||
|
has_socks.cached = True
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def get_proxies():
|
||||||
|
"""Return a usable proxies dictionary from Kodi proxy settings"""
|
||||||
|
# Use proxy settings from environment variables
|
||||||
|
env_http_proxy = os.environ.get('HTTP_PROXY')
|
||||||
|
env_https_proxy = os.environ.get('HTTPS_PROXY')
|
||||||
|
if env_http_proxy:
|
||||||
|
return {'http': env_http_proxy, 'https': env_https_proxy or env_http_proxy}
|
||||||
|
|
||||||
|
usehttpproxy = get_global_setting('network.usehttpproxy')
|
||||||
|
if usehttpproxy is not True:
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
httpproxytype = int(get_global_setting('network.httpproxytype'))
|
||||||
|
except ValueError:
|
||||||
|
httpproxytype = 0
|
||||||
|
|
||||||
|
socks_supported = has_socks()
|
||||||
|
if httpproxytype != 0 and not socks_supported:
|
||||||
|
# Only open the dialog the first time (to avoid multiple popups)
|
||||||
|
if socks_supported is None:
|
||||||
|
ok_dialog('', localize(30966)) # Requires PySocks
|
||||||
|
return None
|
||||||
|
|
||||||
|
proxy_types = ['http', 'socks4', 'socks4a', 'socks5', 'socks5h']
|
||||||
|
|
||||||
|
proxy = {
|
||||||
|
'scheme': proxy_types[httpproxytype] if 0 <= httpproxytype < 5 else 'http',
|
||||||
|
'server': get_global_setting('network.httpproxyserver'),
|
||||||
|
'port': get_global_setting('network.httpproxyport'),
|
||||||
|
'username': get_global_setting('network.httpproxyusername'),
|
||||||
|
'password': get_global_setting('network.httpproxypassword')
|
||||||
|
}
|
||||||
|
|
||||||
|
if proxy.get('username') and proxy.get('password') and proxy.get('server') and proxy.get('port'):
|
||||||
|
proxy_address = '{scheme}://{username}:{password}@{server}:{port}'.format(**proxy)
|
||||||
|
elif proxy.get('username') and proxy.get('server') and proxy.get('port'):
|
||||||
|
proxy_address = '{scheme}://{username}@{server}:{port}'.format(**proxy)
|
||||||
|
elif proxy.get('server') and proxy.get('port'):
|
||||||
|
proxy_address = '{scheme}://{server}:{port}'.format(**proxy)
|
||||||
|
elif proxy.get('server'):
|
||||||
|
proxy_address = '{scheme}://{server}'.format(**proxy)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return {'http': proxy_address, 'https': proxy_address}
|
||||||
|
|
||||||
|
|
||||||
def get_cond_visibility(condition):
|
def get_cond_visibility(condition):
|
||||||
"""Test a condition in XBMC"""
|
"""Test a condition in XBMC"""
|
||||||
return xbmc.getCondVisibility(condition)
|
return xbmc.getCondVisibility(condition)
|
||||||
|
@ -44,7 +44,6 @@ class CognitoIdentity:
|
|||||||
'x-amz-target': 'AWSCognitoIdentityService.GetId',
|
'x-amz-target': 'AWSCognitoIdentityService.GetId',
|
||||||
'content-type': 'application/x-amz-json-1.1',
|
'content-type': 'application/x-amz-json-1.1',
|
||||||
})
|
})
|
||||||
_LOGGER.debug(response.text)
|
|
||||||
|
|
||||||
result = json.loads(response.text)
|
result = json.loads(response.text)
|
||||||
|
|
||||||
@ -64,7 +63,6 @@ class CognitoIdentity:
|
|||||||
'x-amz-target': 'AWSCognitoIdentityService.GetCredentialsForIdentity',
|
'x-amz-target': 'AWSCognitoIdentityService.GetCredentialsForIdentity',
|
||||||
'content-type': 'application/x-amz-json-1.1',
|
'content-type': 'application/x-amz-json-1.1',
|
||||||
})
|
})
|
||||||
_LOGGER.debug(response.text)
|
|
||||||
|
|
||||||
result = json.loads(response.text)
|
result = json.loads(response.text)
|
||||||
|
|
||||||
|
@ -77,7 +77,6 @@ class CognitoIdp:
|
|||||||
self.k = self.__hex_to_long(self.__hex_hash('00' + self.n_hex + '0' + self.g_hex)) # pylint: disable=invalid-name
|
self.k = self.__hex_to_long(self.__hex_hash('00' + self.n_hex + '0' + self.g_hex)) # pylint: disable=invalid-name
|
||||||
self.small_a_value = self.__generate_random_small_a()
|
self.small_a_value = self.__generate_random_small_a()
|
||||||
self.large_a_value = self.__calculate_a()
|
self.large_a_value = self.__calculate_a()
|
||||||
_LOGGER.debug("Created %s", self)
|
|
||||||
|
|
||||||
def authenticate(self, username, password):
|
def authenticate(self, username, password):
|
||||||
""" Authenticate with a username and password. """
|
""" Authenticate with a username and password. """
|
||||||
|
@ -13,6 +13,7 @@ from datetime import datetime
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
from resources.lib import kodiutils
|
||||||
from resources.lib.kodiutils import STREAM_DASH, STREAM_HLS, html_to_kodi
|
from resources.lib.kodiutils import STREAM_DASH, STREAM_HLS, html_to_kodi
|
||||||
from resources.lib.viervijfzes import ResolvedStream
|
from resources.lib.viervijfzes import ResolvedStream
|
||||||
|
|
||||||
@ -29,6 +30,8 @@ CACHE_AUTO = 1 # Allow to use the cache, and query the API if no cache is avail
|
|||||||
CACHE_ONLY = 2 # Only use the cache, don't use the API
|
CACHE_ONLY = 2 # Only use the cache, don't use the API
|
||||||
CACHE_PREVENT = 3 # Don't use the cache
|
CACHE_PREVENT = 3 # Don't use the cache
|
||||||
|
|
||||||
|
PROXIES = kodiutils.get_proxies()
|
||||||
|
|
||||||
|
|
||||||
class UnavailableException(Exception):
|
class UnavailableException(Exception):
|
||||||
""" Is thrown when an item is unavailable. """
|
""" Is thrown when an item is unavailable. """
|
||||||
@ -396,7 +399,8 @@ class ContentApi:
|
|||||||
|
|
||||||
# No manifest url found, get manifest from Server-Side Ad Insertion service
|
# No manifest url found, get manifest from Server-Side Ad Insertion service
|
||||||
if data.get('adType') == 'SSAI' and data.get('ssai'):
|
if data.get('adType') == 'SSAI' and data.get('ssai'):
|
||||||
url = 'https://pubads.g.doubleclick.net/ondemand/dash/content/%s/vid/%s/streams' % (data.get('ssai').get('contentSourceID'), data.get('ssai').get('videoID'))
|
url = 'https://pubads.g.doubleclick.net/ondemand/dash/content/%s/vid/%s/streams' % (
|
||||||
|
data.get('ssai').get('contentSourceID'), data.get('ssai').get('videoID'))
|
||||||
ad_data = json.loads(self._post_url(url, data=''))
|
ad_data = json.loads(self._post_url(url, data=''))
|
||||||
|
|
||||||
# Server-Side Ad Insertion DASH stream
|
# Server-Side Ad Insertion DASH stream
|
||||||
@ -409,7 +413,6 @@ class ContentApi:
|
|||||||
|
|
||||||
raise UnavailableException
|
raise UnavailableException
|
||||||
|
|
||||||
|
|
||||||
def get_program_tree(self, cache=CACHE_AUTO):
|
def get_program_tree(self, cache=CACHE_AUTO):
|
||||||
""" Get a content tree with information about all the programs.
|
""" Get a content tree with information about all the programs.
|
||||||
:type cache: str
|
:type cache: str
|
||||||
@ -772,9 +775,9 @@ class ContentApi:
|
|||||||
if authentication:
|
if authentication:
|
||||||
response = self._session.get(url, params=params, headers={
|
response = self._session.get(url, params=params, headers={
|
||||||
'authorization': authentication,
|
'authorization': authentication,
|
||||||
})
|
}, proxies=PROXIES)
|
||||||
else:
|
else:
|
||||||
response = self._session.get(url, params=params)
|
response = self._session.get(url, params=params, proxies=PROXIES)
|
||||||
|
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
_LOGGER.error(response.text)
|
_LOGGER.error(response.text)
|
||||||
@ -791,9 +794,9 @@ class ContentApi:
|
|||||||
if authentication:
|
if authentication:
|
||||||
response = self._session.post(url, params=params, json=data, headers={
|
response = self._session.post(url, params=params, json=data, headers={
|
||||||
'authorization': authentication,
|
'authorization': authentication,
|
||||||
})
|
}, proxies=PROXIES)
|
||||||
else:
|
else:
|
||||||
response = self._session.post(url, params=params, json=data)
|
response = self._session.post(url, params=params, json=data, proxies=PROXIES)
|
||||||
|
|
||||||
if response.status_code not in (200, 201):
|
if response.status_code not in (200, 201):
|
||||||
_LOGGER.error(response.text)
|
_LOGGER.error(response.text)
|
||||||
@ -810,9 +813,9 @@ class ContentApi:
|
|||||||
if authentication:
|
if authentication:
|
||||||
response = self._session.delete(url, params=params, headers={
|
response = self._session.delete(url, params=params, headers={
|
||||||
'authorization': authentication,
|
'authorization': authentication,
|
||||||
})
|
}, proxies=PROXIES)
|
||||||
else:
|
else:
|
||||||
response = self._session.delete(url, params=params)
|
response = self._session.delete(url, params=params, proxies=PROXIES)
|
||||||
|
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
_LOGGER.error(response.text)
|
_LOGGER.error(response.text)
|
||||||
|
@ -11,6 +11,8 @@ import dateutil.parser
|
|||||||
import dateutil.tz
|
import dateutil.tz
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
from resources.lib import kodiutils
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
GENRE_MAPPING = {
|
GENRE_MAPPING = {
|
||||||
@ -31,6 +33,8 @@ GENRE_MAPPING = {
|
|||||||
'Voetbal': 0x43,
|
'Voetbal': 0x43,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PROXIES = kodiutils.get_proxies()
|
||||||
|
|
||||||
|
|
||||||
class EpgProgram:
|
class EpgProgram:
|
||||||
""" Defines a Program in the EPG. """
|
""" Defines a Program in the EPG. """
|
||||||
@ -177,7 +181,7 @@ class EpgApi:
|
|||||||
:type url: str
|
:type url: str
|
||||||
:rtype str
|
:rtype str
|
||||||
"""
|
"""
|
||||||
response = self._session.get(url)
|
response = self._session.get(url, proxies=PROXIES)
|
||||||
|
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
raise Exception('Could not fetch data')
|
raise Exception('Could not fetch data')
|
||||||
|
@ -13,6 +13,8 @@ from resources.lib.viervijfzes.content import CACHE_ONLY, ContentApi, Program
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
PROXIES = kodiutils.get_proxies()
|
||||||
|
|
||||||
|
|
||||||
class SearchApi:
|
class SearchApi:
|
||||||
""" GoPlay Search API """
|
""" GoPlay Search API """
|
||||||
@ -37,9 +39,9 @@ class SearchApi:
|
|||||||
"query": query,
|
"query": query,
|
||||||
"page": 0,
|
"page": 0,
|
||||||
"mode": "programs"
|
"mode": "programs"
|
||||||
}
|
},
|
||||||
|
proxies=PROXIES
|
||||||
)
|
)
|
||||||
_LOGGER.debug(response.content)
|
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
data = json.loads(response.text)
|
data = json.loads(response.text)
|
||||||
|
Loading…
Reference in New Issue
Block a user