# pylint: skip-file # -*- coding: utf-8 -*- # Author: asciidisco # Module: default # Created on: 13.01.2017 # License: MIT https://goo.gl/5bMj3H """Netflix API management""" import os import sys import json from time import time from urllib import quote, unquote from re import compile as recompile, DOTALL from base64 import urlsafe_b64encode from requests import session, cookies from utils import noop, get_user_agent from collections import OrderedDict try: import cPickle as pickle except: import pickle FETCH_VIDEO_REQUEST_COUNT = 26 ART_FANART_SIZE = '1080' # Lower quality for episodes than 1080, because it provides more variance # (1080 is usually the same as interestingMoment for episodes) ART_FANART_SIZE_EPISODE = '720' ART_MOMENT_SIZE_SMALL = '_665x375' ART_MOMENT_SIZE_LARGE = '_1920x1080' ART_BOX_SIZE_POSTER = '_342x684' ART_BOX_SIZE_SMALL = '_665x375' ART_BOX_SIZE_LARGE = '_1920x1080' ART_LOGO_SIZE = '_550x124' class NetflixSession(object): """Helps with login/session management of Netflix users & API handling""" base_url = 'https://www.netflix.com' """str: Secure Netflix url""" urls = { 'login': '/login', 'browse': '/browse', 'video_list_ids': '/preflight', 'shakti': '/pathEvaluator', 'profiles': '/profiles/manage', 'switch_profiles': '/profiles/switch', 'adult_pin': '/pin/service', 'metadata': '/metadata', 'set_video_rating': '/setVideoRating', 'update_my_list': '/playlistop', 'kids': '/Kids' } """:obj:`dict` of :obj:`str` List of all static endpoints for HTML/JSON POST/GET requests""" video_list_keys = ['user', 'genres', 'recommendations'] """:obj:`list` of :obj:`str` Divide the users video lists into 3 different categories (for easier digestion)""" profiles = {} """:obj:`dict` Dict of user profiles, user id is the key: "72ERT45...": { "profileName": "username", "avatar": "http://..../avatar.png", "id": "72ERT45...", "isAccountOwner": False, "isActive": True, "isFirstUse": False } """ user_data = {} """:obj:`dict` dict of user data (used for authentication): { "guid": "72ERT45...", "authURL": "145637....", "gpsModel": "harris" } """ api_data = {} """:obj:`dict` dict of api data (used to build up the api urls): { "API_BASE_URL": "/shakti", "API_ROOT": "https://www.netflix.com/api", "BUILD_IDENTIFIER": "113b89c9", " ICHNAEA_ROOT": "/ichnaea" } """ esn = '' """str: ESN - something like: NFCDCH-MC-D7D6F54LOPY8J416T72MQXX3RD20ME""" page_items = [ 'models/userInfo/data/authURL', 'models/serverDefs/data/BUILD_IDENTIFIER', 'models/serverDefs/data/ICHNAEA_ROOT', 'models/serverDefs/data/API_ROOT', 'models/serverDefs/data/API_BASE_URL', 'models/esnGeneratorModel/data/esn', 'gpsModel', 'models/userInfo/data/countryOfSignup', 'models/userInfo/data/membershipStatus', 'models/memberContext/data/geo/preferredLocale' ] def __init__(self, cookie_path, data_path, verify_ssl, nx_common): """Stores the cookie path for later use & instanciates a requests session with a proper user agent & stored cookies/data if available Parameters ---------- cookie_path : :obj:`str` Cookie location data_path : :obj:`str` User data cache location log_fn : :obj:`fn` optional log function """ self.cookie_path = cookie_path self.data_path = data_path self.verify_ssl = verify_ssl self.nx_common = nx_common self.parsed_cookies = {} self.parsed_user_data = {} self._init_session() def extract_json(self, content, name): # Extract json from netflix content page json_array = recompile(r"netflix\.%s\s*=\s*(.*?);\s*" % name, DOTALL).findall(content) if not json_array: return {} # Return an empty dict if json not found ! json_str = json_array[0] json_str = json_str.replace('\"', '\\"') # Hook for escape double-quotes json_str = json_str.replace('\\s', '\\\\s') # Hook for escape \s in json regex json_str = json_str.decode('unicode_escape') # finally decoding... return json.loads(json_str, encoding='utf-8', strict=False) def extract_inline_netflix_page_data(self, content='', items=None): """Extract the essential data from the page contents The contents of the parsable tags looks something like this: :return: List List of all the serialized data pulled out of the pages