mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-02 17:33:37 +00:00
138 lines
4.5 KiB
Python
138 lines
4.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
from __future__ import absolute_import, unicode_literals
|
|
|
|
import json
|
|
import requests
|
|
import tempfile
|
|
from datetime import datetime
|
|
try:
|
|
from base64 import encodebytes
|
|
except ImportError:
|
|
from base64 import encodestring as encodebytes
|
|
|
|
import diskcache
|
|
from dateutil.tz import tzutc
|
|
from dateutil.parser import parse
|
|
import boto.utils
|
|
from six.moves.urllib.parse import urlparse, parse_qs, quote
|
|
from boto import provider
|
|
from boto.connection import HTTPRequest
|
|
from boto.auth import HmacAuthV3HTTPHandler
|
|
|
|
from .constants import APP_KEY, HOST, USER_AGENT, BASE_URI
|
|
|
|
|
|
class ZuluHmacAuthV3HTTPHandler(HmacAuthV3HTTPHandler):
|
|
|
|
def sign_string(self, string_to_sign):
|
|
new_hmac = self._get_hmac()
|
|
new_hmac.update(string_to_sign)
|
|
return encodebytes(new_hmac.digest()).decode('utf-8').strip()
|
|
|
|
def headers_to_sign(self, http_request):
|
|
headers_to_sign = {'Host': self.host}
|
|
for name, value in http_request.headers.items():
|
|
lname = name.lower()
|
|
if lname.startswith('x-amz'):
|
|
headers_to_sign[name] = value
|
|
return headers_to_sign
|
|
|
|
def canonical_query_string(self, http_request):
|
|
if http_request.method == 'POST':
|
|
return ''
|
|
qs_parts = []
|
|
for param in sorted(http_request.params):
|
|
value = boto.utils.get_utf8_value(http_request.params[param])
|
|
param_ = quote(param, safe='-_.~')
|
|
value_ = quote(value, safe='-_.~')
|
|
qs_parts.append('{0}={1}'.format(param_, value_))
|
|
return '&'.join(qs_parts)
|
|
|
|
def string_to_sign(self, http_request):
|
|
headers_to_sign = self.headers_to_sign(http_request)
|
|
canonical_qs = self.canonical_query_string(http_request)
|
|
canonical_headers = self.canonical_headers(headers_to_sign)
|
|
string_to_sign = '\n'.join((
|
|
http_request.method,
|
|
http_request.path,
|
|
canonical_qs,
|
|
canonical_headers,
|
|
'',
|
|
http_request.body
|
|
))
|
|
return string_to_sign, headers_to_sign
|
|
|
|
|
|
def _get_credentials():
|
|
url = '{0}/authentication/credentials/temporary/ios82'.format(BASE_URI)
|
|
response = requests.post(
|
|
url, json={'appKey': APP_KEY}, headers={'User-Agent': USER_AGENT}
|
|
)
|
|
response.raise_for_status()
|
|
return json.loads(response.content.decode('utf8'))['resource']
|
|
|
|
|
|
class Auth(object):
|
|
|
|
SOON_EXPIRES_SECONDS = 60
|
|
_CREDS_STORAGE_KEY = 'imdbpie-credentials'
|
|
|
|
def __init__(self, creds=None):
|
|
self._cachedir = tempfile.gettempdir()
|
|
|
|
def _get_creds(self):
|
|
with diskcache.Cache(directory=self._cachedir) as cache:
|
|
return cache.get(self._CREDS_STORAGE_KEY)
|
|
|
|
def _set_creds(self, creds):
|
|
with diskcache.Cache(directory=self._cachedir) as cache:
|
|
cache[self._CREDS_STORAGE_KEY] = creds
|
|
return creds
|
|
|
|
def clear_cached_credentials(self):
|
|
with diskcache.Cache(directory=self._cachedir) as cache:
|
|
cache.delete(self._CREDS_STORAGE_KEY)
|
|
|
|
def _creds_soon_expiring(self):
|
|
creds = self._get_creds()
|
|
if not creds:
|
|
return creds, True
|
|
expires_at = parse(creds['expirationTimeStamp'])
|
|
now = datetime.now(tzutc())
|
|
if now < expires_at:
|
|
time_diff = expires_at - now
|
|
if time_diff.total_seconds() < self.SOON_EXPIRES_SECONDS:
|
|
# creds will soon expire, so renew them
|
|
return creds, True
|
|
return creds, False
|
|
else:
|
|
return creds, True
|
|
|
|
def get_auth_headers(self, url_path):
|
|
creds, soon_expires = self._creds_soon_expiring()
|
|
if soon_expires:
|
|
creds = self._set_creds(creds=_get_credentials())
|
|
|
|
handler = ZuluHmacAuthV3HTTPHandler(
|
|
host=HOST,
|
|
config={},
|
|
provider=provider.Provider(
|
|
name='aws',
|
|
access_key=creds['accessKeyId'],
|
|
secret_key=creds['secretAccessKey'],
|
|
security_token=creds['sessionToken'],
|
|
)
|
|
)
|
|
parsed_url = urlparse(url_path)
|
|
params = {
|
|
key: val[0] for key, val in parse_qs(parsed_url.query).items()
|
|
}
|
|
request = HTTPRequest(
|
|
method='GET', protocol='https', host=HOST,
|
|
port=443, path=parsed_url.path, auth_path=None, params=params,
|
|
headers={}, body=''
|
|
)
|
|
handler.add_auth(req=request)
|
|
headers = request.headers
|
|
headers['User-Agent'] = USER_AGENT
|
|
return headers
|