From 85447a5fdfc7dff80e2272d77a5f94c0eddff1af Mon Sep 17 00:00:00 2001 From: Sebastian Golasch Date: Thu, 26 Jan 2017 20:22:16 +0100 Subject: [PATCH 1/1] feat(init): Repository init --- .gitignore | 1 + README.md | 29 + __init__.py | 0 addon.py | 54 + addon.xml | 34 + resources/__init__.py | 0 resources/fanart.jpg | Bin 0 -> 30025 bytes resources/icon.png | Bin 0 -> 11406 bytes resources/language/English/strings.po | 150 ++ resources/language/German/strings.po | 150 ++ resources/lib/KodiHelper.py | 785 +++++++++ resources/lib/Library.py | 215 +++ resources/lib/MSL.py | 551 +++++++ resources/lib/MSLHttpRequestHandler.py | 46 + resources/lib/Navigation.py | 473 ++++++ resources/lib/NetflixSession.py | 2010 ++++++++++++++++++++++++ resources/lib/__init__.py | 0 resources/lib/common.py | 18 + resources/lib/utils.py | 46 + resources/screenshot-01.jpg | Bin 0 -> 305841 bytes resources/screenshot-02.jpg | Bin 0 -> 496219 bytes resources/screenshot-03.jpg | Bin 0 -> 628915 bytes resources/settings.xml | 18 + service.py | 28 + 24 files changed, 4608 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 __init__.py create mode 100644 addon.py create mode 100644 addon.xml create mode 100644 resources/__init__.py create mode 100644 resources/fanart.jpg create mode 100644 resources/icon.png create mode 100644 resources/language/English/strings.po create mode 100644 resources/language/German/strings.po create mode 100644 resources/lib/KodiHelper.py create mode 100644 resources/lib/Library.py create mode 100644 resources/lib/MSL.py create mode 100644 resources/lib/MSLHttpRequestHandler.py create mode 100644 resources/lib/Navigation.py create mode 100644 resources/lib/NetflixSession.py create mode 100644 resources/lib/__init__.py create mode 100644 resources/lib/common.py create mode 100644 resources/lib/utils.py create mode 100644 resources/screenshot-01.jpg create mode 100644 resources/screenshot-02.jpg create mode 100644 resources/screenshot-03.jpg create mode 100644 resources/settings.xml create mode 100644 service.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..bc69919 --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +# plugin.video.netflix + +Einstellungen: +-------------- + + - E-Mail/Passwort: Logindaten des Netflix-Accounts + - Verbose logging an/aus + - Logout (löscht gespeicherte Cookies & Benutzerdaten) + - Library Einstellugnen (noch nicht genutzt) + - SSL Einstellungen (noch nicht genutzt) + +Funktionen: +----------- + + - Wechsel zwischen Profilen + - Suche nach Filmen/Serien (Nicht nach Schauspielern, Genres) + - Anzeigen von Kategorien wie "Meine Liste", "Weil Sie x gesehen haben", "Mit dem Profil von x weiterschauen", "Originals" etc. + - Eingabe von "Adult Pin" bei FSK 18 Filmen/Serien + - Rating aus Kodi in Netflix + - Einträge auf Netflix in Watchlist (Meine Liste) hinzufügen/entfernen + +ToDo: +----- + + - Export in lokale Library + - Suche nach Schauspielern, Genres ermöglichen + - Fehlende Daten (Cast, bookmark position, etc.) den Show items in der Serien Video Liste hinzufügen + - Mit dem Profil von "x" weiterschauen - Statt der Liste der Shows direkt die Episode mit Bookmark anzeigen + - Sorting erweitern diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/addon.py b/addon.py new file mode 100644 index 0000000..6ac0874 --- /dev/null +++ b/addon.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Module: default +# Created on: 13.01.2017 + +# import local classes +if __package__ is None: + import sys + import os + sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + from resources.lib.NetflixSession import NetflixSession + from resources.lib.KodiHelper import KodiHelper + from resources.lib.Navigation import Navigation + from resources.lib.Library import Library +else: + from .resources.lib.NetflixSession import NetflixSession + from .resources.lib.KodiHelper import KodiHelper + from .resources.lib.Navigation import Navigation + from .resources.lib.Library import Library + +# Setup plugin +plugin_handle = int(sys.argv[1]) +base_url = sys.argv[0] + +# init plugin libs +kodi_helper = KodiHelper( + plugin_handle=plugin_handle, + base_url=base_url +) +netflix_session = NetflixSession( + cookie_path=kodi_helper.cookie_path, + data_path=kodi_helper.data_path, + log_fn=kodi_helper.log +) +library = Library( + base_url=base_url, + #root_folder=kodi_helper.base_data_path, + root_folder='/Users/asciidisco/Desktop/lib', + library_settings=kodi_helper.get_custom_library_settings(), + log_fn=kodi_helper.log +) +navigation = Navigation( + netflix_session=netflix_session, + kodi_helper=kodi_helper, + library=library, + base_url=base_url, + log_fn=kodi_helper.log +) +kodi_helper.set_library(library=library) + +if __name__ == '__main__': + # Call the router function and pass the plugin call parameters to it. + # We use string slicing to trim the leading '?' from the plugin call paramstring + navigation.router(paramstring=sys.argv[2][1:]) diff --git a/addon.xml b/addon.xml new file mode 100644 index 0000000..140b595 --- /dev/null +++ b/addon.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + video + + + + Netflix + Addon für Netflix VOD Services + Möglicherweise sind einge Teile dieses Addons in Ihrem Land illegal, Sie sollten dies unbedingt vor der Installation überprüfen. + Netflix + Netflix VOD Services Addon + Some parts of this addon may not be legal in your country of residence - please check with your local laws before installing. + + resources\icon.png + resources\fanart.jpg + resources\screenshot-01.jpg + resources\screenshot-02.jpg + resources\screenshot-03.jpg + + all + GNU GENERAL PUBLIC LICENSE. Version 2, June 1991 + http://www.kodinerds.net/ + https://github.com/kodinerds/repo + + diff --git a/resources/__init__.py b/resources/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/resources/fanart.jpg b/resources/fanart.jpg new file mode 100644 index 0000000000000000000000000000000000000000..099eaa8ede176af73f55c682a2fefd1745a0912f GIT binary patch literal 30025 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 JRho{G{{xFM$JPJ< literal 0 HcmV?d00001 diff --git a/resources/language/English/strings.po b/resources/language/English/strings.po new file mode 100644 index 0000000..1005031 --- /dev/null +++ b/resources/language/English/strings.po @@ -0,0 +1,150 @@ +# Kodi Media Center language file +# Addon Name: Netflix +# Addon id: plugin.video.netflix +# Addon version: 0.2.0 +# Addon Provider: tba. +msgid "" +msgstr "" +"Project-Id-Version: XBMC-Addons\n" +"Report-Msgid-Bugs-To: alanwww1@xbmc.org\n" +"POT-Creation-Date: 2017-01-01 12:00+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" + +msgctxt "Addon Summary" +msgid "Netflix" +msgstr "" + +msgctxt "Addon Description" +msgid "Netflix VOD Services Addon" +msgstr "" + +msgctxt "Addon Disclaimer" +msgid "Some parts of this addon may not be legal in your country of residence - please check with your local laws before installing." +msgstr "" + +msgctxt "#30001" +msgid "Recommendations" +msgstr "" + +msgctxt "#30002" +msgid "Adult Pin" +msgstr "" + +msgctxt "#30003" +msgid "Search term" +msgstr "" + +msgctxt "#30004" +msgid "Password" +msgstr "" + +msgctxt "#30005" +msgid "E-mail" +msgstr "" + +msgctxt "#30006" +msgid "Adult verification failed" +msgstr "" + +msgctxt "#30007" +msgid "Please Check your adult pin" +msgstr "" + +msgctxt "#30008" +msgid "Login failed" +msgstr "" + +msgctxt "#30009" +msgid "Please Check your credentials" +msgstr "" + +msgctxt "#30010" +msgid "Genres" +msgstr "" + +msgctxt "#30011" +msgid "Search" +msgstr "" + +msgctxt "#30012" +msgid "No seasons available" +msgstr "" + +msgctxt "#30013" +msgid "No matches found" +msgstr "" + +msgctxt "#30014" +msgid "Account" +msgstr "" + +msgctxt "#30015" +msgid "Logging" +msgstr "" + +msgctxt "#30016" +msgid "Verbose logging" +msgstr "" + +msgctxt "#30017" +msgid "Logout" +msgstr "" + +msgctxt "#30018" +msgid "Export to library" +msgstr "" + +msgctxt "#30019" +msgid "Rate on Netflix" +msgstr "" + +msgctxt "#30020" +msgid "Remove from 'My list'" +msgstr "" + +msgctxt "#30021" +msgid "Add to 'My list'" +msgstr "" + +msgctxt "#30022" +msgid "(between 0 & 10)" +msgstr "" + +msgctxt "#30023" +msgid "Expert" +msgstr "" + +msgctxt "#30024" +msgid "SSL verification" +msgstr "" + +msgctxt "#30025" +msgid "Library" +msgstr "" + +msgctxt "#30026" +msgid "Enable custom library folder" +msgstr "" + +msgctxt "#30027" +msgid "Custom library path" +msgstr "" + +msgctxt "#30028" +msgid "Playback error" +msgstr "" + +msgctxt "#30029" +msgid "Missing Inputstream addon" +msgstr "" + +msgctxt "#30030" +msgid "Remove from library" +msgstr "" diff --git a/resources/language/German/strings.po b/resources/language/German/strings.po new file mode 100644 index 0000000..671cc86 --- /dev/null +++ b/resources/language/German/strings.po @@ -0,0 +1,150 @@ +# Kodi Media Center language file +# Addon Name: Netflix +# Addon id: plugin.video.netflix +# Addon version: 0.2.0 +# Addon Provider: tba. +msgid "" +msgstr "" +"Project-Id-Version: XBMC-Addons\n" +"Report-Msgid-Bugs-To: alanwww1@xbmc.org\n" +"POT-Creation-Date: 2017-01-01 12:00+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" + +msgctxt "Addon Summary" +msgid "Netflix" +msgstr "Netflix" + +msgctxt "Addon Description" +msgid "Netflix VOD Services Addon" +msgstr "Addon für Netflix VOD Services" + +msgctxt "Addon Disclaimer" +msgid "Some parts of this addon may not be legal in your country of residence - please check with your local laws before installing." +msgstr "Möglicherweise sind einge Teile dieses Addons in Ihrem Land illegal, Sie sollten dies unbedingt vor der Installation überprüfen." + +msgctxt "#30001" +msgid "Recommendations" +msgstr "Vorschläge" + +msgctxt "#30002" +msgid "Adult Pin" +msgstr "Pin" + +msgctxt "#30003" +msgid "Search term" +msgstr "Suchbegriff" + +msgctxt "#30004" +msgid "Password" +msgstr "Passwort" + +msgctxt "#30005" +msgid "E-mail" +msgstr "E-mail" + +msgctxt "#30006" +msgid "Adult verification failed" +msgstr "Kindersicherungs-PIN nicht korrekt" + +msgctxt "#30007" +msgid "Please Check your adult pin" +msgstr "Bitter überprüfen Sie Ihre Kindersicherungs-PIN" + +msgctxt "#30008" +msgid "Login failed" +msgstr "Login nicht erfolgreich" + +msgctxt "#30009" +msgid "Please Check your credentials" +msgstr "Bitte überprüfen Sie Ihre Login Daten" + +msgctxt "#30010" +msgid "Genres" +msgstr "Genres" + +msgctxt "#30011" +msgid "Search" +msgstr "Suche" + +msgctxt "#30012" +msgid "No seasons available" +msgstr "Keine Staffeln verfügbar" + +msgctxt "#30013" +msgid "No matches found" +msgstr "Keine Titel gefunden" + +msgctxt "#30014" +msgid "Account" +msgstr "Account" + +msgctxt "#30015" +msgid "Logging" +msgstr "Logging" + +msgctxt "#30016" +msgid "Verbose logging" +msgstr "Verbose logging" + +msgctxt "#30017" +msgid "Logout" +msgstr "Logout" + +msgctxt "#30018" +msgid "Export to library" +msgstr "In Bibliothek exportieren" + +msgctxt "#30019" +msgid "Rate on Netflix" +msgstr "Auf Netflix bewerten" + +msgctxt "#30020" +msgid "Remove from 'My list'" +msgstr "Von 'Meiner Liste' entfernen" + +msgctxt "#30021" +msgid "Add to 'My list'" +msgstr "Zu 'Meiner Liste' hinzufügen" + +msgctxt "#30022" +msgid "(between 0 & 10)" +msgstr "(zwischen 0 & 10)" + +msgctxt "#30023" +msgid "Expert" +msgstr "Experte" + +msgctxt "#30024" +msgid "SSL verification" +msgstr "SSL verifizierung" + +msgctxt "#30025" +msgid "Library" +msgstr "Bibliothek" + +msgctxt "#30026" +msgid "Enable custom library folder" +msgstr "Eigenen Bibliotheks ordner nutzen" + +msgctxt "#30027" +msgid "Custom library path" +msgstr "Pfad zur Bibliothek" + +msgctxt "#30028" +msgid "Playback error" +msgstr "Fehler beim abspielen" + +msgctxt "#30029" +msgid "Missing Inputstream addon" +msgstr "Inputstream nicht gefunden" + +msgctxt "#30030" +msgid "Remove from library" +msgstr "Aus Bibliothek entfernen" diff --git a/resources/lib/KodiHelper.py b/resources/lib/KodiHelper.py new file mode 100644 index 0000000..ff4e836 --- /dev/null +++ b/resources/lib/KodiHelper.py @@ -0,0 +1,785 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Module: KodiHelper +# Created on: 13.01.2017 + +import os +import xbmcplugin +import xbmcgui +import xbmcaddon +import xbmc +import json + +class KodiHelper: + """Consumes all the configuration data from Kodi as well as turns data into lists of folders and videos""" + + msl_service_server_certificate = 'Cr0CCAMSEOVEukALwQ8307Y2+LVP+0MYh/HPkwUijgIwggEKAoIBAQDm875btoWUbGqQD8eAGuBlGY+Pxo8YF1LQR+Ex0pDONMet8EHslcZRBKNQ/09RZFTP0vrYimyYiBmk9GG+S0wB3CRITgweNE15cD33MQYyS3zpBd4z+sCJam2+jj1ZA4uijE2dxGC+gRBRnw9WoPyw7D8RuhGSJ95OEtzg3Ho+mEsxuE5xg9LM4+Zuro/9msz2bFgJUjQUVHo5j+k4qLWu4ObugFmc9DLIAohL58UR5k0XnvizulOHbMMxdzna9lwTw/4SALadEV/CZXBmswUtBgATDKNqjXwokohncpdsWSauH6vfS6FXwizQoZJ9TdjSGC60rUB2t+aYDm74cIuxAgMBAAE6EHRlc3QubmV0ZmxpeC5jb20SgAOE0y8yWw2Win6M2/bw7+aqVuQPwzS/YG5ySYvwCGQd0Dltr3hpik98WijUODUr6PxMn1ZYXOLo3eED6xYGM7Riza8XskRdCfF8xjj7L7/THPbixyn4mULsttSmWFhexzXnSeKqQHuoKmerqu0nu39iW3pcxDV/K7E6aaSr5ID0SCi7KRcL9BCUCz1g9c43sNj46BhMCWJSm0mx1XFDcoKZWhpj5FAgU4Q4e6f+S8eX39nf6D6SJRb4ap7Znzn7preIvmS93xWjm75I6UBVQGo6pn4qWNCgLYlGGCQCUm5tg566j+/g5jvYZkTJvbiZFwtjMW5njbSRwB3W4CrKoyxw4qsJNSaZRTKAvSjTKdqVDXV/U5HK7SaBA6iJ981/aforXbd2vZlRXO/2S+Maa2mHULzsD+S5l4/YGpSt7PnkCe25F+nAovtl/ogZgjMeEdFyd/9YMYjOS4krYmwp3yJ7m9ZzYCQ6I8RQN4x/yLlHG5RH/+WNLNUs6JAZ0fFdCmw=' + """str: MSL service certificate""" + + msl_service_server_url = 'http://localhost:%PORT%' + """str: MSL service url""" + + msl_service_port = 8000 + """str: MSL service port (TODO: Make it dynamic)""" + + def __init__ (self, plugin_handle, base_url): + """Fetches all needed info from Kodi & configures the baseline of the plugin + + Parameters + ---------- + plugin_handle : :obj:`int` + Plugin handle + + base_url : :obj:`str` + Plugin base url + """ + self.plugin_handle = plugin_handle + self.base_url = base_url + self.addon = xbmcaddon.Addon() + self.plugin = self.addon.getAddonInfo('name') + self.base_data_path = xbmc.translatePath(self.addon.getAddonInfo('profile')) + self.home_path = xbmc.translatePath('special://home') + self.plugin_path = self.addon.getAddonInfo('path') + self.cookie_path = self.base_data_path + 'COOKIE' + self.data_path = self.base_data_path + 'DATA' + self.config_path = os.path.join(self.base_data_path, 'config') + self.verb_log = self.addon.getSetting('logging') == 'true' + self.default_fanart = self.addon.getAddonInfo('fanart') + self.win = xbmcgui.Window(xbmcgui.getCurrentWindowId()) + self.library = None + + def refresh (self): + """Refrsh the current list""" + return xbmc.executebuiltin('Container.Refresh') + + def show_rating_dialog (self): + """Asks the user for a movie rating + + Returns + ------- + :obj:`int` + Movie rating between 0 & 10 + """ + dlg = xbmcgui.Dialog() + return dlg.numeric(heading=self.get_local_string(string_id=30019) + ' ' + self.get_local_string(string_id=30022), type=0) + + def show_adult_pin_dialog (self): + """Asks the user for the adult pin + + Returns + ------- + :obj:`int` + 4 digit adult pin needed for adult movies + """ + dlg = xbmcgui.Dialog() + return dlg.input(self.get_local_string(string_id=30002), type=xbmcgui.INPUT_NUMERIC) + + def show_search_term_dialog (self): + """Asks the user for a term to query the netflix search for + + Returns + ------- + term : :obj:`str` + Term to search for + """ + dlg = xbmcgui.Dialog() + return dlg.input(self.get_local_string(string_id=30003), type=xbmcgui.INPUT_ALPHANUM) + + def show_password_dialog (self): + """Asks the user for its Netflix password + + Returns + ------- + :obj:`str` + Netflix password + """ + dlg = xbmcgui.Dialog() + return dlg.input(self.get_local_string(string_id=30004), type=xbmcgui.INPUT_ALPHANUM) + + def show_email_dialog (self): + """Asks the user for its Netflix account email + + Returns + ------- + term : :obj:`str` + Netflix account email + """ + dlg = xbmcgui.Dialog() + return dlg.input(self.get_local_string(string_id=30005), type=xbmcgui.INPUT_ALPHANUM) + + def show_wrong_adult_pin_notification (self): + """Shows notification that a wrong adult pin was given + + Returns + ------- + bool + Dialog shown + """ + dialog = xbmcgui.Dialog() + dialog.notification(self.get_local_string(string_id=30006), self.get_local_string(string_id=30007), xbmcgui.NOTIFICATION_ERROR, 5000) + return True + + def show_login_failed_notification (self): + """Shows notification that the login failed + + Returns + ------- + bool + Dialog shown + """ + dialog = xbmcgui.Dialog() + dialog.notification(self.get_local_string(string_id=30008), self.get_local_string(string_id=30009), xbmcgui.NOTIFICATION_ERROR, 5000) + return True + + def show_missing_inputstream_addon_notification (self): + """Shows notification that the inputstream addon couldn't be found + + Returns + ------- + bool + Dialog shown + """ + dialog = xbmcgui.Dialog() + dialog.notification(self.get_local_string(string_id=30028), self.get_local_string(string_id=30029), xbmcgui.NOTIFICATION_ERROR, 5000) + return True + + def set_setting (key, value): + """Public interface for the addons setSetting method + + Returns + ------- + bool + Setting could be set or not + """ + return self.addon.setSetting(key, value) + + def get_credentials (self): + """Returns the users stored credentials + + Returns + ------- + :obj:`dict` of :obj:`str` + The users stored account data + """ + return { + 'email': self.addon.getSetting('email'), + 'password': self.addon.getSetting('password') + } + + def get_custom_library_settings (self): + """Returns the settings in regards to the custom library folder(s) + + Returns + ------- + :obj:`dict` of :obj:`str` + The users library settings + """ + return { + 'enablelibraryfolder': self.addon.getSetting('enablelibraryfolder'), + 'customlibraryfolder': self.addon.getSetting('customlibraryfolder') + } + + def set_main_menu_selection (self, type): + self.win.setProperty('main_menu_selection', type) + + def get_main_menu_selection (self): + return self.win.getProperty('main_menu_selection') + + def build_profiles_listing (self, profiles, action, build_url): + """Builds the profiles list Kodi screen + + Parameters + ---------- + profiles : :obj:`dict` of :obj:`str` + List of user profiles + + action : :obj:`str` + Action paramter to build the subsequent routes + + build_url : :obj:`fn` + Function to build the subsequent routes + + Returns + ------- + bool + List could be build + """ + for profile_id in profiles: + profile = profiles[profile_id] + url = build_url({'action': action, 'profile_id': profile_id}) + li = xbmcgui.ListItem(label=profile['profileName'], iconImage=profile['avatar']) + li.setProperty('fanart_image', self.default_fanart) + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=li, isFolder=True) + xbmcplugin.addSortMethod(handle=self.plugin_handle, sortMethod=xbmcplugin.SORT_METHOD_LABEL) + xbmcplugin.endOfDirectory(self.plugin_handle) + return True + + def build_main_menu_listing (self, video_list_ids, user_list_order, actions, build_url): + """Builds the video lists (my list, continue watching, etc.) Kodi screen + + Parameters + ---------- + video_list_ids : :obj:`dict` of :obj:`str` + List of video lists + + user_list_order : :obj:`list` of :obj:`str` + Ordered user lists, to determine what should be displayed in the main menue + + actions : :obj:`dict` of :obj:`str` + Dictionary of actions to build subsequent routes + + build_url : :obj:`fn` + Function to build the subsequent routes + + Returns + ------- + bool + List could be build + """ + preselect_items = [] + for category in user_list_order: + for video_list_id in video_list_ids['user']: + if video_list_ids['user'][video_list_id]['name'] == category: + label = video_list_ids['user'][video_list_id]['displayName'] + if category == 'netflixOriginals': + label = label.capitalize() + li = xbmcgui.ListItem(label=label) + li.setProperty('fanart_image', self.default_fanart) + # determine action route + action = actions['default'] + if category in actions.keys(): + action = actions[category] + # determine if the item should be selected + preselect_items.append((False, True)[category == self.get_main_menu_selection()]) + url = build_url({'action': action, 'video_list_id': video_list_id, 'type': category}) + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=li, isFolder=True) + + # add recommendations/genres as subfolders (save us some space on the home page) + i18n_ids = { + 'recommendations': self.get_local_string(30001), + 'genres': self.get_local_string(30010) + } + for type in i18n_ids.keys(): + # determine if the lists have contents + if len(video_list_ids[type]) > 0: + # determine action route + action = actions['default'] + if type in actions.keys(): + action = actions[type] + # determine if the item should be selected + preselect_items.append((False, True)[type == self.get_main_menu_selection()]) + li_rec = xbmcgui.ListItem(label=i18n_ids[type]) + li_rec.setProperty('fanart_image', self.default_fanart) + url_rec = build_url({'action': action, 'type': type}) + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url_rec, listitem=li_rec, isFolder=True) + + # add search as subfolder + action = actions['default'] + if 'search' in actions.keys(): + action = actions[type] + li_rec = xbmcgui.ListItem(label=self.get_local_string(30011)) + li_rec.setProperty('fanart_image', self.default_fanart) + url_rec = build_url({'action': action, 'type': 'search'}) + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url_rec, listitem=li_rec, isFolder=True) + + # no srting & close + xbmcplugin.addSortMethod(handle=self.plugin_handle, sortMethod=xbmcplugin.SORT_METHOD_UNSORTED) + xbmcplugin.endOfDirectory(self.plugin_handle) + + # (re)select the previously selected main menu entry + idx = 1 + preselected_list_item = None + for item in preselect_items: + idx += 1 + if item: + preselected_list_item = idx + if self.get_main_menu_selection() == 'search': + preselected_list_item = idx + 2 + if preselected_list_item != None: + xbmc.executebuiltin('SetFocus(%s, %s)' % (self.win.getFocusId(), preselected_list_item)) + + return True + + def build_video_listing (self, video_list, actions, type, build_url): + """Builds the video lists (my list, continue watching, etc.) contents Kodi screen + + Parameters + ---------- + video_list_ids : :obj:`dict` of :obj:`str` + List of video lists + + actions : :obj:`dict` of :obj:`str` + Dictionary of actions to build subsequent routes + + type : :obj:`str` + None or 'queue' f.e. when it´s a special video lists + + build_url : :obj:`fn` + Function to build the subsequent routes + + Returns + ------- + bool + List could be build + """ + for video_list_id in video_list: + video = video_list[video_list_id] + if type != 'queue' or (type == 'queue' and video['in_my_list'] == True): + li = xbmcgui.ListItem(label=video['title']) + # add some art to the item + li = self._generate_art_info(entry=video, li=li) + # it´s a show, so we need a subfolder & route (for seasons) + isFolder = True + url = build_url({'action': actions[video['type']], 'show_id': video_list_id}) + # lists can be mixed with shows & movies, therefor we need to check if its a movie, so play it right away + if video_list[video_list_id]['type'] == 'movie': + # it´s a movie, so we need no subfolder & a route to play it + isFolder = False + # check maturity index, to determine if we need the adult pin + needs_pin = (True, False)[int(video['maturity']['level']) >= 1000] + url = build_url({'action': 'play_video', 'video_id': video_list_id, 'pin': needs_pin}) + # add list item info + li = self._generate_entry_info(entry=video, li=li) + li = self._generate_context_menu_items(entry=video, li=li) + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=li, isFolder=isFolder) + + xbmcplugin.addSortMethod(handle=self.plugin_handle, sortMethod=xbmcplugin.SORT_METHOD_LABEL) + xbmcplugin.endOfDirectory(self.plugin_handle) + return True + + def build_search_result_listing (self, video_list, actions, build_url): + """Builds the search results list Kodi screen + + Parameters + ---------- + video_list : :obj:`dict` of :obj:`str` + List of videos or shows + + actions : :obj:`dict` of :obj:`str` + Dictionary of actions to build subsequent routes + + build_url : :obj:`fn` + Function to build the subsequent routes + + Returns + ------- + bool + List could be build + """ + return self.build_video_listing(video_list=video_list, actions=actions, type='search', build_url=build_url) + + def build_no_seasons_available (self): + """Builds the season list screen if no seasons could be found + + Returns + ------- + bool + List could be build + """ + li = xbmcgui.ListItem(label=self.get_local_string(30012)) + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url='', listitem=li, isFolder=False) + xbmcplugin.endOfDirectory(self.plugin_handle) + return True + + def build_no_search_results_available (self, build_url, action): + """Builds the search results screen if no matches could be found + + Parameters + ---------- + action : :obj:`str` + Action paramter to build the subsequent routes + + build_url : :obj:`fn` + Function to build the subsequent routes + + Returns + ------- + bool + List could be build + """ + li = xbmcgui.ListItem(label=self.get_local_string(30013)) + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=build_url({'action': action}), listitem=li, isFolder=False) + xbmcplugin.endOfDirectory(self.plugin_handle) + return True + + def build_user_sub_listing (self, video_list_ids, type, action, build_url): + """Builds the video lists screen for user subfolders (genres & recommendations) + + Parameters + ---------- + video_list_ids : :obj:`dict` of :obj:`str` + List of video lists + + type : :obj:`str` + List type (genre or recommendation) + + action : :obj:`str` + Action paramter to build the subsequent routes + + build_url : :obj:`fn` + Function to build the subsequent routes + + Returns + ------- + bool + List could be build + """ + for video_list_id in video_list_ids: + li = xbmcgui.ListItem(video_list_ids[video_list_id]['displayName']) + li.setProperty('fanart_image', self.default_fanart) + url = build_url({'action': action, 'video_list_id': video_list_id}) + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=li, isFolder=True) + + xbmcplugin.addSortMethod(handle=self.plugin_handle, sortMethod=xbmcplugin.SORT_METHOD_LABEL) + xbmcplugin.endOfDirectory(self.plugin_handle) + return True + + def build_season_listing (self, seasons_sorted, season_list, build_url): + """Builds the season list screen for a show + + Parameters + ---------- + seasons_sorted : :obj:`list` of :obj:`str` + Sorted season indexes + + season_list : :obj:`dict` of :obj:`str` + List of season entries + + build_url : :obj:`fn` + Function to build the subsequent routes + + Returns + ------- + bool + List could be build + """ + for index in seasons_sorted: + for season_id in season_list: + season = season_list[season_id] + if int(season['shortName'].split(' ')[1]) == index: + li = xbmcgui.ListItem(label=season['text']) + # add some art to the item + li = self._generate_art_info(entry=season, li=li) + # add list item info + li = self._generate_entry_info(entry=season, li=li, base_info={'mediatype': 'season'}) + li = self._generate_context_menu_items(entry=season, li=li) + url = build_url({'action': 'episode_list', 'season_id': season_id}) + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=li, isFolder=True) + + xbmcplugin.addSortMethod(handle=self.plugin_handle, sortMethod=xbmcplugin.SORT_METHOD_NONE) + xbmcplugin.endOfDirectory(self.plugin_handle) + return True + + def build_episode_listing (self, episodes_sorted, episode_list, build_url): + """Builds the episode list screen for a season of a show + + Parameters + ---------- + episodes_sorted : :obj:`list` of :obj:`str` + Sorted episode indexes + + episode_list : :obj:`dict` of :obj:`str` + List of episode entries + + build_url : :obj:`fn` + Function to build the subsequent routes + + Returns + ------- + bool + List could be build + """ + for index in episodes_sorted: + for episode_id in episode_list: + episode = episode_list[episode_id] + if int(episode['episode']) == index: + li = xbmcgui.ListItem(label=episode['title']) + # add some art to the item + li = self._generate_art_info(entry=episode, li=li) + # add list item info + li = self._generate_entry_info(entry=episode, li=li, base_info={'mediatype': 'episode'}) + li = self._generate_context_menu_items(entry=episode, li=li) + # check maturity index, to determine if we need the adult pin + needs_pin = (True, False)[int(episode['maturity']['rating']['maturityLevel']) >= 1000] + url = build_url({'action': 'play_video', 'video_id': episode_id, 'pin': needs_pin, 'start_offset': episode['bookmark']}) + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=li, isFolder=False) + xbmcplugin.addSortMethod(handle=self.plugin_handle, sortMethod=xbmcplugin.SORT_METHOD_EPISODE) + xbmcplugin.endOfDirectory(self.plugin_handle) + return True + + def play_item (self, esn, video_id, start_offset=-1): + """Plays a video + + Parameters + ---------- + esn : :obj:`str` + ESN needed for Widevine/Inputstream + + video_id : :obj:`str` + ID of the video that should be played + + start_offset : :obj:`str` + Offset to resume playback from (in seconds) + + Returns + ------- + bool + List could be build + """ + inputstream_addon = self.get_inputstream_addon() + if inputstream_addon == None: + self.show_missing_inputstream_addon_notification() + self.log(msg='Inputstream addon not found') + return False + + # inputstream addon properties + msl_service_url = self.msl_service_server_url.replace('%PORT%', str(self.msl_service_port)) + play_item = xbmcgui.ListItem(path=msl_service_url + '/manifest?id=' + video_id) + play_item.setProperty(inputstream_addon + '.license_type', 'com.widevine.alpha') + play_item.setProperty(inputstream_addon + '.manifest_type', 'mpd') + play_item.setProperty(inputstream_addon + '.license_key', msl_service_url + '/license?id=' + video_id + '||b{SSM}!b{SID}|') + play_item.setProperty(inputstream_addon + '.server_certificate', self.msl_service_server_certificate) + play_item.setProperty('inputstreamaddon', inputstream_addon) + + # check if we have a bookmark e.g. start offset position + if int(start_offset) > 0: + play_item.setProperty('StartOffset', str(start_offset)) + return xbmcplugin.setResolvedUrl(self.plugin_handle, True, listitem=play_item) + + def _generate_art_info (self, entry, li): + """Adds the art info from an entry to a Kodi list item + + Parameters + ---------- + entry : :obj:`dict` of :obj:`str` + Entry that should be turned into a list item + + li : :obj:`XMBC.ListItem` + Kodi list item instance + + Returns + ------- + :obj:`XMBC.ListItem` + Kodi list item instance + """ + art = {'fanart': self.default_fanart} + if 'boxarts' in dict(entry).keys(): + art.update({ + 'poster': entry['boxarts']['big'], + 'landscape': entry['boxarts']['big'], + 'thumb': entry['boxarts']['small'], + 'fanart': entry['boxarts']['big'] + }) + if 'interesting_moment' in dict(entry).keys(): + art.update({ + 'poster': entry['interesting_moment'], + 'fanart': entry['interesting_moment'] + }) + if 'thumb' in dict(entry).keys(): + art.update({'thumb': entry['thumb']}) + if 'fanart' in dict(entry).keys(): + art.update({'fanart': entry['fanart']}) + if 'poster' in dict(entry).keys(): + art.update({'poster': entry['poster']}) + li.setArt(art) + return li + + def _generate_entry_info (self, entry, li, base_info={}): + """Adds the item info from an entry to a Kodi list item + + Parameters + ---------- + entry : :obj:`dict` of :obj:`str` + Entry that should be turned into a list item + + li : :obj:`XMBC.ListItem` + Kodi list item instance + + base_info : :obj:`dict` of :obj:`str` + Additional info that overrules the entry info + + Returns + ------- + :obj:`XMBC.ListItem` + Kodi list item instance + """ + infos = base_info + entry_keys = entry.keys() + if 'cast' in entry_keys and len(entry['cast']) > 0: + infos.update({'cast': entry['cast']}) + if 'creators' in entry_keys and len(entry['creators']) > 0: + infos.update({'writer': entry['creators'][0]}) + if 'directors' in entry_keys and len(entry['directors']) > 0: + infos.update({'director': entry['directors'][0]}) + if 'genres' in entry_keys and len(entry['genres']) > 0: + infos.update({'genre': entry['genres'][0]}) + if 'maturity' in entry_keys: + if 'mpaa' in entry_keys: + infos.update({'mpaa': entry['mpaa']}) + else: + infos.update({'mpaa': str(entry['maturity']['board']) + '-' + str(entry['maturity']['value'])}) + if 'rating' in entry_keys: + infos.update({'rating': int(entry['rating']) * 2}) + if 'synopsis' in entry_keys: + infos.update({'plot': entry['synopsis']}) + if 'plot' in entry_keys: + infos.update({'plot': entry['plot']}) + if 'runtime' in entry_keys: + infos.update({'duration': entry['runtime']}) + if 'duration' in entry_keys: + infos.update({'duration': entry['duration']}) + if 'seasons_label' in entry_keys: + infos.update({'season': entry['seasons_label']}) + if 'season' in entry_keys: + infos.update({'season': entry['season']}) + if 'title' in entry_keys: + infos.update({'title': entry['title']}) + if 'type' in entry_keys: + if entry['type'] == 'movie' or entry['type'] == 'episode': + li.setProperty('IsPlayable', 'true') + if 'mediatype' in entry_keys: + if entry['mediatype'] == 'movie' or entry['mediatype'] == 'episode': + li.setProperty('IsPlayable', 'true') + infos.update({'mediatype': entry['mediatype']}) + if 'watched' in entry_keys: + infos.update({'playcount': (1, 0)[entry['watched']]}) + if 'index' in entry_keys: + infos.update({'episode': entry['index']}) + if 'episode' in entry_keys: + infos.update({'episode': entry['episode']}) + if 'year' in entry_keys: + infos.update({'year': entry['year']}) + if 'quality' in entry_keys: + quality = {'width': '960', 'height': '540'} + if entry['quality'] == '720': + quality = {'width': '1280', 'height': '720'} + if entry['quality'] == '1080': + quality = {'width': '1920', 'height': '1080'} + li.addStreamInfo('video', quality) + li.setInfo('video', infos) + return li + + def _generate_context_menu_items (self, entry, li): + """Adds context menue items to a Kodi list item + + Parameters + ---------- + entry : :obj:`dict` of :obj:`str` + Entry that should be turned into a list item + + li : :obj:`XMBC.ListItem` + Kodi list item instance + Returns + ------- + :obj:`XMBC.ListItem` + Kodi list item instance + """ + items = [] + action = {} + entry_keys = entry.keys() + + # action item templates + url_tmpl = 'XBMC.RunPlugin(' + self.base_url + '?action=%action%&id=' + str(entry['id']) + ')' + actions = [ + ['export_to_library', self.get_local_string(30018), 'export'], + ['remove_from_library', self.get_local_string(30030), 'remove'], + ['rate_on_netflix', self.get_local_string(30019), 'rating'], + ['remove_from_my_list', self.get_local_string(30020), 'remove_from_list'], + ['add_to_my_list', self.get_local_string(30021), 'add_to_list'] + ] + + # build concrete action items + for action_item in actions: + action.update({action_item[0]: [action_item[1], url_tmpl.replace('%action%', action_item[2])]}) + + # add or remove the movie/show/season/episode from & to the users "My List" + if 'in_my_list' in entry_keys: + items.append(action['remove_from_my_list']) if entry['in_my_list'] else items.append(action['add_to_my_list']) + elif 'queue' in entry_keys: + items.append(action['remove_from_my_list']) if entry['queue'] else items.append(action['add_to_my_list']) + elif 'my_list' in entry_keys: + items.append(action['remove_from_my_list']) if entry['my_list'] else items.append(action['add_to_my_list']) + # rate the movie/show/season/episode on Netflix + items.append(action['rate_on_netflix']) + + # add possibility to export this movie/show/season/episode to a static/local library (and to remove it) + # TODO: Not yet finished, still needs implementation + #if 'type' in entry_keys: + #items.append(action['export_to_library']) + #items.append(action['remove_from_library']) + + # add it to the item + li.addContextMenuItems(items) + return li + + def log (self, msg, level=xbmc.LOGNOTICE): + """Adds a log entry to the Kodi log + + Parameters + ---------- + msg : :obj:`str` + Entry that should be turned into a list item + + level : :obj:`int` + Kodi log level + """ + if level == xbmc.LOGDEBUG and self.verb_log: + level = xbmc.LOGNOTICE + if isinstance(msg, unicode): + msg = msg.encode('utf-8') + xbmc.log('[%s] %s' % (self.plugin, msg.__str__()), level) + + def get_local_string (self, string_id): + """Returns the localized version of a string + + Parameters + ---------- + string_id : :obj:`int` + ID of the string that shoudl be fetched + + Returns + ------- + :obj:`str` + Requested string or empty string + """ + src = xbmc if string_id < 30000 else self.addon + locString = src.getLocalizedString(string_id) + if isinstance(locString, unicode): + locString = locString.encode('utf-8') + return locString + + def get_inputstream_addon (self): + """Checks if the inputstream addon is installed & enabled. + Returns the type of the inputstream addon used or None if not found + + Returns + ------- + :obj:`str` or None + Inputstream addon or None + """ + type = 'inputstream.adaptive' + payload = { + 'jsonrpc': '2.0', + 'id': 1, + 'method': 'Addons.GetAddonDetails', + 'params': { + 'addonid': type, + 'properties': ['enabled'] + } + } + response = xbmc.executeJSONRPC(json.dumps(payload)) + data = json.loads(response) + if not 'error' in data.keys(): + if data['result']['addon']['enabled'] == True: + return type + return None + + def set_library (self, library): + """Adds an instance of the Library class + + Parameters + ---------- + library : :obj:`Library` + instance of the Library class + """ + self.library = library diff --git a/resources/lib/Library.py b/resources/lib/Library.py new file mode 100644 index 0000000..e7e4f5b --- /dev/null +++ b/resources/lib/Library.py @@ -0,0 +1,215 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Module: LibraryExporter +# Created on: 13.01.2017 + +import os +import pickle +from utils import noop + +class Library: + """Exports Netflix shows & movies to a local library folder (Not yet ready)""" + + series_label = 'shows' + movies_label = 'movies' + db_filename = 'lib.ndb' + + + def __init__ (self, base_url, root_folder, library_settings, log_fn=noop): + """Takes the instances & configuration options needed to drive the plugin + + Parameters + ---------- + base_url : :obj:`str` + Plugin base url + + root_folder : :obj:`str` + Cookie location + + library_settings : :obj:`str` + User data cache location + + library_db_path : :obj:`str` + User data cache location + + log_fn : :obj:`fn` + optional log function + """ + self.base_url = base_url + self.base_data_path = root_folder + self.enable_custom_library_folder = library_settings['enablelibraryfolder'] + self.custom_library_folder = library_settings['customlibraryfolder'] + self.log = log_fn + self.db_filepath = os.path.join(self.base_data_path, self.db_filename) + + # check for local library folder & set up the paths + if self.enable_custom_library_folder != 'true': + self.movie_path = os.path.join(self.base_data_path, self.series_label) + self.tvshow_path = os.path.join(self.base_data_path, self.movies_label) + else: + self.movie_path = os.path.join(self.custom_library_folder, self.movies_label) + self.tvshow_path = os.path.join(self.custom_library_folder, self.series_label) + + self.setup_local_netflix_library(source={ + self.movies_label: self.movie_path, + self.series_label: self.tvshow_path + }) + + self.db = self._load_local_db(filename=self.db_filepath) + + def setup_local_netflix_library (self, source): + for label in source: + if not os.path.exists(source[label]): + os.makedirs(source[label]) + + def write_strm_file(self, path, url): + with open(path, 'w+') as f: + f.write(url) + f.close() + + def _load_local_db (self, filename): + # if the db doesn't exist, create it + if not os.path.isfile(filename): + data = {self.movies_label: {}, self.series_label: {}} + self.log('Setup local library DB') + self._update_local_db(filename=filename, data=data) + return data + + with open(filename) as f: + data = pickle.load(f) + if data: + return data + else: + return {} + + def _update_local_db (self, filename, data): + if not os.path.isdir(os.path.dirname(filename)): + return False + with open(filename, 'w') as f: + f.truncate() + pickle.dump(data, f) + return True + + def movie_exists (self, title, year): + movie_meta = '%s (%d)' % (title, year) + return movie_meta in self.db[self.movies_label] + + def show_exists (self, title, year): + show_meta = '%s (%d)' % (title, year) + return show_meta in self.db[self.series_label] + + def season_exists (self, title, year, season): + if self.show_exists() == False: + return False + show_meta = '%s (%d)' % (title, year) + show_entry = self.db[self.series_label][show_meta] + return season in show_entry['seasons'] + + def episode_exists (self, title, year, season, episode): + if self.show_exists() == False: + return False + show_meta = '%s (%d)' % (title, year) + show_entry = self.db[self.series_label][show_meta] + episode_entry = 'S%02dE%02d' % (season, episode) + return episode_entry in show_entry['episodes'] + + def add_movie(self, title, year, video_id, pin, build_url): + movie_meta = '%s (%d)' % (title, year) + dirname = os.path.join(self.movie_path, movie_meta) + filename = os.path.join(dirname, movie_meta + '.strm') + if os.path.exists(filename): + return + if not os.path.exists(dirname): + os.makedirs(dirname) + if self.movie_exists(title=title, year=year) == False: + self.db[self.movies_label][movie_meta] = True + self._update_local_db(filename=self.db_filepath, db=self.db) + self.write_strm_file(path=filename, url=build_url({'action': 'play_video', 'video_id': video_id, 'pin': pin})) + + def add_show(self, title, year, episodes, build_url): + show_meta = '%s (%d)' % (title, year) + show_dir = os.path.join(self.tvshow_path, show_meta) + if not os.path.exists(show_dir): + os.makedirs(show_dir) + if self.show_exists(title, year) == False: + self.db[self.series_label][show_meta] = {'seasons': [], 'episodes': []} + for episode_id in episodes: + episode = episodes[episode_id] + self._add_episode(show_dir=show_dir, show_meta=show_meta, title=title, year=year, season=episode['season'], episode=episode['idx'], video_id=episode['id'], pin=episode['pin'], build_url=build_url) + self._update_local_db(filename=self.db_filepath, db=self.db) + return show_dir + + def _add_episode(self, title, year, show_dir, show_meta, season, episode, video_id, pin, build_url): + season = int(season) + episode = int(episode) + + # add season + if self.season_exists(title=title, year=year, season=season) == False: + self.db[self.series_label][show_meta]['seasons'].append(season) + + # add episode + episode_meta = 'S%02dE%02d' % (season, episode) + if self.episode_exists(title=title, year=year, season=season, episode=episode) == False: + self.db[self.series_label][show_meta]['episodes'].append(episode_meta) + + # create strm file + filename = episode_meta + '.strm' + filepath = os.path.join(show_dir, filename) + if os.path.exists(filepath): + return + self.write_strm_file(path=filepath, url=build_url({'action': 'play_video', 'video_id': video_id, 'pin': pin})) + + def remove_movie(self, title, year): + movie_meta = '%s (%d)' % (title, year) + del self.db[self.movies_label][movie_meta] + self._update_local_db(filename=self.db_filepath, db=self.db) + dirname = os.path.join(self.movie_path, movie_meta) + if os.path.exists(dirname): + os.rmtree(dirname) + return True + return False + + def remove_show(self, title, year): + show_meta = '%s (%d)' % (title, year) + del self.db[self.series_label][show_meta] + self._update_local_db(filename=self.db_filepath, db=self.db) + show_dir = os.path.join(self.tvshow_path, show_meta) + if os.path.exists(show_dir): + os.rmtree(show_dir) + return True + return False + + def remove_season(self, title, year, season): + season = int(season) + season_list = [] + episodes_list = [] + show_meta = '%s (%d)' % (title, year) + for season_entry in self.db[self.series_label][show_meta]['seasons']: + if season_entry != season: + season_list.append(season_entry) + self.db[self.series_label][show_meta]['seasons'] = season_list + show_dir = os.path.join(self.tvshow_path, show_meta) + if os.path.exists(show_dir): + show_files = [f for f in os.listdir(show_dir) if os.path.isfile(os.path.join(show_dir, f))] + for filename in show_files: + if 'S%02dE' % (season) in filename: + os.remove(os.path.join(show_dir, filename)) + else: + episodes_list.append(filename.replace('.strm', '')) + self.db[self.series_label][show_meta]['episodes'] = episodes_list + self._update_local_db(filename=self.db_filepath, db=self.db) + return True + + def remove_episode(self, title, year, season, episode): + episodes_list = [] + show_meta = '%s (%d)' % (title, year) + episode_meta = 'S%02dE%02d' % (season, episode) + show_dir = os.path.join(self.tvshow_path, show_meta) + if os.path.exists(os.path.join(show_dir, episode_meta + '.strm')): + os.remove(os.path.join(show_dir, episode_meta + '.strm')) + for episode_entry in self.db[self.series_label][show_meta]['episodes']: + if episode_meta != episode_entry: + episodes_list.append(episode_entry) + self.db[self.series_label][show_meta]['episodes'] = episodes_list + self._update_local_db(filename=self.db_filepath, db=self.db) + return True diff --git a/resources/lib/MSL.py b/resources/lib/MSL.py new file mode 100644 index 0000000..58a25f5 --- /dev/null +++ b/resources/lib/MSL.py @@ -0,0 +1,551 @@ +import base64 +import gzip +import json +import os +import pprint +import random +from StringIO import StringIO +from hmac import HMAC +import hashlib +import requests +import zlib + +import time +from Crypto.PublicKey import RSA +from Crypto.Cipher import PKCS1_OAEP +from Crypto.Cipher import AES +from Crypto.Random import get_random_bytes +# from Crypto.Hash import HMAC, SHA256 +from Crypto.Util import Padding +import xml.etree.ElementTree as ET +from lib import log + +pp = pprint.PrettyPrinter(indent=4) + +def base64key_decode(payload): + l = len(payload) % 4 + if l == 2: + payload += '==' + elif l == 3: + payload += '=' + elif l != 0: + raise ValueError('Invalid base64 string') + return base64.urlsafe_b64decode(payload.encode('utf-8')) + + +class MSL: + handshake_performed = False # Is a handshake already performed and the keys loaded + last_drm_context = '' + last_playback_context = '' + esn = "NFCDCH-LX-CQE0NU6PA5714R25VPLXVU2A193T36" + current_message_id = 0 + session = requests.session() + rndm = random.SystemRandom() + tokens = [] + endpoints = { + 'manifest': 'http://www.netflix.com/api/msl/NFCDCH-LX/cadmium/manifest', + 'license': 'http://www.netflix.com/api/msl/NFCDCH-LX/cadmium/license' + } + + def __init__(self, email, password): + """ + The Constructor checks for already existing crypto Keys. + If they exist it will load the existing keys + """ + self.email = email + self.password = password + + if self.file_exists('msl_data.json'): + self.__load_msl_data() + self.handshake_performed = True + elif self.file_exists('rsa_key.bin'): + log('RSA Keys do already exist load old ones') + self.__load_rsa_keys() + self.__perform_key_handshake() + else: + log('Create new RSA Keys') + # Create new Key Pair and save + self.rsa_key = RSA.generate(2048) + self.__save_rsa_keys() + self.__perform_key_handshake() + + def load_manifest(self, viewable_id): + manifest_request_data = { + 'method': 'manifest', + 'lookupType': 'PREPARE', + 'viewableIds': [viewable_id], + 'profiles': [ + 'playready-h264mpl30-dash', + 'playready-h264mpl31-dash', + 'heaac-2-dash', + 'dfxp-ls-sdh', + 'simplesdh', + 'nflx-cmisc', + 'BIF240', + 'BIF320' + ], + 'drmSystem': 'widevine', + 'appId': '14673889385265', + 'sessionParams': { + 'pinCapableClient': False, + 'uiplaycontext': 'null' + }, + 'sessionId': '14673889385265', + 'trackId': 0, + 'flavor': 'PRE_FETCH', + 'secureUrls': False, + 'supportPreviewContent': True, + 'forceClearStreams': False, + 'languages': ['de-DE'], + 'clientVersion': '4.0004.899.011', + 'uiVersion': 'akira' + } + request_data = self.__generate_msl_request_data(manifest_request_data) + + resp = self.session.post(self.endpoints['manifest'], request_data) + + + try: + resp.json() + log('MANIFEST RESPONE JSON: '+resp.text) + except ValueError: + # Maybe we have a CHUNKED response + resp = self.__parse_chunked_msl_response(resp.text) + data = self.__decrypt_payload_chunk(resp['payloads'][0]) + # pprint.pprint(data) + return self.__tranform_to_dash(data) + + + def get_license(self, challenge, sid): + + """ + std::time_t t = std::time(0); // t is an integer type + licenseRequestData["clientTime"] = (int)t; + //licenseRequestData["challengeBase64"] = challengeStr; + licenseRequestData["licenseType"] = "STANDARD"; + licenseRequestData["playbackContextId"] = playbackContextId;//"E1-BQFRAAELEB32o6Se-GFvjwEIbvDydEtfj6zNzEC3qwfweEPAL3gTHHT2V8rS_u1Mc3mw5BWZrUlKYIu4aArdjN8z_Z8t62E5jRjLMdCKMsVhlSJpiQx0MNW4aGqkYz-1lPh85Quo4I_mxVBG5lgd166B5NDizA8."; + licenseRequestData["drmContextIds"] = Json::arrayValue; + licenseRequestData["drmContextIds"].append(drmContextId); + + :param viewable_id: + :param challenge: + :param kid: + :return: + """ + + license_request_data = { + 'method': 'license', + 'licenseType': 'STANDARD', + 'clientVersion': '4.0004.899.011', + 'uiVersion': 'akira', + 'languages': ['de-DE'], + 'playbackContextId': self.last_playback_context, + 'drmContextIds': [self.last_drm_context], + 'challenges': [{ + 'dataBase64': challenge, + 'sessionId': sid + }], + 'clientTime': int(time.time()), + 'xid': int((int(time.time()) + 0.1612) * 1000) + + } + request_data = self.__generate_msl_request_data(license_request_data) + + resp = self.session.post(self.endpoints['license'], request_data) + + try: + resp.json() + log('LICENSE RESPONE JSON: '+resp.text) + except ValueError: + # Maybe we have a CHUNKED response + resp = self.__parse_chunked_msl_response(resp.text) + data = self.__decrypt_payload_chunk(resp['payloads'][0]) + # pprint.pprint(data) + if data['success'] is True: + return data['result']['licenses'][0]['data'] + else: + return '' + + + def __decrypt_payload_chunk(self, payloadchunk): + payloadchunk = json.JSONDecoder().decode(payloadchunk) + encryption_envelope = json.JSONDecoder().decode(base64.standard_b64decode(payloadchunk['payload'])) + # Decrypt the text + cipher = AES.new(self.encryption_key, AES.MODE_CBC, base64.standard_b64decode(encryption_envelope['iv'])) + plaintext = cipher.decrypt(base64.standard_b64decode(encryption_envelope['ciphertext'])) + # unpad the plaintext + plaintext = json.JSONDecoder().decode(Padding.unpad(plaintext, 16)) + data = plaintext['data'] + + # uncompress data if compressed + if plaintext['compressionalgo'] == 'GZIP': + data = zlib.decompress(base64.standard_b64decode(data), 16 + zlib.MAX_WBITS) + else: + data = base64.standard_b64decode(data) + + data = json.JSONDecoder().decode(data)[1]['payload']['data'] + data = base64.standard_b64decode(data) + return json.JSONDecoder().decode(data) + + + def __tranform_to_dash(self, manifest): + + self.save_file('/home/johannes/manifest.json', json.dumps(manifest)) + manifest = manifest['result']['viewables'][0] + + self.last_playback_context = manifest['playbackContextId'] + self.last_drm_context = manifest['drmContextId'] + + #Check for pssh + pssh = '' + if 'psshb64' in manifest: + if len(manifest['psshb64']) >= 1: + pssh = manifest['psshb64'][0] + + + + root = ET.Element('MPD') + root.attrib['xmlns'] = 'urn:mpeg:dash:schema:mpd:2011' + root.attrib['xmlns:cenc'] = 'urn:mpeg:cenc:2013' + + + seconds = manifest['runtime']/1000 + duration = "PT"+str(seconds)+".00S" + + period = ET.SubElement(root, 'Period', start='PT0S', duration=duration) + + # One Adaption Set for Video + for video_track in manifest['videoTracks']: + video_adaption_set = ET.SubElement(period, 'AdaptationSet', mimeType='video/mp4', contentType="video") + # Content Protection + protection = ET.SubElement(video_adaption_set, 'ContentProtection', + schemeIdUri='urn:uuid:EDEF8BA9-79D6-4ACE-A3C8-27DCD51D21ED') + if pssh is not '': + ET.SubElement(protection, 'cenc:pssh').text = pssh + + for downloadable in video_track['downloadables']: + rep = ET.SubElement(video_adaption_set, 'Representation', + width=str(downloadable['width']), + height=str(downloadable['height']), + bitrate=str(downloadable['bitrate']*8*1024), + mimeType='video/mp4') + + #BaseURL + ET.SubElement(rep, 'BaseURL').text = self.__get_base_url(downloadable['urls']) + # Init an Segment block + segment_base = ET.SubElement(rep, 'SegmentBase', indexRange="0-60000", indexRangeExact="true") + ET.SubElement(segment_base, 'Initialization', range='0-60000') + + + + # Multiple Adaption Set for audio + for audio_track in manifest['audioTracks']: + audio_adaption_set = ET.SubElement(period, 'AdaptationSet', + lang=audio_track['bcp47'], + contentType='audio', + mimeType='audio/mp4') + for downloadable in audio_track['downloadables']: + rep = ET.SubElement(audio_adaption_set, 'Representation', + codecs='aac', + bitrate=str(downloadable['bitrate'] * 8 * 1024), + mimeType='audio/mp4') + + #AudioChannel Config + ET.SubElement(rep, 'AudioChannelConfiguration', + schemeIdUri='urn:mpeg:dash:23003:3:audio_channel_configuration:2011', + value=str(audio_track['channelsCount'])) + + #BaseURL + ET.SubElement(rep, 'BaseURL').text = self.__get_base_url(downloadable['urls']) + # Index range + segment_base = ET.SubElement(rep, 'SegmentBase', indexRange="0-60000", indexRangeExact="true") + ET.SubElement(segment_base, 'Initialization', range='0-60000') + + + xml = ET.tostring(root, encoding='utf-8', method='xml') + xml = xml.replace('\n', '').replace('\r', '') + return xml + + def __get_base_url(self, urls): + for key in urls: + return urls[key] + + def __parse_chunked_msl_response(self, message): + i = 0 + opencount = 0 + closecount = 0 + header = "" + payloads = [] + old_end = 0 + + while i < len(message): + if message[i] == '{': + opencount = opencount + 1 + if message[i] == '}': + closecount = closecount + 1 + if opencount == closecount: + if header == "": + header = message[:i] + old_end = i + 1 + else: + payloads.append(message[old_end:i + 1]) + i += 1 + + return { + 'header': header, + 'payloads': payloads + } + + def __generate_msl_request_data(self, data): + header_encryption_envelope = self.__encrypt(self.__generate_msl_header()) + header = { + 'headerdata': base64.standard_b64encode(header_encryption_envelope), + 'signature': self.__sign(header_encryption_envelope), + 'mastertoken': self.mastertoken, + } + + # Serialize the given Data + serialized_data = json.dumps(data) + serialized_data = serialized_data.replace('"', '\\"') + serialized_data = '[{},{"headers":{},"path":"/cbp/cadmium-11","payload":{"data":"' + serialized_data + '"},"query":""}]\n' + + compressed_data = self.__compress_data(serialized_data) + + # Create FIRST Payload Chunks + first_payload = { + "messageid": self.current_message_id, + "data": compressed_data, + "compressionalgo": "GZIP", + "sequencenumber": 1, + "endofmsg": True + } + first_payload_encryption_envelope = self.__encrypt(json.dumps(first_payload)) + first_payload_chunk = { + 'payload': base64.standard_b64encode(first_payload_encryption_envelope), + 'signature': self.__sign(first_payload_encryption_envelope), + } + + + # Create Second Payload + second_payload = { + "messageid": self.current_message_id, + "data": "", + "endofmsg": True, + "sequencenumber": 2 + } + second_payload_encryption_envelope = self.__encrypt(json.dumps(second_payload)) + second_payload_chunk = { + 'payload': base64.standard_b64encode(second_payload_encryption_envelope), + 'signature': base64.standard_b64encode(self.__sign(second_payload_encryption_envelope)), + } + + request_data = json.dumps(header) + json.dumps(first_payload_chunk) # + json.dumps(second_payload_chunk) + return request_data + + + + def __compress_data(self, data): + # GZIP THE DATA + out = StringIO() + with gzip.GzipFile(fileobj=out, mode="w") as f: + f.write(data) + return base64.standard_b64encode(out.getvalue()) + + + def __generate_msl_header(self, is_handshake=False, is_key_request=False, compressionalgo="GZIP", encrypt=True): + """ + Function that generates a MSL header dict + :return: The base64 encoded JSON String of the header + """ + self.current_message_id = self.rndm.randint(0, pow(2, 52)) + + header_data = { + 'sender': self.esn, + 'handshake': is_handshake, + 'nonreplayable': False, + 'capabilities': { + 'languages': ["en-US"], + 'compressionalgos': [] + }, + 'recipient': 'Netflix', + 'renewable': True, + 'messageid': self.current_message_id, + 'timestamp': 1467733923 + } + + # Add compression algo if not empty + if compressionalgo is not "": + header_data['capabilities']['compressionalgos'].append(compressionalgo) + + # If this is a keyrequest act diffrent then other requests + if is_key_request: + public_key = base64.standard_b64encode(self.rsa_key.publickey().exportKey(format='DER')) + header_data['keyrequestdata'] = [{ + 'scheme': 'ASYMMETRIC_WRAPPED', + 'keydata': { + 'publickey': public_key, + 'mechanism': 'JWK_RSA', + 'keypairid': 'superKeyPair' + } + }] + else: + if 'usertoken' in self.tokens: + pass + else: + # Auth via email and password + header_data['userauthdata'] = { + 'scheme': 'EMAIL_PASSWORD', + 'authdata': { + 'email': self.email, + 'password': self.password + } + } + + return json.dumps(header_data) + + + + def __encrypt(self, plaintext): + """ + Encrypt the given Plaintext with the encryption key + :param plaintext: + :return: Serialized JSON String of the encryption Envelope + """ + iv = get_random_bytes(16) + encryption_envelope = { + 'ciphertext': '', + 'keyid': self.esn + '_' + str(self.sequence_number), + 'sha256': 'AA==', + 'iv': base64.standard_b64encode(iv) + } + # Padd the plaintext + plaintext = Padding.pad(plaintext, 16) + # Encrypt the text + cipher = AES.new(self.encryption_key, AES.MODE_CBC, iv) + ciphertext = cipher.encrypt(plaintext) + encryption_envelope['ciphertext'] = base64.standard_b64encode(ciphertext) + return json.dumps(encryption_envelope) + + def __sign(self, text): + #signature = hmac.new(self.sign_key, text, hashlib.sha256).digest() + signature = HMAC(self.sign_key, text, hashlib.sha256).digest() + + + # hmac = HMAC.new(self.sign_key, digestmod=SHA256) + # hmac.update(text) + return base64.standard_b64encode(signature) + + + def __perform_key_handshake(self): + + header = self.__generate_msl_header(is_key_request=True, is_handshake=True, compressionalgo="", encrypt=False) + request = { + 'entityauthdata': { + 'scheme': 'NONE', + 'authdata': { + 'identity': self.esn + } + }, + 'headerdata': base64.standard_b64encode(header), + 'signature': '', + } + log('Key Handshake Request:') + log(json.dumps(request)) + + + resp = self.session.post(self.endpoints['manifest'], json.dumps(request, sort_keys=True)) + if resp.status_code == 200: + resp = resp.json() + if 'errordata' in resp: + log('Key Exchange failed') + log(base64.standard_b64decode(resp['errordata'])) + return False + self.__parse_crypto_keys(json.JSONDecoder().decode(base64.standard_b64decode(resp['headerdata']))) + else: + log('Key Exchange failed') + log(resp.text) + + def __parse_crypto_keys(self, headerdata): + self.__set_master_token(headerdata['keyresponsedata']['mastertoken']) + # Init Decryption + encrypted_encryption_key = base64.standard_b64decode(headerdata['keyresponsedata']['keydata']['encryptionkey']) + encrypted_sign_key = base64.standard_b64decode(headerdata['keyresponsedata']['keydata']['hmackey']) + cipher_rsa = PKCS1_OAEP.new(self.rsa_key) + + # Decrypt encryption key + encryption_key_data = json.JSONDecoder().decode(cipher_rsa.decrypt(encrypted_encryption_key)) + self.encryption_key = base64key_decode(encryption_key_data['k']) + + # Decrypt sign key + sign_key_data = json.JSONDecoder().decode(cipher_rsa.decrypt(encrypted_sign_key)) + self.sign_key = base64key_decode(sign_key_data['k']) + + self.__save_msl_data() + self.handshake_performed = True + + def __load_msl_data(self): + msl_data = json.JSONDecoder().decode(self.load_file('msl_data.json')) + self.__set_master_token(msl_data['tokens']['mastertoken']) + self.encryption_key = base64.standard_b64decode(msl_data['encryption_key']) + self.sign_key = base64.standard_b64decode(msl_data['sign_key']) + + def __save_msl_data(self): + """ + Saves the keys and tokens in json file + :return: + """ + data = { + "encryption_key": base64.standard_b64encode(self.encryption_key), + 'sign_key': base64.standard_b64encode(self.sign_key), + 'tokens': { + 'mastertoken': self.mastertoken + } + } + serialized_data = json.JSONEncoder().encode(data) + self.save_file('msl_data.json', serialized_data) + + def __set_master_token(self, master_token): + self.mastertoken = master_token + self.sequence_number = json.JSONDecoder().decode(base64.standard_b64decode(master_token['tokendata']))[ + 'sequencenumber'] + + def __load_rsa_keys(self): + loaded_key = self.load_file('rsa_key.bin') + self.rsa_key = RSA.importKey(loaded_key) + + def __save_rsa_keys(self): + log('Save RSA Keys') + # Get the DER Base64 of the keys + encrypted_key = self.rsa_key.exportKey() + self.save_file('rsa_key.bin', encrypted_key) + + @staticmethod + def file_exists(filename): + """ + Checks if a given file exists + :param filename: The filename + :return: True if so + """ + return os.path.isfile(filename) + + @staticmethod + def save_file(filename, content): + """ + Saves the given content under given filename + :param filename: The filename + :param content: The content of the file + """ + with open(filename, 'w') as file_: + file_.write(content) + file_.flush() + + @staticmethod + def load_file(filename): + """ + Loads the content of a given filename + :param filename: The file to load + :return: The content of the file + """ + with open(filename) as file_: + file_content = file_.read() + return file_content diff --git a/resources/lib/MSLHttpRequestHandler.py b/resources/lib/MSLHttpRequestHandler.py new file mode 100644 index 0000000..4d7626b --- /dev/null +++ b/resources/lib/MSLHttpRequestHandler.py @@ -0,0 +1,46 @@ +import BaseHTTPServer +import base64 +from urlparse import urlparse, parse_qs + +from MSL import MSL +from lib import ADDON +email = ADDON.getSetting('email') +password = ADDON.getSetting('password') +msl = MSL(email, password) + +class MSLHttpRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): + + def do_HEAD(self): + self.send_response(200) + + def do_POST(self): + length = int(self.headers['content-length']) + post = self.rfile.read(length) + print post + data = post.split('!') + if len(data) is 2: + challenge = data[0] + sid = base64.standard_b64decode(data[1]) + b64license = msl.get_license(challenge, sid) + if b64license is not '': + self.send_response(200) + self.end_headers() + self.wfile.write(base64.standard_b64decode(b64license)) + self.finish() + else: + self.send_response(400) + else: + self.send_response(400) + + def do_GET(self): + url = urlparse(self.path) + params = parse_qs(url.query) + if 'id' not in params: + self.send_response(400, 'No id') + else: + # Get the manifest with the given id + data = msl.load_manifest(int(params['id'][0])) + self.send_response(200) + self.send_header('Content-type', 'application/xml') + self.end_headers() + self.wfile.write(data) diff --git a/resources/lib/Navigation.py b/resources/lib/Navigation.py new file mode 100644 index 0000000..c1e9397 --- /dev/null +++ b/resources/lib/Navigation.py @@ -0,0 +1,473 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Module: Navigation +# Created on: 13.01.2017 + +import urllib +import time +from urlparse import parse_qsl +from utils import noop +from utils import log + +class Navigation: + """Routes to the correct subfolder, dispatches actions & acts as a controller for the Kodi view & the Netflix model""" + + def __init__ (self, netflix_session, kodi_helper, library, base_url, log_fn=noop): + """Takes the instances & configuration options needed to drive the plugin + + Parameters + ---------- + netflix_session : :obj:`NetflixSession` + instance of the NetflixSession class + + kodi_helper : :obj:`KodiHelper` + instance of the KodiHelper class + + library : :obj:`Library` + instance of the Library class + + base_url : :obj:`str` + plugin base url + + log_fn : :obj:`fn` + optional log function + """ + self.netflix_session = netflix_session + self.kodi_helper = kodi_helper + self.library = library + self.base_url = base_url + self.log = log_fn + + @log + def router (self, paramstring): + """Route to the requested subfolder & dispatch actions along the way + + Parameters + ---------- + paramstring : :obj:`str` + Url query params + """ + params = self.parse_paramters(paramstring=paramstring) + + # log out the user + if 'action' in params.keys() and params['action'] == 'logout': + return self.netflix_session.logout() + + # check login & try to relogin if necessary + account = self.kodi_helper.get_credentials() + if self.netflix_session.is_logged_in(account=account) != True: + if self.establish_session(account=account) != True: + return self.kodi_helper.show_login_failed_notification() + + # check if we need to execute any actions before the actual routing + # gives back a dict of options routes might need + options = self.before_routing_action(params=params) + + # check if one of the before routing options decided to killthe routing + if 'exit' in options: + return False + if 'action' not in params.keys(): + # show the profiles + self.show_profiles() + elif params['action'] == 'video_lists': + # list lists that contain other lists (starting point with recommendations, search, etc.) + return self.show_video_lists() + elif params['action'] == 'video_list': + # show a list of shows/movies + type = None if 'type' not in params.keys() else params['type'] + return self.show_video_list(video_list_id=params['video_list_id'], type=type) + elif params['action'] == 'season_list': + # list of seasons for a show + return self.show_seasons(show_id=params['show_id']) + elif params['action'] == 'episode_list': + # list of episodes for a season + return self.show_episode_list(season_id=params['season_id']) + elif params['action'] == 'rating': + return self.rate_on_netflix(video_id=params['id']) + elif params['action'] == 'remove_from_list': + # removes a title from the users list on Netflix + return self.remove_from_list(video_id=params['id']) + elif params['action'] == 'add_to_list': + # adds a title to the users list on Netflix + return self.add_to_list(video_id=params['id']) + elif params['action'] == 'user-items' and params['type'] != 'search': + # display the lists (recommendations, genres, etc.) + return self.show_user_list(type=params['type']) + elif params['action'] == 'play_video': + # play a video, check for adult pin if needed + adult_pin = None + if self.check_for_adult_pin(params=params): + adult_pin = self.kodi_helper.show_adult_pin_dialog() + if self.netflix_session.send_adult_pin(adult_pin=adult_pin) != True: + return self.kodi_helper.show_wrong_adult_pin_notification() + self.play_video(video_id=params['video_id'], start_offset=params['start_offset']) + elif params['action'] == 'user-items' and params['type'] == 'search': + # if the user requested a search, ask for the term + term = self.kodi_helper.show_search_term_dialog() + return self.show_search_results(term=term) + else: + raise ValueError('Invalid paramstring: {0}!'.format(paramstring)) + return True + + @log + def play_video (self, video_id, start_offset): + """Starts video playback + + Note: This is just a dummy, inputstream is needed to play the vids + + Parameters + ---------- + video_id : :obj:`str` + ID of the video that should be played + + start_offset : :obj:`str` + Offset to resume playback from (in seconds) + """ + # widevine esn + esn = self.netflix_session.esn + return self.kodi_helper.play_item(esn=esn, video_id=video_id, start_offset=start_offset) + + def show_search_results (self, term): + """Display a list of search results + + Parameters + ---------- + term : :obj:`str` + String to lookup + + Returns + ------- + bool + If no results are available + """ + has_search_results = False + search_results_raw = self.netflix_session.fetch_search_results(term=term) + # check for any errors + if self._is_dirty_response(response=search_results_raw): + return False + + # determine if we found something + if 'search' in search_results_raw['value']: + for key in search_results_raw['value']['search'].keys(): + if self.netflix_session._is_size_key(key=key) == False: + has_search_results = search_results_raw['value']['search'][key]['titles']['length'] > 0 + + # display that we haven't found a thing + if has_search_results == False: + return self.kodi_helper.build_no_search_results_available(build_url=self.build_url, action='search') + + # list the search results + search_results = self.netflix_session.parse_search_results(response_data=search_results_raw) + # add more menaingful data to the search results + raw_search_contents = self.netflix_session.fetch_video_list_information(video_ids=search_results.keys()) + # check for any errors + if self._is_dirty_response(response=raw_search_contents): + return False + search_contents = self.netflix_session.parse_video_list(response_data=raw_search_contents) + actions = {'movie': 'play_video', 'show': 'season_list'} + return self.kodi_helper.build_search_result_listing(video_list=search_contents, actions=actions, build_url=self.build_url) + + def show_user_list (self, type): + """List the users lists for shows/movies for recommendations/genres based on the given type + + Parameters + ---------- + user_list_id : :obj:`str` + Type of list to display + """ + video_list_ids_raw = self.netflix_session.fetch_video_list_ids() + # check for any errors + if self._is_dirty_response(response=video_list_ids_raw): + return False + video_list_ids = self.netflix_session.parse_video_list_ids(response_data=video_list_ids_raw) + return self.kodi_helper.build_user_sub_listing(video_list_ids=video_list_ids[type], type=type, action='video_list', build_url=self.build_url) + + def show_episode_list (self, season_id): + """Lists all episodes for a given season + + Parameters + ---------- + season_id : :obj:`str` + ID of the season episodes should be displayed for + """ + raw_episode_list = self.netflix_session.fetch_episodes_by_season(season_id=season_id) + # check for any errors + if self._is_dirty_response(response=raw_episode_list): + return False + # parse the raw Netflix data + episode_list = self.netflix_session.parse_episodes_by_season(response_data=raw_episode_list) + + # sort seasons by number (they´re coming back unsorted from the api) + episodes_sorted = [] + for episode_id in episode_list: + episodes_sorted.append(int(episode_list[episode_id]['episode'])) + episodes_sorted.sort() + + # list the episodes + return self.kodi_helper.build_episode_listing(episodes_sorted=episodes_sorted, episode_list=episode_list, build_url=self.build_url) + + def show_seasons (self, show_id): + """Lists all seasons for a given show + + Parameters + ---------- + show_id : :obj:`str` + ID of the show seasons should be displayed for + + Returns + ------- + bool + If no seasons are available + """ + season_list_raw = self.netflix_session.fetch_seasons_for_show(id=show_id); + # check for any errors + if self._is_dirty_response(response=season_list_raw): + return False + # check if we have sesons, announced shows that are not available yet have none + if 'seasons' not in season_list_raw['value']: + return self.kodi_helper.build_no_seasons_available() + # parse the seasons raw response from Netflix + season_list = self.netflix_session.parse_seasons(id=show_id, response_data=season_list_raw) + # sort seasons by index by default (they´re coming back unsorted from the api) + seasons_sorted = [] + for season_id in season_list: + seasons_sorted.append(int(season_list[season_id]['shortName'].split(' ')[1])) + seasons_sorted.sort() + return self.kodi_helper.build_season_listing(seasons_sorted=seasons_sorted, season_list=season_list, build_url=self.build_url) + + def show_video_list (self, video_list_id, type): + """List shows/movies based on the given video list id + + Parameters + ---------- + video_list_id : :obj:`str` + ID of the video list that should be displayed + + type : :obj:`str` + None or 'queue' f.e. when it´s a special video lists + """ + raw_video_list = self.netflix_session.fetch_video_list(list_id=video_list_id) + # check for any errors + if self._is_dirty_response(response=raw_video_list): + return False + # parse the video list ids + video_list = self.netflix_session.parse_video_list(response_data=raw_video_list) + actions = {'movie': 'play_video', 'show': 'season_list'} + return self.kodi_helper.build_video_listing(video_list=video_list, actions=actions, type=type, build_url=self.build_url) + + def show_video_lists (self): + """List the users video lists (recommendations, my list, etc.)""" + # fetch video lists + raw_video_list_ids = self.netflix_session.fetch_video_list_ids() + # check for any errors + if self._is_dirty_response(response=raw_video_list_ids): + return False + # parse the video list ids + video_list_ids = self.netflix_session.parse_video_list_ids(response_data=raw_video_list_ids) + # defines an order for the user list, as Netflix changes the order at every request + user_list_order = ['queue', 'continueWatching', 'topTen', 'netflixOriginals', 'trendingNow', 'newRelease', 'popularTitles'] + # define where to route the user + actions = {'recommendations': 'user-items', 'genres': 'user-items', 'search': 'user-items', 'default': 'video_list'} + return self.kodi_helper.build_main_menu_listing(video_list_ids=video_list_ids, user_list_order=user_list_order, actions=actions, build_url=self.build_url) + + def show_profiles (self): + """List the profiles for the active account""" + self.netflix_session.refresh_session_data(account=self.kodi_helper.get_credentials()) + profiles = self.netflix_session.profiles + return self.kodi_helper.build_profiles_listing(profiles=profiles, action='video_lists', build_url=self.build_url) + + @log + def rate_on_netflix (self, video_id): + """Rate a show/movie/season/episode on Netflix + + Parameters + ---------- + video_list_id : :obj:`str` + ID of the video list that should be displayed + """ + rating = self.kodi_helper.show_rating_dialog() + return self.netflix_session.rate_video(video_id=video_id, rating=rating) + + @log + def remove_from_list (self, video_id): + """Remove an item from 'My List' & refresh the view + + Parameters + ---------- + video_list_id : :obj:`str` + ID of the video list that should be displayed + """ + self.netflix_session.remove_from_list(video_id=video_id) + return self.kodi_helper.refresh() + + @log + def add_to_list (self, video_id): + """Add an item to 'My List' & refresh the view + + Parameters + ---------- + video_list_id : :obj:`str` + ID of the video list that should be displayed + """ + self.netflix_session.add_to_list(video_id=video_id) + return self.kodi_helper.refresh() + + @log + def establish_session(self, account): + """Checks if we have an cookie with an active sessions, otherwise tries to login the user + + Parameters + ---------- + account : :obj:`dict` of :obj:`str` + Dict containing an email & a password property + + Returns + ------- + bool + If we don't have an active session & the user couldn't be logged in + """ + if self.netflix_session.is_logged_in(account=account): + return True + else: + return self.netflix_session.login(account=account) + + @log + def before_routing_action (self, params): + """Executes actions before the actual routing takes place: + + - Check if account data has been stored, if not, asks for it + - Check if the profile should be changed (and changes if so) + - Establishes a session if no action route is given + + Parameters + ---------- + params : :obj:`dict` of :obj:`str` + Url query params + + Returns + ------- + :obj:`dict` of :obj:`str` + Options that can be provided by this hook & used later in the routing process + """ + options = {} + credentials = self.kodi_helper.get_credentials() + # check if we have user settings, if not, set em + if credentials['email'] == '': + email = self.kodi_helper.show_email_dialog() + self.kodi_helper.set_setting(key='email', value=email) + if credentials['password'] == '': + password = self.kodi_helper.show_password_dialog() + self.kodi_helper.set_setting(key='password', value=password) + # persist & load main menu selection + if 'type' in params: + self.kodi_helper.set_main_menu_selection(type=params['type']) + options['main_menu_selection'] = self.kodi_helper.get_main_menu_selection() + # check and switch the profile if needed + if self.check_for_designated_profile_change(params=params): + self.netflix_session.switch_profile(profile_id=params['profile_id'], account=credentials) + # check login, in case of main menu + if 'action' not in params: + self.establish_session(account=credentials) + return options + + def check_for_designated_profile_change (self, params): + """Checks if the profile needs to be switched + + Parameters + ---------- + params : :obj:`dict` of :obj:`str` + Url query params + + Returns + ------- + bool + Profile should be switched or not + """ + # check if we need to switch the user + if 'guid' not in self.netflix_session.user_data: + return False + current_profile_id = self.netflix_session.user_data['guid'] + return 'profile_id' in params and current_profile_id != params['profile_id'] + + def check_for_adult_pin (self, params): + """Checks if an adult pin is given in the query params + + Parameters + ---------- + params : :obj:`dict` of :obj:`str` + Url query params + + Returns + ------- + bool + Adult pin parameter exists or not + """ + return (True, False)[params['pin'] == 'True'] + + def parse_paramters (self, paramstring): + """Tiny helper to convert a url paramstring into a dictionary + + Parameters + ---------- + paramstring : :obj:`str` + Url query params (in url string notation) + + Returns + ------- + :obj:`dict` of :obj:`str` + Url query params (as a dictionary) + """ + return dict(parse_qsl(paramstring)) + + def _is_expired_session (self, response): + """Checks if a response error is based on an invalid session + + Parameters + ---------- + response : :obj:`dict` of :obj:`str` + Error response object + + Returns + ------- + bool + Error is based on an invalid session + """ + return 'error' in response and 'code' in response and str(response['code']) == '401' + + def _is_dirty_response (self, response): + """Checks if a response contains an error & if the error is based on an invalid session, it tries a relogin + + Parameters + ---------- + response : :obj:`dict` of :obj:`str` + Success response object or Error response object + + Returns + ------- + bool + Response contains error or not + """ + # check for any errors + if 'error' in response: + # check if we do not have a valid session, in case that happens: (re)login + if self._is_expired_session(response=response): + if self.establish_session(account=self.kodi_helper.get_credentials()): + return True + self.log(msg='[ERROR]: ' + response['message'] + '::' + str(response['code'])) + return True + return False + + def build_url(self, query): + """Tiny helper to transform a dict into a url + querystring + + Parameters + ---------- + query : :obj:`dict` of :obj:`str` + List of paramters to be url encoded + + Returns + ------- + str + Url + querystring based on the param + """ + return self.base_url + '?' + urllib.urlencode(query) diff --git a/resources/lib/NetflixSession.py b/resources/lib/NetflixSession.py new file mode 100644 index 0000000..b2416c2 --- /dev/null +++ b/resources/lib/NetflixSession.py @@ -0,0 +1,2010 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Module: NetflixSession +# Created on: 13.01.2017 + +import sys +import os +import base64 +import time +import urllib +import json +import requests +import pickle +from BeautifulSoup import BeautifulSoup +from utils import strip_tags +from utils import noop + +class NetflixSession: + """Helps with login/session management of Netflix users & API data fetching""" + + base_url = 'https://www.netflix.com/' + """str: Secure Netflix url""" + + urls = { + 'login': '/login', + 'browse': '/browse', + 'video_list_ids': '/warmer', + 'shakti': '/pathEvaluator', + 'profiles': '/profiles', + 'switch_profiles': '/profiles/switch', + 'adult_pin': '/pin/service', + 'metadata': '/metadata', + 'set_video_rating': '/setVideoRating', + 'update_my_list': '/playlistop' + } + """: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....", + "countryOfSignup": "DE", + "emailAddress": "foo@..", + "gpsModel": "harris", + "isAdultVerified": True, + "isInFreeTrial": False, + "isKids": False, + "isTestAccount": False, + "numProfiles": 5, + "pinEnabled": True + } + """ + + 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: Widevine esn, something like: NFCDCH-MC-D7D6F54LOPY8J416T72MQXX3RD20ME""" + + def __init__(self, cookie_path, data_path, log_fn=noop): + """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.log = log_fn + + # start session, fake chrome (so that we get a proper widevine esn) & enable gzip + self.session = requests.session() + self.session.headers.update({ + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36', + 'Accept-Encoding': 'gzip, deflate' + }) + + def parse_login_form_fields (self, form_soup): + """Fetches all the inputfields from the login form, so that we + can build a request with all the fields needed besides the known email & password ones + + Parameters + ---------- + form_soup : :obj:`BeautifulSoup` + Instance of an BeautifulSoup documet or node containing the login form + + Returns + ------- + :obj:`dict` of :obj:`str` + Dictionary of all input fields with their name as the key & the default + value from the form field + """ + login_input_fields = {} + login_inputs = form_soup.findAll('input') + # gather all form fields, set an empty string as the default value + for item in login_inputs: + keys = dict(item.attrs).keys() + if 'name' in keys and 'value' not in keys: + login_input_fields[item['name']] = '' + elif 'name' in keys and 'value' in keys: + login_input_fields[item['name']] = item['value'] + return login_input_fields + + def extract_inline_netflix_page_data (self, page_soup): + """Extracts all + + So we´re extracting every JavaScript object contained in the `netflix.x = {};` variable, + strip all html tags, unescape the whole thing & finally parse the resulting serialized JSON from this + operations. Errors are expected, as not all ', '').strip() + # unescape the contents as they contain characters a JSON parser chokes up upon + unescaped_data = stripped_data.decode('string_escape') + # strip all the HTML tags within the strings a JSON parser chokes up upon them + transformed_data = strip_tags(unescaped_data) + # parse the contents with a regular JSON parser, as they should be in a shape that ot actually works + try: + parsed_data = json.loads(transformed_data) + inline_data.append(parsed_data) + except ValueError, e: + noop() + except TypeError, e: + noop() + + return inline_data; + + def _parse_user_data (self, netflix_page_data): + """Parse out the user data from the big chunk of dicts we got from + parsing the JSON-ish data from the netflix homepage + + Parameters + ---------- + netflix_page_data : :obj:`list` + List of all the JSON-ish data that has been extracted from the Netflix homepage + see: extract_inline_netflix_page_data + + Returns + ------- + :obj:`dict` of :obj:`str` + + { + "guid": "72ERT45...", + "authURL": "145637....", + "countryOfSignup": "DE", + "emailAddress": "foo@..", + "gpsModel": "harris", + "isAdultVerified": True, + "isInFreeTrial": False, + "isKids": False, + "isTestAccount": False, + "numProfiles": 5, + "pinEnabled": True + } + """ + user_data = {}; + important_fields = [ + 'authURL', + 'countryOfSignup', + 'emailAddress', + 'gpsModel', + 'guid', + 'isAdultVerified', + 'isInFreeTrial', + 'isKids', + 'isTestAccount', + 'numProfiles', + 'pinEnabled' + ] + for item in netflix_page_data: + if 'models' in dict(item).keys(): + for important_field in important_fields: + user_data.update({important_field: item['models']['userInfo']['data'][important_field]}) + return user_data + + def _parse_profile_data (self, netflix_page_data): + """Parse out the profile data from the big chunk of dicts we got from + parsing the JSON-ish data from the netflix homepage + + Parameters + ---------- + netflix_page_data : :obj:`list` + List of all the JSON-ish data that has been extracted from the Netflix homepage + see: extract_inline_netflix_page_data + + Returns + ------- + :obj:`dict` of :obj:`dict + + { + "72ERT45...": { + "profileName": "username", + "avatar": "http://..../avatar.png", + "id": "72ERT45...", + "isAccountOwner": False, + "isActive": True, + "isFirstUse": False + } + } + """ + profiles = {}; + important_fields = [ + 'profileName', + 'isActive', + 'isFirstUse', + 'isAccountOwner' + ] + # TODO: get rid of this christmas tree of doom + for item in netflix_page_data: + if 'profiles' in dict(item).keys(): + for profile_id in item['profiles']: + if self._is_size_key(key=profile_id) == False: + profile = {'id': profile_id} + for important_field in important_fields: + profile.update({important_field: item['profiles'][profile_id]['summary'][important_field]}) + profile.update({'avatar': item['avatars']['nf'][item['profiles'][profile_id]['summary']['avatarName']]['images']['byWidth']['320']['value']}) + profiles.update({profile_id: profile}) + + return profiles + + def _parse_api_base_data (self, netflix_page_data): + """Parse out the api url data from the big chunk of dicts we got from + parsing the JSOn-ish data from the netflix homepage + + Parameters + ---------- + netflix_page_data : :obj:`list` + List of all the JSON-ish data that has been extracted from the Netflix homepage + see: extract_inline_netflix_page_data + + Returns + ------- + :obj:`dict` of :obj:`str + + { + "API_BASE_URL": "/shakti", + "API_ROOT": "https://www.netflix.com/api", + "BUILD_IDENTIFIER": "113b89c9", " + ICHNAEA_ROOT": "/ichnaea" + } + """ + api_data = {}; + important_fields = [ + 'API_BASE_URL', + 'API_ROOT', + 'BUILD_IDENTIFIER', + 'ICHNAEA_ROOT' + ] + for item in netflix_page_data: + if 'models' in dict(item).keys(): + for important_field in important_fields: + api_data.update({important_field: item['models']['serverDefs']['data'][important_field]}) + return api_data + + def _parse_esn_data (self, netflix_page_data): + """Parse out the esn id data from the big chunk of dicts we got from + parsing the JSOn-ish data from the netflix homepage + + Parameters + ---------- + netflix_page_data : :obj:`list` + List of all the JSON-ish data that has been extracted from the Netflix homepage + see: extract_inline_netflix_page_data + + Returns + ------- + :obj:`str` of :obj:`str + Widevine esn, something like: NFCDCH-MC-D7D6F54LOPY8J416T72MQXX3RD20ME + """ + esn = ''; + for item in netflix_page_data: + if 'models' in dict(item).keys(): + esn = item['models']['esnGeneratorModel']['data']['esn'] + return esn + + def _parse_page_contents (self, page_soup): + """Call all the parsers we need to extract all the session relevant data from the HTML page + Directly assigns it to the NetflixSession instance + + Parameters + ---------- + page_soup : :obj:`BeautifulSoup` + Instance of an BeautifulSoup document or node containing the complete page contents + """ + netflix_page_data = self.extract_inline_netflix_page_data(page_soup=page_soup) + self.user_data = self._parse_user_data(netflix_page_data=netflix_page_data) + self.esn = self._parse_esn_data(netflix_page_data=netflix_page_data) + self.api_data = self._parse_api_base_data(netflix_page_data=netflix_page_data) + self.profiles = self._parse_profile_data(netflix_page_data=netflix_page_data) + + def is_logged_in (self, account): + """Determines if a user is already logged in (with a valid cookie), + by fetching the index page with the current cookie & checking for the + `membership status` user data + + Parameters + ---------- + account : :obj:`dict` of :obj:`str` + Dict containing an email, country & a password property + + Returns + ------- + bool + User is already logged in (e.g. Cookie is valid) or not + """ + is_logged_in = False + # load cookies + account_hash = self._generate_account_hash(account=account) + if self._load_cookies(filename=self.cookie_path + '_' + account_hash) == False: + return False + if self._load_data(filename=self.data_path + '_' + account_hash) == False: + # load the profiles page (to verify the user) + response = self.session.get(self._get_document_url_for(component='profiles')) + + # parse out the needed inline information + page_soup = BeautifulSoup(response.text) + page_data = self.extract_inline_netflix_page_data(page_soup=page_soup) + self._parse_page_contents(page_soup=page_soup) + + # check if the cookie is still valid + for item in page_data: + if 'profilesList' in dict(item).keys(): + if item['profilesList']['summary']['length'] >= 1: + is_logged_in = True + return is_logged_in + return True + + def logout (self): + """Delete all cookies and session data + + Parameters + ---------- + account : :obj:`dict` of :obj:`str` + Dict containing an email, country & a password property + + """ + self._delete_cookies(path=self.cookie_path) + self._delete_data(path=self.data_path) + + def login (self, account): + """Try to log in a user with its credentials & stores the cookies if the action is successfull + + Note: It fetches the HTML of the login page to extract the fields of the login form, + again, this is dirty, but as the fields & their values coudl change at any time, this + should be the most reliable way of retrieving the information + + Parameters + ---------- + account : :obj:`dict` of :obj:`str` + Dict containing an email, country & a password property + + Returns + ------- + bool + User could be logged in or not + """ + response = self.session.get(self._get_document_url_for(component='login')) + if response.status_code != 200: + return False; + + # collect all the login fields & their contents and add the user credentials + page_soup = BeautifulSoup(response.text) + login_form = page_soup.find(attrs={'class' : 'ui-label-text'}).findPrevious('form') + login_payload = self.parse_login_form_fields(form_soup=login_form) + if 'email' in login_payload: + login_payload['email'] = account['email'] + if 'emailOrPhoneNumber' in login_payload: + login_payload['emailOrPhoneNumber'] = account['email'] + login_payload['password'] = account['password'] + + # perform the login + login_response = self.session.post(self._get_document_url_for(component='login'), data=login_payload) + login_soup = BeautifulSoup(login_response.text) + + # we know that the login was successfull if we find an HTML element with the class of 'profile-name' + if login_soup.find(attrs={'class' : 'profile-name'}) or login_soup.find(attrs={'class' : 'profile-icon'}): + # parse the needed inline information & store cookies for later requests + self._parse_page_contents(page_soup=login_soup) + account_hash = self._generate_account_hash(account=account) + self._save_cookies(filename=self.cookie_path + '_' + account_hash) + self._save_data(filename=self.data_path + '_' + account_hash) + return True + else: + return False + + def switch_profile (self, profile_id, account): + """Switch the user profile based on a given profile id + + Note: All available profiles & their ids can be found in the ´profiles´ property after a successfull login + + Parameters + ---------- + profile_id : :obj:`str` + User profile id + + account : :obj:`dict` of :obj:`str` + Dict containing an email, country & a password property + + Returns + ------- + bool + User could be switched or not + """ + payload = { + 'switchProfileGuid': profile_id, + '_': int(time.time()), + 'authURL': self.user_data['authURL'] + } + + response = self.session.get(self._get_api_url_for(component='switch_profiles'), params=payload); + if response.status_code != 200: + return False + + # fetch the index page again, so that we can fetch the corresponding user data + browse_response = self.session.get(self._get_document_url_for(component='browse')) + browse_soup = BeautifulSoup(browse_response.text) + self._parse_page_contents(page_soup=browse_soup) + account_hash = self._generate_account_hash(account=account) + self._save_data(filename=self.data_path + '_' + account_hash) + return True + + def send_adult_pin (self, pin): + """Send the adult pin to Netflix in case an adult rated video requests it + + Note: Once entered, it should last for the complete session (Not so sure about this) + + Parameters + ---------- + pin : :obj:`str` + The users adult pin + + Returns + ------- + bool + Pin was accepted or not + or + :obj:`dict` of :obj:`str` + Api call error + """ + payload = { + 'pin': pin, + 'authURL': self.user_data['authURL'] + } + url = self._get_api_url_for(component='adult_pin') + response = self.session.get(url, params=payload); + pin_response = self._process_response(response=response, component=url) + keys = pin_response.keys() + if 'success' in keys: + return True + if 'error' in keys: + return pin_response + return False + + def add_to_list (self, video_id): + """Adds a video to "my list" on Netflix + + Parameters + ---------- + video_id : :obj:`str` + ID of th show/video/movie to be added + + Returns + ------- + bool + Adding was successfull + """ + return self._update_my_list(video_id=video_id, operation='add') + + def remove_from_list (self, video_id): + """Removes a video from "my list" on Netflix + + Parameters + ---------- + video_id : :obj:`str` + ID of th show/video/movie to be removed + + Returns + ------- + bool + Removing was successfull + """ + return self._update_my_list(video_id=video_id, operation='remove') + + def rate_video (self, video_id, rating): + """Rate a video on Netflix + + Parameters + ---------- + video_id : :obj:`str` + ID of th show/video/movie to be rated + + rating : :obj:`int` + Rating, must be between 0 & 10 + + Returns + ------- + bool + Rating successfull or not + """ + + # dirty rating validation + ratun = int(rating) + if rating > 10 or rating < 0: + return False + + # In opposition to Kodi, Netflix uses a rating from 0 to in 0.5 steps + if rating != 0: + rating = rating / 2 + + headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json, text/javascript, */*', + } + + params = { + 'titleid': video_id, + 'rating': rating + } + + payload = json.dumps({ + 'authURL': self.user_data['authURL'] + }) + + response = self.session.post(self._get_api_url_for(component='set_video_rating'), params=params, headers=headers, data=payload) + return response.status_code == 200 + + def parse_video_list_ids (self, response_data): + """Parse the list of video ids e.g. rip out the parts we need + + Parameters + ---------- + response_data : :obj:`dict` of :obj:`str` + Parsed response JSON from the ´fetch_video_list_ids´ call + + Returns + ------- + :obj:`dict` of :obj:`dict` + Video list ids in the format: + + { + "genres": { + "3589e2c6-ca3b-48b4-a72d-34f2c09ffbf4_11568367": { + "displayName": "US-Serien", + "id": "3589e2c6-ca3b-48b4-a72d-34f2c09ffbf4_11568367", + "index": 3, + "name": "genre", + "size": 38 + }, + "3589e2c6-ca3b-48b4-a72d-34f2c09ffbf4_11568368": { + "displayName": ... + }, + }, + "user": { + "3589e2c6-ca3b-48b4-a72d-34f2c09ffbf4_11568364": { + "displayName": "Meine Liste", + "id": "3589e2c6-ca3b-48b4-a72d-34f2c09ffbf4_11568364", + "index": 0, + "name": "queue", + "size": 2 + }, + "3589e2c6-ca3b-48b4-a72d-34f2c09ffbf4_11568365": { + "displayName": ... + }, + }, + "recommendations": { + "3589e2c6-ca3b-48b4-a72d-34f2c09ffbf4_11568382": { + "displayName": "Passend zu Family Guy", + "id": "3589e2c6-ca3b-48b4-a72d-34f2c09ffbf4_11568382", + "index": 18, + "name": "similars", + "size": 33 + }, + "3589e2c6-ca3b-48b4-a72d-34f2c09ffbf4_11568397": { + "displayName": ... + } + } + } + """ + # prepare the return dictionary + video_list_ids = {} + for key in self.video_list_keys: + video_list_ids[key] = {} + + # subcatogorize the lists by their context + video_lists = response_data['lists'] + for video_list_id in video_lists.keys(): + video_list = video_lists[video_list_id] + if video_list['context'] == 'genre': + video_list_ids['genres'].update(self.parse_video_list_ids_entry(id=video_list_id, entry=video_list)) + elif video_list['context'] == 'similars' or video_list['context'] == 'becauseYouAdded': + video_list_ids['recommendations'].update(self.parse_video_list_ids_entry(id=video_list_id, entry=video_list)) + else: + video_list_ids['user'].update(self.parse_video_list_ids_entry(id=video_list_id, entry=video_list)) + + return video_list_ids + + def parse_video_list_ids_entry (self, id, entry): + """Parse a video id entry e.g. rip out the parts we need + + Parameters + ---------- + response_data : :obj:`dict` of :obj:`str` + Dictionary entry from the ´fetch_video_list_ids´ call + + Returns + ------- + id : :obj:`str` + Unique id of the video list + + entry : :obj:`dict` of :obj:`str` + Video list entry in the format: + + "3589e2c6-ca3b-48b4-a72d-34f2c09ffbf4_11568382": { + "displayName": "Passend zu Family Guy", + "id": "3589e2c6-ca3b-48b4-a72d-34f2c09ffbf4_11568382", + "index": 18, + "name": "similars", + "size": 33 + } + """ + return { + id: { + 'id': id, + 'index': entry['index'], + 'name': entry['context'], + 'displayName': entry['displayName'], + 'size': entry['length'] + } + } + + def parse_search_results (self, response_data): + """Parse the list of search results, rip out the parts we need + and extend it with detailed show informations + + Parameters + ---------- + response_data : :obj:`dict` of :obj:`str` + Parsed response JSON from the `fetch_search_results` call + + Returns + ------- + :obj:`dict` of :obj:`dict` of :obj:`str` + Search results in the format: + + { + "70136140": { + "boxarts": "https://art-s.nflximg.net/0d7af/d5c72668c35d3da65ae031302bd4ae1bcc80d7af.jpg", + "detail_text": "Die legend\u00e4re und mit 13 Emmys nominierte Serie von Gene Roddenberry inspirierte eine ganze Generation.", + "id": "70136140", + "season_id": "70109435", + "synopsis": "Unter Befehl von Captain Kirk begibt sich die Besatzung des Raumschiffs Enterprise in die Tiefen des Weltraums, wo sie fremde Galaxien und neue Zivilisationen erforscht.", + "title": "Star Trek", + "type": "show" + }, + "70158329": { + "boxarts": ... + } + } + """ + search_results = {} + raw_search_results = response_data['value']['videos'] + for entry_id in raw_search_results: + if self._is_size_key(key=entry_id) == False: + # fetch information about each show & build up a proper search results dictionary + show = self.parse_show_list_entry(id=entry_id, entry=raw_search_results[entry_id]) + show[entry_id].update(self.parse_show_information(id=entry_id, response_data=self.fetch_show_information(id=entry_id, type=show[entry_id]['type']))) + search_results.update(show) + return search_results + + def parse_show_list_entry (self, id, entry): + """Parse a show entry e.g. rip out the parts we need + + Parameters + ---------- + response_data : :obj:`dict` of :obj:`str` + Dictionary entry from the ´fetch_show_information´ call + + id : :obj:`str` + Unique id of the video list + + Returns + ------- + entry : :obj:`dict` of :obj:`dict` of :obj:`str` + Show list entry in the format: + + { + "3589e2c6-ca3b-48b4-a72d-34f2c09ffbf4_11568382": { + "id": "3589e2c6-ca3b-48b4-a72d-34f2c09ffbf4_11568382", + "title": "Enterprise", + "boxarts": "https://art-s.nflximg.net/.../smth.jpg", + "type": "show" + } + } + """ + return { + id: { + 'id': id, + 'title': entry['title'], + 'boxarts': entry['boxarts']['_342x192']['jpg']['url'], + 'type': entry['summary']['type'] + } + } + + def parse_video_list (self, response_data): + """Parse a list of videos + + Parameters + ---------- + response_data : :obj:`dict` of :obj:`str` + Parsed response JSON from the `fetch_video_list` call + + Returns + ------- + :obj:`dict` of :obj:`dict` + Video list in the format: + + { + "372203": { + "artwork": null, + "boxarts": { + "big": "https://art-s.nflximg.net/5e7d3/b3b48749843fd3a36db11c319ffa60f96b55e7d3.jpg", + "small": "https://art-s.nflximg.net/57543/a039845c2eb9186dc26019576d895bf5a1957543.jpg" + }, + "cast": [ + "Christine Elise", + "Brad Dourif", + "Grace Zabriskie", + "Jenny Agutter", + "John Lafia", + "Gerrit Graham", + "Peter Haskell", + "Alex Vincent", + "Beth Grant" + ], + "creators": [], + "directors": [], + "episode_count": null, + "genres": [ + "Horrorfilme" + ], + "id": "372203", + "in_my_list": true, + "interesting_moment": "https://art-s.nflximg.net/09544/ed4b3073394b4469fb6ec22b9df81a4f5cb09544.jpg", + "list_id": "9588df32-f957-40e4-9055-1f6f33b60103_46891306", + "maturity": { + "board": "FSK", + "description": "Nur f\u00fcr Erwachsene geeignet.", + "level": 1000, + "value": "18" + }, + "quality": "540", + "rating": 3.1707757, + "regular_synopsis": "Ein Spielzeughersteller erweckt aus Versehen die Seele der M\u00f6rderpuppe Chucky erneut zum Leben, die sich unmittelbar wieder ihren m\u00f6rderischen Aktivit\u00e4ten zuwendet.", + "runtime": 5028, + "seasons_count": null, + "seasons_label": null, + "synopsis": "Die allseits beliebte, von D\u00e4monen besessene M\u00f6rderpuppe ist wieder da und verbreitet erneut Horror und Schrecken.", + "tags": [ + "Brutal", + "Spannend" + ], + "title": "Chucky 2 \u2013 Die M\u00f6rderpuppe ist wieder da", + "type": "movie", + "watched": false, + "year": 1990 + }, + "80011356": { + "artwork": null, + "boxarts": { + "big": "https://art-s.nflximg.net/7c10d/5dcc3fc8f08487e92507627068cfe26ef727c10d.jpg", + "small": "https://art-s.nflximg.net/5bc0e/f3be361b8c594929062f90a8d9c6eb57fb75bc0e.jpg" + }, + "cast": [ + "Bjarne M\u00e4del" + ], + "creators": [], + "directors": [ + "Arne Feldhusen" + ], + "episode_count": 24, + "genres": [ + "Deutsche Serien", + "Serien", + "Comedyserien" + ], + "id": "80011356", + "in_my_list": true, + "interesting_moment": "https://art-s.nflximg.net/0188e/19cd705a71ee08c8d2609ae01cd8a97a86c0188e.jpg", + "list_id": "9588df32-f957-40e4-9055-1f6f33b60103_46891306", + "maturity": { + "board": "FSF", + "description": "Geeignet ab 12 Jahren.", + "level": 80, + "value": "12" + }, + "quality": "720", + "rating": 4.4394655, + "regular_synopsis": "Comedy-Serie \u00fcber die Erlebnisse eines Tatortreinigers, der seine schmutzige Arbeit erst beginnen kann, wenn die Polizei die Tatortanalyse abgeschlossen hat.", + "runtime": null, + "seasons_count": 5, + "seasons_label": "5 Staffeln", + "synopsis": "In den meisten Krimiserien werden Mordf\u00e4lle auf faszinierende und spannende Weise gel\u00f6st. Diese Serie ist anders.", + "tags": [ + "Zynisch" + ], + "title": "Der Tatortreiniger", + "type": "show", + "watched": false, + "year": 2015 + }, + } + """ + video_list = {}; + raw_video_list = response_data['value'] + netflix_list_id = self.parse_netflix_list_id(video_list=raw_video_list); + for video_id in raw_video_list['videos']: + if self._is_size_key(key=video_id) == False: + video_list.update(self.parse_video_list_entry(id=video_id, list_id=netflix_list_id, video=raw_video_list['videos'][video_id], persons=raw_video_list['person'], genres=raw_video_list['genres'])) + return video_list + + def parse_video_list_entry (self, id, list_id, video, persons, genres): + """Parse a video list entry e.g. rip out the parts we need + + Parameters + ---------- + id : :obj:`str` + Unique id of the video + + list_id : :obj:`str` + Unique id of the containing list + + video : :obj:`dict` of :obj:`str` + Video entry from the ´fetch_video_list´ call + + persons : :obj:`dict` of :obj:`dict` of :obj:`str` + List of persons with reference ids + + persons : :obj:`dict` of :obj:`dict` of :obj:`str` + List of genres with reference ids + + Returns + ------- + entry : :obj:`dict` of :obj:`dict` of :obj:`str` + Video list entry in the format: + + { + "372203": { + "artwork": null, + "boxarts": { + "big": "https://art-s.nflximg.net/5e7d3/b3b48749843fd3a36db11c319ffa60f96b55e7d3.jpg", + "small": "https://art-s.nflximg.net/57543/a039845c2eb9186dc26019576d895bf5a1957543.jpg" + }, + "cast": [ + "Christine Elise", + "Brad Dourif", + "Grace Zabriskie", + "Jenny Agutter", + "John Lafia", + "Gerrit Graham", + "Peter Haskell", + "Alex Vincent", + "Beth Grant" + ], + "creators": [], + "directors": [], + "episode_count": null, + "genres": [ + "Horrorfilme" + ], + "id": "372203", + "in_my_list": true, + "interesting_moment": "https://art-s.nflximg.net/09544/ed4b3073394b4469fb6ec22b9df81a4f5cb09544.jpg", + "list_id": "9588df32-f957-40e4-9055-1f6f33b60103_46891306", + "maturity": { + "board": "FSK", + "description": "Nur f\u00fcr Erwachsene geeignet.", + "level": 1000, + "value": "18" + }, + "quality": "540", + "rating": 3.1707757, + "regular_synopsis": "Ein Spielzeughersteller erweckt aus Versehen die Seele der M\u00f6rderpuppe Chucky erneut zum Leben, die sich unmittelbar wieder ihren m\u00f6rderischen Aktivit\u00e4ten zuwendet.", + "runtime": 5028, + "seasons_count": null, + "seasons_label": null, + "synopsis": "Die allseits beliebte, von D\u00e4monen besessene M\u00f6rderpuppe ist wieder da und verbreitet erneut Horror und Schrecken.", + "tags": [ + "Brutal", + "Spannend" + ], + "title": "Chucky 2 \u2013 Die M\u00f6rderpuppe ist wieder da", + "type": "movie", + "watched": false, + "year": 1990 + } + } + """ + season_info = self.parse_season_information_for_video(video=video) + return { + id: { + 'id': id, + 'list_id': list_id, + 'title': video['title'], + 'synopsis': video['synopsis'], + 'regular_synopsis': video['regularSynopsis'], + 'type': video['summary']['type'], + 'rating': video['userRating']['average'], + 'episode_count': season_info['episode_count'], + 'seasons_label': season_info['seasons_label'], + 'seasons_count': season_info['seasons_count'], + 'in_my_list': video['queue']['inQueue'], + 'year': video['releaseYear'], + 'runtime': self.parse_runtime_for_video(video=video), + 'watched': video['watched'], + 'tags': self.parse_tags_for_video(video=video), + 'genres': self.parse_genres_for_video(video=video, genres=genres), + 'quality': self.parse_quality_for_video(video=video), + 'cast': self.parse_cast_for_video(video=video, persons=persons), + 'directors': self.parse_directors_for_video(video=video, persons=persons), + 'creators': self.parse_creators_for_video(video=video, persons=persons), + 'maturity': { + 'board': None if 'board' not in video['maturity']['rating'].keys() else video['maturity']['rating']['board'], + 'value': None if 'value' not in video['maturity']['rating'].keys() else video['maturity']['rating']['value'], + 'description': None if 'maturityDescription' not in video['maturity']['rating'].keys() else video['maturity']['rating']['maturityDescription'], + 'level': None if 'maturityLevel' not in video['maturity']['rating'].keys() else video['maturity']['rating']['maturityLevel'] + }, + 'boxarts': { + 'small': video['boxarts']['_342x192']['jpg']['url'], + 'big': video['boxarts']['_1280x720']['jpg']['url'] + }, + 'interesting_moment': None if 'interestingMoment' not in video.keys() else video['interestingMoment']['_665x375']['jpg']['url'], + 'artwork': video['artWorkByType']['BILLBOARD']['_1280x720']['jpg']['url'], + } + } + + def parse_creators_for_video (self, video, persons): + """Matches ids with person names to generate a list of creators + + Parameters + ---------- + video : :obj:`dict` of :obj:`str` + Dictionary entry for one video entry + + persons : :obj:`dict` of :obj:`str` + Raw resposne of all persons delivered by the API call + + Returns + ------- + :obj:`list` of :obj:`str` + List of creators + """ + creators = [] + for person_key in dict(persons).keys(): + if self._is_size_key(key=person_key) == False and person_key != 'summary': + for creator_key in dict(video['creators']).keys(): + if self._is_size_key(key=creator_key) == False and creator_key != 'summary': + if video['creators'][creator_key][1] == person_key: + creators.append(persons[person_key]['name']) + return creators + + def parse_directors_for_video (self, video, persons): + """Matches ids with person names to generate a list of directors + + Parameters + ---------- + video : :obj:`dict` of :obj:`str` + Dictionary entry for one video entry + + persons : :obj:`dict` of :obj:`str` + Raw resposne of all persons delivered by the API call + + Returns + ------- + :obj:`list` of :obj:`str` + List of directors + """ + directors = [] + for person_key in dict(persons).keys(): + if self._is_size_key(key=person_key) == False and person_key != 'summary': + for director_key in dict(video['directors']).keys(): + if self._is_size_key(key=director_key) == False and director_key != 'summary': + if video['directors'][director_key][1] == person_key: + directors.append(persons[person_key]['name']) + return directors + + def parse_cast_for_video (self, video, persons): + """Matches ids with person names to generate a list of cast members + + Parameters + ---------- + video : :obj:`dict` of :obj:`str` + Dictionary entry for one video entry + + persons : :obj:`dict` of :obj:`str` + Raw resposne of all persons delivered by the API call + + Returns + ------- + :obj:`list` of :obj:`str` + List of cast members + """ + cast = [] + for person_key in dict(persons).keys(): + if self._is_size_key(key=person_key) == False and person_key != 'summary': + for cast_key in dict(video['cast']).keys(): + if self._is_size_key(key=cast_key) == False and cast_key != 'summary': + if video['cast'][cast_key][1] == person_key: + cast.append(persons[person_key]['name']) + return cast + + def parse_genres_for_video (self, video, genres): + """Matches ids with genre names to generate a list of genres for a video + + Parameters + ---------- + video : :obj:`dict` of :obj:`str` + Dictionary entry for one video entry + + genres : :obj:`dict` of :obj:`str` + Raw resposne of all genres delivered by the API call + + Returns + ------- + :obj:`list` of :obj:`str` + List of genres + """ + video_genres = [] + for genre_key in dict(genres).keys(): + if self._is_size_key(key=genre_key) == False and genre_key != 'summary': + for show_genre_key in dict(video['genres']).keys(): + if self._is_size_key(key=show_genre_key) == False and show_genre_key != 'summary': + if video['genres'][show_genre_key][1] == genre_key: + video_genres.append(genres[genre_key]['name']) + return video_genres + + def parse_tags_for_video (self, video): + """Parses a nested list of tags, removes the not needed meta information & returns a raw string list + + Parameters + ---------- + video : :obj:`dict` of :obj:`str` + Dictionary entry for one video entry + + Returns + ------- + :obj:`list` of :obj:`str` + List of tags + """ + tags = [] + for tag_key in dict(video['tags']).keys(): + if self._is_size_key(key=tag_key) == False and tag_key != 'summary': + tags.append(video['tags'][tag_key]['name']) + return tags + + def parse_season_information_for_video (self, video): + """Checks if the fiven video is a show (series) and returns season & episode information + + Parameters + ---------- + video : :obj:`dict` of :obj:`str` + Dictionary entry for one video entry + + Returns + ------- + :obj:`dict` of :obj:`str` + Episode count / Season Count & Season label if given + """ + season_info = { + 'episode_count': None, + 'seasons_label': None, + 'seasons_count': None + } + if video['summary']['type'] == 'show': + season_info = { + 'episode_count': video['episodeCount'], + 'seasons_label': video['numSeasonsLabel'], + 'seasons_count': video['seasonCount'] + } + return season_info + + def parse_quality_for_video (self, video): + """Transforms Netflix quality information in video resolution info + + Parameters + ---------- + video : :obj:`dict` of :obj:`str` + Dictionary entry for one video entry + + Returns + ------- + :obj:`str` + Quality of the video + """ + quality = '540' + if video['videoQuality']['hasHD']: + quality = '720' + if video['videoQuality']['hasUltraHD']: + quality = '1080' + return quality + + def parse_runtime_for_video (self, video): + """Checks if the video is a movie & returns the runtime if given + + Parameters + ---------- + video : :obj:`dict` of :obj:`str` + Dictionary entry for one video entry + + Returns + ------- + :obj:`str` + Runtime of the video (in seconds) + """ + runtime = None + if video['summary']['type'] != 'show': + runtime = video['runtime'] + return runtime + + def parse_netflix_list_id (self, video_list): + """Parse a video list and extract the list id + + Parameters + ---------- + video_list : :obj:`dict` of :obj:`str` + Netflix video list + + Returns + ------- + entry : :obj:`str` or None + Netflix list id + """ + netflix_list_id = None + if 'lists' in video_list.keys(): + for video_id in video_list['lists']: + if self._is_size_key(key=video_id) == False: + netflix_list_id = video_id; + return netflix_list_id + + def parse_show_information (self, id, response_data): + """Parse extended show information (synopsis, seasons, etc.) + + Parameters + ---------- + id : :obj:`str` + Video id + + response_data : :obj:`dict` of :obj:`str` + Parsed response JSON from the `fetch_show_information` call + + Returns + ------- + entry : :obj:`dict` of :obj:`str` + Show information in the format: + { + "season_id": "80113084", + "synopsis": "Aus verzweifelter Geldnot versucht sich der Familienvater und Drucker Jochen als Geldf\u00e4lscher und rutscht dabei immer mehr in die dunkle Welt des Verbrechens ab." + "detail_text": "I´m optional" + } + """ + show = {} + raw_show = response_data['value']['videos'][id] + show.update({'synopsis': raw_show['regularSynopsis']}) + if 'evidence' in raw_show: + show.update({'detail_text': raw_show['evidence']['value']['text']}) + if 'seasonList' in raw_show: + show.update({'season_id': raw_show['seasonList']['current'][1]}) + return show + + def parse_seasons (self, id, response_data): + """Parse a list of seasons for a given show + + Parameters + ---------- + id : :obj:`str` + Season id + + response_data : :obj:`dict` of :obj:`str` + Parsed response JSON from the `fetch_seasons_for_show` call + + Returns + ------- + entry : :obj:`dict` of :obj:`dict` of :obj:`str` + Season information in the format: + { + "80113084": { + "id": 80113084, + "text": "Season 1", + "shortName": "St. 1", + "boxarts": { + "big": "https://art-s.nflximg.net/5e7d3/b3b48749843fd3a36db11c319ffa60f96b55e7d3.jpg", + "small": "https://art-s.nflximg.net/57543/a039845c2eb9186dc26019576d895bf5a1957543.jpg" + }, + "interesting_moment": "https://art-s.nflximg.net/09544/ed4b3073394b4469fb6ec22b9df81a4f5cb09544.jpg" + }, + "80113085": { + "id": 80113085, + "text": "Season 2", + "shortName": "St. 2", + "boxarts": { + "big": "https://art-s.nflximg.net/5e7d3/b3b48749843fd3a36db11c319ffa60f96b55e7d3.jpg", + "small": "https://art-s.nflximg.net/57543/a039845c2eb9186dc26019576d895bf5a1957543.jpg" + }, + "interesting_moment": "https://art-s.nflximg.net/09544/ed4b3073394b4469fb6ec22b9df81a4f5cb09544.jpg" + } + } + """ + seasons = {} + raw_seasons = response_data['value'] + for season in raw_seasons['seasons']: + if self._is_size_key(key=season) == False: + seasons.update(self.parse_season_entry(season=raw_seasons['seasons'][season], videos=raw_seasons['videos'])) + return seasons + + def parse_season_entry (self, season, videos): + """Parse a season list entry e.g. rip out the parts we need + + Parameters + ---------- + season : :obj:`dict` of :obj:`str` + Season entry from the `fetch_seasons_for_show` call + + Returns + ------- + entry : :obj:`dict` of :obj:`dict` of :obj:`str` + Season list entry in the format: + + { + "80113084": { + "id": 80113084, + "text": "Season 1", + "shortName": "St. 1", + "boxarts": { + "big": "https://art-s.nflximg.net/5e7d3/b3b48749843fd3a36db11c319ffa60f96b55e7d3.jpg", + "small": "https://art-s.nflximg.net/57543/a039845c2eb9186dc26019576d895bf5a1957543.jpg" + }, + "interesting_moment": "https://art-s.nflximg.net/09544/ed4b3073394b4469fb6ec22b9df81a4f5cb09544.jpg" + } + } + """ + # get art video key + video_key = '' + for key in videos.keys(): + if self._is_size_key(key=key) == False: + video_key = key + return { + season['summary']['id']: { + 'id': season['summary']['id'], + 'text': season['summary']['name'], + 'shortName': season['summary']['shortName'], + 'boxarts': { + 'small': videos[video_key]['boxarts']['_342x192']['jpg']['url'], + 'big': videos[video_key]['boxarts']['_1280x720']['jpg']['url'] + }, + 'interesting_moment': videos[video_key]['interestingMoment']['_665x375']['jpg']['url'], + } + } + + def parse_episodes_by_season (self, response_data): + """Parse episodes for a given season/episode list + + Parameters + ---------- + response_data : :obj:`dict` of :obj:`str` + Parsed response JSON from the `fetch_seasons_for_show` call + + Returns + ------- + entry : :obj:`dict` of :obj:`dict` of :obj:`str` + Season information in the format: + + { + "70251729": { + "banner": "https://art-s.nflximg.net/63a36/c7fdfe6604ef2c22d085ac5dca5f69874e363a36.jpg", + "duration": 1387, + "episode": 1, + "fanart": "https://art-s.nflximg.net/74e02/e7edcc5cc7dcda1e94d505df2f0a2f0d22774e02.jpg", + "genres": [ + "Serien", + "Comedyserien" + ], + "id": 70251729, + "mediatype": "episode", + "mpaa": "FSK 16", + "my_list": false, + "playcount": 0, + "plot": "Als die Griffins und andere Einwohner von Quahog in die Villa von James Woods eingeladen werden, muss pl\u00f6tzlich ein Mord aufgekl\u00e4rt werden.", + "poster": "https://art-s.nflximg.net/72fd6/57088715e8d436fdb6986834ab39124b0a972fd6.jpg", + "rating": 3.9111512, + "season": 9, + "thumb": "https://art-s.nflximg.net/be686/07680670a68da8749eba607efb1ae37f9e3be686.jpg", + "title": "Und dann gab es weniger (Teil 1)", + "year": 2010, + "bookmark": -1 + }, + "70251730": { + "banner": "https://art-s.nflximg.net/63a36/c7fdfe6604ef2c22d085ac5dca5f69874e363a36.jpg", + "duration": 1379, + "episode": 2, + "fanart": "https://art-s.nflximg.net/c472c/6c10f9578bf2c1d0a183c2ccb382931efcbc472c.jpg", + "genres": [ + "Serien", + "Comedyserien" + ], + "id": 70251730, + "mediatype": "episode", + "mpaa": "FSK 16", + "my_list": false, + "playcount": 1, + "plot": "Wer ist der M\u00f6rder? Nach zahlreichen Morden wird immer wieder jemand anderes verd\u00e4chtigt.", + "poster": "https://art-s.nflximg.net/72fd6/57088715e8d436fdb6986834ab39124b0a972fd6.jpg", + "rating": 3.9111512, + "season": 9, + "thumb": "https://art-s.nflximg.net/15a08/857d59126641987bec302bb147a802a00d015a08.jpg", + "title": "Und dann gab es weniger (Teil 2)", + "year": 2010, + "bookmark": 1234 + }, + } + """ + episodes = {} + raw_episodes = response_data['value']['videos'] + for episode_id in raw_episodes: + if self._is_size_key(key=episode_id) == False: + if (raw_episodes[episode_id]['summary']['type'] == 'episode'): + episodes.update(self.parse_episode(episode=raw_episodes[episode_id], genres=response_data['value']['genres'])) + return episodes + + def parse_episode (self, episode, genres=None): + """Parse episode from an list of episodes by season + + Parameters + ---------- + episode : :obj:`dict` of :obj:`str` + Episode entry from the `fetch_episodes_by_season` call + + Returns + ------- + entry : :obj:`dict` of :obj:`dict` of :obj:`str` + Episode information in the format: + + { + "70251729": { + "banner": "https://art-s.nflximg.net/63a36/c7fdfe6604ef2c22d085ac5dca5f69874e363a36.jpg", + "duration": 1387, + "episode": 1, + "fanart": "https://art-s.nflximg.net/74e02/e7edcc5cc7dcda1e94d505df2f0a2f0d22774e02.jpg", + "genres": [ + "Serien", + "Comedyserien" + ], + "id": 70251729, + "mediatype": "episode", + "mpaa": "FSK 16", + "my_list": false, + "playcount": 0, + "plot": "Als die Griffins und andere Einwohner von Quahog in die Villa von James Woods eingeladen werden, muss pl\u00f6tzlich ein Mord aufgekl\u00e4rt werden.", + "poster": "https://art-s.nflximg.net/72fd6/57088715e8d436fdb6986834ab39124b0a972fd6.jpg", + "rating": 3.9111512, + "season": 9, + "thumb": "https://art-s.nflximg.net/be686/07680670a68da8749eba607efb1ae37f9e3be686.jpg", + "title": "Und dann gab es weniger (Teil 1)", + "year": 2010, + "bookmark": 1234 + }, + } + """ + return { + episode['summary']['id']: { + 'id': episode['summary']['id'], + 'episode': episode['summary']['episode'], + 'season': episode['summary']['season'], + 'plot': episode['info']['synopsis'], + 'duration': episode['info']['runtime'], + 'title': episode['info']['title'], + 'year': episode['info']['releaseYear'], + 'genres': self.parse_genres_for_video(video=episode, genres=genres), + 'mpaa': str(episode['maturity']['rating']['board']) + ' ' + str(episode['maturity']['rating']['value']), + 'maturity': episode['maturity'], + 'playcount': (0, 1)[episode['watched']], + 'rating': episode['userRating']['average'], + 'thumb': episode['info']['interestingMoments']['url'], + 'fanart': episode['interestingMoment']['_1280x720']['jpg']['url'], + 'poster': episode['boxarts']['_1280x720']['jpg']['url'], + 'banner': episode['boxarts']['_342x192']['jpg']['url'], + 'mediatype': {'episode': 'episode', 'movie': 'movie'}[episode['summary']['type']], + 'my_list': episode['queue']['inQueue'], + 'bookmark': episode['bookmarkPosition'] + } + } + + def fetch_browse_list_contents (self): + """Fetches the HTML data for the lists on the landing page (browse page) of Netflix + + Returns + ------- + :obj:`BeautifulSoup` + Instance of an BeautifulSoup document containing the complete page contents + """ + response = self.session.get(self._get_document_url_for(component='browse')) + return BeautifulSoup(response.text) + + def fetch_video_list_ids (self, list_from=0, list_to=50): + """Fetches the JSON with detailed information based on the lists on the landing page (browse page) of Netflix + + Parameters + ---------- + list_from : :obj:`int` + Start entry for pagination + + list_to : :obj:`int` + Last entry for pagination + + Returns + ------- + :obj:`dict` of :obj:`dict` of :obj:`str` + Raw Netflix API call response or api call error + """ + payload = { + 'fromRow': list_from, + 'toRow': list_to, + 'opaqueImageExtension': 'jpg', + 'transparentImageExtension': 'png', + '_': int(time.time()), + 'authURL': self.user_data['authURL'] + } + url = self._get_api_url_for(component='video_list_ids') + response = self.session.get(url, params=payload); + return self._process_response(response=response, component=url) + + def fetch_search_results (self, search_str, list_from=0, list_to=48): + """Fetches the JSON which contains the results for the given search query + + Parameters + ---------- + search_str : :obj:`str` + String to query Netflix search for + + list_from : :obj:`int` + Start entry for pagination + + list_to : :obj:`int` + Last entry for pagination + + Returns + ------- + :obj:`dict` of :obj:`dict` of :obj:`str` + Raw Netflix API call response or api call error + """ + # properly encode the search string + encoded_search_string = urllib.quote(search_str) + + paths = [ + ['search', encoded_search_string, 'titles', {'from': list_from, 'to': list_to}, ['summary', 'title']], + ['search', encoded_search_string, 'titles', {'from': list_from, 'to': list_to}, 'boxarts', '_342x192', 'jpg'], + ['search', encoded_search_string, 'titles', ['id', 'length', 'name', 'trackIds', 'requestId']] + ] + response = self._path_request(paths=paths) + return self._process_response(response=response, component='Search results') + + def fetch_video_list (self, list_id, list_from=0, list_to=20): + """Fetches the JSON which contains the contents of a given video list + + Parameters + ---------- + list_id : :obj:`str` + Unique list id to query Netflix for + + list_from : :obj:`int` + Start entry for pagination + + list_to : :obj:`int` + Last entry for pagination + + Returns + ------- + :obj:`dict` of :obj:`dict` of :obj:`str` + Raw Netflix API call response or api call error + """ + paths = [ + ['lists', list_id, {'from': list_from, 'to': list_to}, ['summary', 'title', 'synopsis', 'regularSynopsis', 'evidence', 'queue', 'episodeCount', 'info', 'maturity', 'runtime', 'seasonCount', 'releaseYear', 'userRating', 'numSeasonsLabel', 'bookmarkPosition', 'watched', 'videoQuality']], + ['lists', list_id, {'from': list_from, 'to': list_to}, 'cast', {'from': 0, 'to': 15}, ['id', 'name']], + ['lists', list_id, {'from': list_from, 'to': list_to}, 'cast', 'summary'], + ['lists', list_id, {'from': list_from, 'to': list_to}, 'genres', {'from': 0, 'to': 5}, ['id', 'name']], + ['lists', list_id, {'from': list_from, 'to': list_to}, 'genres', 'summary'], + ['lists', list_id, {'from': list_from, 'to': list_to}, 'tags', {'from': 0, 'to': 9}, ['id', 'name']], + ['lists', list_id, {'from': list_from, 'to': list_to}, 'tags', 'summary'], + ['lists', list_id, {'from': list_from, 'to': list_to}, ['creators', 'directors'], {'from': 0, 'to': 49}, ['id', 'name']], + ['lists', list_id, {'from': list_from, 'to': list_to}, ['creators', 'directors'], 'summary'], + ['lists', list_id, {'from': list_from, 'to': list_to}, 'bb2OGLogo', '_400x90', 'png'], + ['lists', list_id, {'from': list_from, 'to': list_to}, 'boxarts', '_342x192', 'jpg'], + ['lists', list_id, {'from': list_from, 'to': list_to}, 'boxarts', '_1280x720', 'jpg'], + ['lists', list_id, {'from': list_from, 'to': list_to}, 'storyarts', '_1632x873', 'jpg'], + ['lists', list_id, {'from': list_from, 'to': list_to}, 'interestingMoment', '_665x375', 'jpg'], + ['lists', list_id, {'from': list_from, 'to': list_to}, 'artWorkByType', 'BILLBOARD', '_1280x720', 'jpg'] + ]; + + response = self._path_request(paths=paths) + return self._process_response(response=response, component='Video list') + + def fetch_video_list_information (self, video_ids): + """Fetches the JSON which contains the detail information of a list of given video ids + + Parameters + ---------- + video_ids : :obj:`list` of :obj:`str` + List of video ids to fetch detail data for + + Returns + ------- + :obj:`dict` of :obj:`dict` of :obj:`str` + Raw Netflix API call response or api call error + """ + paths = [] + for video_id in video_ids: + paths.append(['videos', video_id, ['summary', 'title', 'synopsis', 'regularSynopsis', 'evidence', 'queue', 'episodeCount', 'info', 'maturity', 'runtime', 'seasonCount', 'releaseYear', 'userRating', 'numSeasonsLabel', 'bookmarkPosition', 'watched', 'videoQuality']]) + paths.append(['videos', video_id, 'cast', {'from': 0, 'to': 15}, ['id', 'name']]) + paths.append(['videos', video_id, 'cast', 'summary']) + paths.append(['videos', video_id, 'genres', {'from': 0, 'to': 5}, ['id', 'name']]) + paths.append(['videos', video_id, 'genres', 'summary']) + paths.append(['videos', video_id, 'tags', {'from': 0, 'to': 9}, ['id', 'name']]) + paths.append(['videos', video_id, 'tags', 'summary']) + paths.append(['videos', video_id, ['creators', 'directors'], {'from': 0, 'to': 49}, ['id', 'name']]) + paths.append(['videos', video_id, ['creators', 'directors'], 'summary']) + paths.append(['videos', video_id, 'bb2OGLogo', '_400x90', 'png']) + paths.append(['videos', video_id, 'boxarts', '_342x192', 'jpg']) + paths.append(['videos', video_id, 'boxarts', '_1280x720', 'jpg']) + paths.append(['videos', video_id, 'storyarts', '_1632x873', 'jpg']) + paths.append(['videos', video_id, 'interestingMoment', '_665x375', 'jpg']) + paths.append(['videos', video_id, 'artWorkByType', 'BILLBOARD', '_1280x720', 'jpg']) + + response = self._path_request(paths=paths) + return self._process_response(response=response, component='fetch_video_list_information') + + def fetch_metadata (self, id): + """Fetches the JSON which contains the metadata for a given show/movie or season id + + Parameters + ---------- + id : :obj:`str` + Show id, movie id or season id + + Returns + ------- + :obj:`dict` of :obj:`dict` of :obj:`str` + Raw Netflix API call response or api call error + """ + payload = { + 'movieid': id, + 'imageformat': 'jpg', + '_': int(time.time()) + } + url = self._get_api_url_for(component='metadata') + response = self.session.get(url, params=payload); + return self._process_response(response=response, component=url) + + def fetch_show_information (self, id, type): + """Fetches the JSON which contains the detailed contents of a show + + Parameters + ---------- + id : :obj:`str` + Unique show id to query Netflix for + + type : :obj:`str` + Can be 'movie' or 'show' + + Returns + ------- + :obj:`dict` of :obj:`dict` of :obj:`str` + Raw Netflix API call response or api call error + """ + # check if we have a show or a movie, the request made depends on this + if type == 'show': + paths = [ + ['videos', id, ['requestId', 'regularSynopsis', 'evidence']], + ['videos', id, 'seasonList', 'current', 'summary'] + ] + else: + paths = [['videos', id, ['requestId', 'regularSynopsis', 'evidence']]] + response = self._path_request(paths=paths) + return self._process_response(response=response, component='Show information') + + def fetch_seasons_for_show (self, id, list_from=0, list_to=30): + """Fetches the JSON which contains the seasons of a given show + + Parameters + ---------- + id : :obj:`str` + Unique show id to query Netflix for + + list_from : :obj:`int` + Start entry for pagination + + list_to : :obj:`int` + Last entry for pagination + + Returns + ------- + :obj:`dict` of :obj:`dict` of :obj:`str` + Raw Netflix API call response or api call error + """ + paths = [ + ['videos', id, 'seasonList', {'from': list_from, 'to': list_to}, 'summary'], + ['videos', id, 'seasonList', 'summary'], + ['videos', id, 'boxarts', '_342x192', 'jpg'], + ['videos', id, 'boxarts', '_1280x720', 'jpg'], + ['videos', id, 'storyarts', '_1632x873', 'jpg'], + ['videos', id, 'interestingMoment', '_665x375', 'jpg'] + ] + response = self._path_request(paths=paths) + return self._process_response(response=response, component='Seasons') + + def fetch_episodes_by_season (self, season_id, list_from=-1, list_to=40): + """Fetches the JSON which contains the episodes of a given season + + TODO: Add more metadata + + Parameters + ---------- + season_id : :obj:`str` + Unique season_id id to query Netflix for + + list_from : :obj:`int` + Start entry for pagination + + list_to : :obj:`int` + Last entry for pagination + + Returns + ------- + :obj:`dict` of :obj:`dict` of :obj:`str` + Raw Netflix API call response or api call error + """ + paths = [ + ['seasons', season_id, 'episodes', {'from': list_from, 'to': list_to}, ['summary', 'queue', 'info', 'maturity', 'userRating', 'bookmarkPosition', 'creditOffset', 'watched', 'videoQuality']], + #['videos', season_id, 'cast', {'from': 0, 'to': 15}, ['id', 'name']], + #['videos', season_id, 'cast', 'summary'], + #['videos', season_id, 'genres', {'from': 0, 'to': 5}, ['id', 'name']], + #['videos', season_id, 'genres', 'summary'], + #['videos', season_id, 'tags', {'from': 0, 'to': 9}, ['id', 'name']], + #['videos', season_id, 'tags', 'summary'], + #['videos', season_id, ['creators', 'directors'], {'from': 0, 'to': 49}, ['id', 'name']], + #['videos', season_id, ['creators', 'directors'], 'summary'], + ['seasons', season_id, 'episodes', {'from': list_from, 'to': list_to}, 'genres', {'from': 0, 'to': 1}, ['id', 'name']], + ['seasons', season_id, 'episodes', {'from': list_from, 'to': list_to}, 'genres', 'summary'], + ['seasons', season_id, 'episodes', {'from': list_from, 'to': list_to}, 'interestingMoment', '_1280x720', 'jpg'], + ['seasons', season_id, 'episodes', {'from': list_from, 'to': list_to}, 'interestingMoment', '_665x375', 'jpg'], + ['seasons', season_id, 'episodes', {'from': list_from, 'to': list_to}, 'boxarts', '_342x192', 'jpg'], + ['seasons', season_id, 'episodes', {'from': list_from, 'to': list_to}, 'boxarts', '_1280x720', 'jpg'] + ] + response = self._path_request(paths=paths) + return self._process_response(response=response, component='fetch_episodes_by_season') + + def refresh_session_data (self, account): + """Reload the session data (profiles, user_data, api_data) + + Parameters + ---------- + account : :obj:`dict` of :obj:`str` + Dict containing an email, country & a password property + """ + # load the profiles page (to verify the user) + response = self.session.get(self._get_document_url_for(component='profiles')) + + # parse out the needed inline information + page_soup = BeautifulSoup(response.text) + page_data = self.extract_inline_netflix_page_data(page_soup=page_soup) + self._parse_page_contents(page_soup) + account_hash = self._generate_account_hash(account=account) + self._save_data(filename=self.data_path + '_' + account_hash) + + def _path_request (self, paths): + """Executes a post request against the shakti endpoint with Falcor style payload + + Parameters + ---------- + paths : :obj:`list` of :obj:`list` + Payload with path querys for the Netflix Shakti API in Falcor style + + Returns + ------- + :obj:`requests.response` + Response from a POST call made with Requests + """ + headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json, text/javascript, */*', + } + + data = json.dumps({ + 'paths': paths, + 'authURL': self.user_data['authURL'] + }) + + params = { + 'withSize': True, + 'materialize': True, + 'model': self.user_data['gpsModel'] + } + + return self.session.post(self._get_api_url_for(component='shakti'), params=params, headers=headers, data=data) + + def _is_size_key (self, key): + """Tiny helper that checks if a given key is called $size or size, as we need to check this often + + Parameters + ---------- + key : :obj:`str` + Key to check the value for + + Returns + ------- + bool + Key has a size value or not + """ + return key == '$size' or key == 'size' + + def _get_api_url_for (self, component): + """Tiny helper that builds the url for a requested API endpoint component + + Parameters + ---------- + component : :obj:`str` + Component endpoint to build the URL for + + Returns + ------- + :obj:`str` + API Url + """ + return self.api_data['API_ROOT'] + self.api_data['API_BASE_URL'] + '/' + self.api_data['BUILD_IDENTIFIER'] + self.urls[component] + + def _get_document_url_for (self, component): + """Tiny helper that builds the url for a requested document endpoint component + + Parameters + ---------- + component : :obj:`str` + Component endpoint to build the URL for + + Returns + ------- + :obj:`str` + Document Url + """ + return self.base_url + self.urls[component] + + def _process_response (self, response, component): + """Tiny helper to check responses for API requests + + Parameters + ---------- + response : :obj:`requests.response` + Response from a requests instance + + component : :obj:`str` + Component endpoint + + Returns + ------- + :obj:`dict` of :obj:`dict` of :obj:`str` or :obj:`dict` of :obj:`str` + Raw Netflix API call response or api call error + """ + # check if we´re not authorized to make thios call + if response.status_code == 401: + return { + 'error': True, + 'message': 'Session invalid', + 'code': 401 + } + # check if somethign else failed + if response.status_code != 200: + return { + 'error': True, + 'message': 'API call for "' + component + '" failed', + 'code': response.status_code + } + # return the parsed response & everything´s fine + return response.json() + + def _update_my_list (self, video_id, operation): + """Tiny helper to add & remove items from "my list" + + Parameters + ---------- + video_id : :obj:`str` + ID of the show/movie to be added + + operation : :obj:`str` + Either "add" or "remove" + + Returns + ------- + bool + Operation successfull + """ + headers = { + 'Content-Type': 'application/json', + 'Accept': 'application/json, text/javascript, */*', + } + + payload = json.dumps({ + 'operation': operation, + 'videoId': int(video_id), + 'authURL': self.user_data['authURL'] + }) + + response = self.session.post(self._get_api_url_for(component='update_my_list'), headers=headers, data=payload) + return response.status_code == 200 + + def _save_data(self, filename): + """Tiny helper that stores session data from the session in a given file + + Parameters + ---------- + filename : :obj:`str` + Complete path incl. filename that determines where to store the cookie + + Returns + ------- + bool + Storage procedure was successfull + """ + if not os.path.isdir(os.path.dirname(filename)): + return False + with open(filename, 'w') as f: + f.truncate() + pickle.dump({ + 'user_data': self.user_data, + 'api_data': self.api_data, + 'profiles': self.profiles + }, f) + + def _load_data(self, filename): + """Tiny helper that loads session data into the active session from a given file + + Parameters + ---------- + filename : :obj:`str` + Complete path incl. filename that determines where to load the data from + + Returns + ------- + bool + Load procedure was successfull + """ + if not os.path.isfile(filename): + return False + + with open(filename) as f: + data = pickle.load(f) + if data: + self.profiles = data['profiles'] + self.user_data = data['user_data'] + self.api_data = data['api_data'] + else: + return False + + def _delete_data (self, path): + """Tiny helper that deletes session data + + Parameters + ---------- + filename : :obj:`str` + Complete path incl. filename that determines where to delete the files + + """ + head, tail = os.path.split(path) + for subdir, dirs, files in os.walk(head): + for file in files: + if tail in file: + os.remove(os.path.join(subdir, file)) + + def _save_cookies(self, filename): + """Tiny helper that stores cookies from the session in a given file + + Parameters + ---------- + filename : :obj:`str` + Complete path incl. filename that determines where to store the cookie + + Returns + ------- + bool + Storage procedure was successfull + """ + if not os.path.isdir(os.path.dirname(filename)): + return False + with open(filename, 'w') as f: + f.truncate() + pickle.dump(self.session.cookies._cookies, f) + + def _load_cookies(self, filename): + """Tiny helper that loads cookies into the active session from a given file + + Parameters + ---------- + filename : :obj:`str` + Complete path incl. filename that determines where to load the cookie from + + Returns + ------- + bool + Load procedure was successfull + """ + if not os.path.isfile(filename): + return False + + with open(filename) as f: + cookies = pickle.load(f) + if cookies: + jar = requests.cookies.RequestsCookieJar() + jar._cookies = cookies + self.session.cookies = jar + else: + return False + + def _delete_cookies (self, path): + """Tiny helper that deletes cookie data + + Parameters + ---------- + filename : :obj:`str` + Complete path incl. filename that determines where to delete the files + + """ + head, tail = os.path.split(path) + for subdir, dirs, files in os.walk(head): + for file in files: + if tail in file: + os.remove(os.path.join(subdir, file)) + + def _generate_account_hash (self, account): + """Generates a has for the given account (used for cookie verification) + + Parameters + ---------- + account : :obj:`dict` of :obj:`str` + Dict containing an email, country & a password property + + Returns + ------- + :obj:`str` + Account data hash + """ + return base64.urlsafe_b64encode(account['email']) diff --git a/resources/lib/__init__.py b/resources/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/resources/lib/common.py b/resources/lib/common.py new file mode 100644 index 0000000..161bcae --- /dev/null +++ b/resources/lib/common.py @@ -0,0 +1,18 @@ +import os +import xbmc +import xbmcaddon +import xbmcgui +import xbmcvfs + +ADDON = xbmcaddon.Addon() +ADDONVERSION = ADDON.getAddonInfo('version') +ADDONNAME = ADDON.getAddonInfo('name') +ADDONPATH = ADDON.getAddonInfo('path').decode('utf-8') +ADDONPROFILE = xbmc.translatePath( ADDON.getAddonInfo('profile') ).decode('utf-8') +ICON = ADDON.getAddonInfo('icon') + +def log(txt): + if isinstance (txt,str): + txt = txt.decode("utf-8") + message = u'%s: %s' % ("service.msl", txt) + xbmc.log(msg=message.encode("utf-8"), level=xbmc.LOGDEBUG) diff --git a/resources/lib/utils.py b/resources/lib/utils.py new file mode 100644 index 0000000..25cd285 --- /dev/null +++ b/resources/lib/utils.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Module: utils +# Created on: 13.01.2017 + +# strips html from input +# used the kick out the junk, when parsing the inline JS objects of the Netflix homepage +from HTMLParser import HTMLParser +class MLStripper(HTMLParser): + def __init__(self): + self.reset() + self.fed = [] + def handle_data(self, d): + self.fed.append(d) + def get_data(self): + return ''.join(self.fed) + +def strip_tags(html): + s = MLStripper() + s.feed(html) + return s.get_data() + +# Takes everything, does nothing, classic no operation function +def noop (**kwargs): + return True + +# log decorator +def log(f, name=None): + if name is None: + name = f.func_name + def wrapped(*args, **kwargs): + that = args[0] + class_name = that.__class__.__name__ + arguments = '' + for key, value in kwargs.iteritems(): + if key != 'account' and key != 'credentials': + arguments += ":%s = %s:" % (key, value) + if arguments != '': + that.log('"' + class_name + '::' + name + '" called with arguments ' + arguments) + else: + that.log('"' + class_name + '::' + name + '" called') + result = f(*args, **kwargs) + that.log('"' + class_name + '::' + name + '" returned: ' + str(result)) + return result + wrapped.__doc__ = f.__doc__ + return wrapped diff --git a/resources/screenshot-01.jpg b/resources/screenshot-01.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9f1d39856505ab9e2e9bcebd280f1ce4e259d7a1 GIT binary patch literal 305841 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%0DFlsVWX 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
%Qqx!7j&SvZ5Qh5t_ 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

8j_+3|7x_z#bgS%VmHNHNVd%m?{MB!$g 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