Netflix-4K-Script/pywidevine/getflix/getflix.py

143 wiersze
4.6 KiB
Python

"""Hijack urllib3's dns resolver and getflix.com.au api"""
from socket import error as SocketError, timeout as SocketTimeout
import json
import logging
import time
from urllib3.connection import HTTPConnection
from urllib3.util import connection
from urllib3.exceptions import ConnectTimeoutError
from urllib3.exceptions import NewConnectionError
import requests
import dns.resolver
GETFLIX_DNSSERV = ['54.164.176.2', '54.187.61.200']
def getflix_new_conn(self):
""" Establish a socket connection and set nodelay settings on it.
:return: New socket connection.
"""
extra_kw = {}
if self.source_address:
extra_kw['source_address'] = self.source_address
if self.socket_options:
extra_kw['socket_options'] = self.socket_options
hostname = getflix_lookup(self.host)
try:
conn = connection.create_connection(
(hostname, self.port), self.timeout, **extra_kw)
except SocketTimeout as err:
raise ConnectTimeoutError(
self, "Connection to %s timed out. (connect timeout=%s)" %
(self.host, self.timeout))
except SocketError as err:
raise NewConnectionError(
self, "Failed to establish a new connection: %s" % err)
return conn
def getflix_lookup(host):
"""resolve a dns address"""
res = dns.resolver.Resolver()
res.nameservers = GETFLIX_DNSSERV
answers = res.query(host, 'A')
for rdata in answers:
return str(rdata)
class Getflix(object):
"""interface for getflix"""
API_URL = 'https://www.getflix.com.au/api/'
ENDPOINTS = {
'region': 'v1/regions.json',
'region_list': 'v1/regions/list.json',
'ip': 'v1/addresses.json',
'profile': 'v1/profile.json',
'subscription': 'v1/subscription.json',
'system': 'v1/system.json',
}
_old_conn = None
def __init__(self, apikey):
"""set auth information"""
self.logger = logging.getLogger(__name__)
self.auth = (apikey, 'x')
def enable(self):
"""enable getflix lookups"""
self.logger.info("hijacking dns lookups")
self.logger.debug("saving old HTTPConnection._new_conn: {}".format(HTTPConnection._new_conn))
self._old_conn = HTTPConnection._new_conn
self.logger.debug("setting new HTTPConnection._new_conn: {}".format(getflix_new_conn))
HTTPConnection._new_conn = getflix_new_conn
def disable(self):
"""disable getflix lookups"""
self.logger.debug("restoring HTTPConnection._new_conn")
HTTPConnection._new_conn = self._old_conn
def lookup(self, host):
"""perform a getflix lookup"""
self.logger.info("looking up address")
return getflix_lookup(host)
def region_list(self):
"""return getflix region list"""
req = requests.get(self.API_URL+self.ENDPOINTS['region_list'],
auth=self.auth)
return json.loads(req.text)
def region_get(self, curr_service):
"""get the current region"""
while True:
try:
req = requests.get(self.API_URL+self.ENDPOINTS['region'],
auth=self.auth)
break
except:
time.sleep(10)
continue
for service in json.loads(req.text):
if service['service'] == curr_service:
if service['region'] == 'GB':
return 'UK'
else:
return service['region']
return None
def region_set(self, service, region):
"""set the region"""
self.logger.info("updating getflix region for service {} to {}".format(service, region))
if service == 'prime' and region == 'UK':
region = 'GB'
data = {'service': service, 'region': region}
req = requests.post(self.API_URL+self.ENDPOINTS['region'],
data=json.dumps(data),
auth=self.auth)
resp = json.loads(req.text)
try:
if resp['region'] == region:
return True
else:
self.logger.error("updating getflix region failed")
return False
except:
self.logger.error("updating getflix region failed")
return False
def update_ip(self):
"""updates auth'd ip"""
self.logger.info("updating getflix ip")
req = requests.put(self.API_URL+self.ENDPOINTS['ip'],
auth=self.auth)
if req.status_code == 200:
return True
else:
self.logger.error("updating getflix ip failed")
return False