Skip to content

Commit

Permalink
Merge pull request #180 from asciidisco/feat/adultpin
Browse files Browse the repository at this point in the history
feat(video): Add ability to turn on the adult pin verification
  • Loading branch information
asciidisco authored Oct 10, 2017
2 parents 1d9bccb + d2768f2 commit 64f9fe0
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 12 deletions.
4 changes: 4 additions & 0 deletions resources/language/English/strings.po
Original file line number Diff line number Diff line change
Expand Up @@ -264,3 +264,7 @@ msgstr ""
msgctxt "#30061"
msgid "Update inside library"
msgstr ""

msgctxt "#30062"
msgid "Enable/disable adult pin. Active:"
msgstr ""
4 changes: 4 additions & 0 deletions resources/language/German/strings.po
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,7 @@ msgstr "Aktiviere HEVC profile (z.b. für 4k in Android)"
msgctxt "#30061"
msgid "Update inside library"
msgstr "In Bibliothek aktualisieren"

msgctxt "#30062"
msgid "Enable/disable adult pin. Active:"
msgstr "Kindersicherungs PIN Abfrage ein-/ausschalten. Aktiv:"
40 changes: 38 additions & 2 deletions resources/lib/KodiHelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,29 @@ def show_rating_dialog (self):
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_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_search_term_dialog (self):
"""Asks the user for a term to query the netflix search for
Expand Down Expand Up @@ -301,6 +324,17 @@ def get_setting (self, key):
"""
return self.get_addon().getSetting(key)

def toggle_adult_pin(self):
"""Toggles the adult pin setting"""
addon = self.get_addon()
adultpin_enabled = False
raw_adultpin_enabled = addon.getSetting('adultpin_enable')
if raw_adultpin_enabled == 'true' or raw_adultpin_enabled == 'True':
adultpin_enabled = True
if adultpin_enabled is False:
return addon.setSetting('adultpin_enable', 'True')
return addon.setSetting('adultpin_enable', 'False')

def get_credentials (self):
"""Returns the users stored credentials
Expand Down Expand Up @@ -707,14 +741,16 @@ def build_video_listing (self, video_list, actions, type, build_url, has_more=Fa
li = self._generate_context_menu_items(entry=video, li=li)
# 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
# it´s a movie, so we need no subfolder & a route to play it
isFolder = False
url = build_url({'action': 'play_video', 'video_id': video_list_id, 'infoLabels': infos})
needs_pin = (True, False)[int(video['maturity']['level']) >= 1000]
url = build_url({'action': 'play_video', 'video_id': video_list_id, 'infoLabels': infos, 'pin': needs_pin})
view = VIEW_MOVIE
else:
# it´s a show, so we need a subfolder & route (for seasons)
isFolder = True
params = {'action': actions[video['type']], 'show_id': video_list_id}
params['pin'] = (True, False)[int(video['maturity']['level']) >= 1000]
if 'tvshowtitle' in infos:
params['tvshowtitle'] = base64.urlsafe_b64encode(infos.get('tvshowtitle', '').encode('utf-8'))
url = build_url(params)
Expand Down
30 changes: 30 additions & 0 deletions resources/lib/Navigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ def router(self, paramstring):
if self.establish_session(account=account) != True:
return self.kodi_helper.show_login_failed_notification()

# switch user account
if 'action' in params.keys() and params['action'] == 'toggle_adult_pin':
adult_pin = self.kodi_helper.show_adult_pin_dialog()
if self._check_response(self.call_netflix_service({'method': 'send_adult_pin', 'pin': adult_pin})) != True:
return self.kodi_helper.show_wrong_adult_pin_notification()
return self.kodi_helper.toggle_adult_pin()

# 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)
Expand Down Expand Up @@ -145,6 +152,14 @@ def router(self, paramstring):
# 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
ask_for_adult_pin = self.kodi_helper.get_setting('adultpin_enable').lower() == 'true'
if ask_for_adult_pin is True:
if self.check_for_adult_pin(params=params):
adult_pin = self.kodi_helper.show_adult_pin_dialog()
if self._check_response(self.call_netflix_service({'method': 'send_adult_pin', 'pin': adult_pin})) != True:
return self.kodi_helper.show_wrong_adult_pin_notification()
self.play_video(video_id=params['video_id'], start_offset=params.get('start_offset', -1), infoLabels=params.get('infoLabels', {}))
elif params['action'] == 'user-items' and params['type'] == 'search':
# if the user requested a search, ask for the term
Expand Down Expand Up @@ -472,6 +487,21 @@ def switch_account(self):
return self.kodi_helper.show_login_failed_notification()
return True

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.get('pin') == 'True']

@log
def before_routing_action(self, params):
"""Executes actions before the actual routing takes place:
Expand Down
16 changes: 16 additions & 0 deletions resources/lib/NetflixHttpSubRessourceHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,22 @@ def fetch_metadata (self, params):
video_id = params.get('video_id', [''])[0]
return self.netflix_session.fetch_metadata(id=video_id)

def send_adult_pin(self, params):
"""Checks the adult pin
Parameters
----------
params : :obj:`dict` of :obj:`str`
Request params
Returns
-------
:obj:`Requests.Response`
Response of the remote call
"""
pin = params.get('pin', [''])[0]
return self.netflix_session.send_adult_pin(pin=pin)

def switch_profile (self, params):
"""Switch profile proxy function
Expand Down
19 changes: 9 additions & 10 deletions resources/lib/NetflixSession.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ def switch_profile (self, profile_id, account):
self.user_data['guid'] = profile_id;
return self._save_data(filename=self.data_path + '_' + account_hash)

def send_adult_pin (self, pin):
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)
Expand All @@ -309,16 +309,15 @@ def send_adult_pin (self, pin):
"""
payload = {
'pin': pin,
'authURL': self.user_data['authURL']
'authURL': self.user_data.get('authURL', '')
}
response = self._session_get(component='adult_pin', params=payload)
response = self._session_post(component='adult_pin', type='api', data=payload)
pin_response = self._process_response(response=response, component=self._get_api_url_for(component='adult_pin'))
keys = pin_response.keys()
if 'success' in keys:
return True
if 'error' in keys:
return pin_response
return False
if 'error' in pin_response.keys():
self.log(msg='Pin error')
self.log(msg=str(pin_response))
return False
return pin_response.get('success', False)

def add_to_list (self, video_id):
"""Adds a video to "my list" on Netflix
Expand Down Expand Up @@ -1965,7 +1964,7 @@ def _session_post (self, component, type='document', data={}, headers={}, params
:obj:`str`
Contents of the field to match
"""
url = self._get_document_url_for(component=component) if type == 'document' else self._get_api_url_for(component=component)
url = self._get_document_url_for(component=component) if type == 'document' else self._get_api_url_for(component=component)
start = time()
try:
response = self.session.post(url=url, data=data, params=params, headers=headers, verify=self.verify_ssl)
Expand Down
2 changes: 2 additions & 0 deletions resources/settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<setting id="password" type="text" visible="false" default=""/>
<setting id="switch_account" type="action" label="30059c" action="RunPlugin(plugin://plugin.video.netflix/?action=switch_account)" option="close"/>
<setting id="logout" type="action" label="30017" action="RunPlugin(plugin://plugin.video.netflix/?action=logout)" option="close"/>
<setting id="adultpin_enable" type="action" label="30062" default="False" action="RunPlugin(plugin://plugin.video.netflix/?action=toggle_adult_pin)"/>
<setting type="sep"/>
<setting id="is_settings" type="action" label="30035" action="RunPlugin(plugin://plugin.video.netflix/?mode=openSettings&url=is)" option="close"/>
</category>
<category label="30025">
Expand Down

0 comments on commit 64f9fe0

Please sign in to comment.