astrXbian/.install/.kodi/addons/plugin.video.youtube/resources/lib/youtube_plugin/youtube/client/__config__.py

237 lines
11 KiB
Python
Raw Normal View History

2020-12-17 21:52:17 +01:00
# -*- coding: utf-8 -*-
"""
Copyright (C) 2017-2018 plugin.video.youtube
SPDX-License-Identifier: GPL-2.0-only
See LICENSES/GPL-2.0-only for more information.
"""
from base64 import b64decode
from hashlib import md5
from ...kodion.json_store import APIKeyStore, LoginTokenStore
from ...kodion import Context as __Context
from ... import key_sets
DEFAULT_SWITCH = 1
__context = __Context(plugin_id='plugin.video.youtube')
__settings = __context.get_settings()
class APICheck(object):
def __init__(self, context, settings):
self._context = context
self._settings = settings
self._ui = context.get_ui()
self._api_jstore = APIKeyStore()
self._json_api = self._api_jstore.get_data()
self._am_jstore = LoginTokenStore()
self._json_am = self._am_jstore.get_data()
self.changed = False
self._on_init()
def _on_init(self):
self._json_api = self._api_jstore.get_data()
j_key = self._json_api['keys']['personal'].get('api_key', '')
j_id = self._json_api['keys']['personal'].get('client_id', '')
j_secret = self._json_api['keys']['personal'].get('client_secret', '')
if j_key and j_id and j_secret:
# users are now pasting keys into api_keys.json
# try stripping whitespace and .apps.googleusercontent.com from keys and saving the result if they differ
stripped_key, stripped_id, stripped_secret = self._strip_api_keys(j_key, j_id, j_secret)
if stripped_key and stripped_id and stripped_secret:
if (j_key != stripped_key) or (j_id != stripped_id) or (j_secret != stripped_secret):
self._json_api['keys']['personal'] = {'api_key': stripped_key, 'client_id': stripped_id, 'client_secret': stripped_secret}
self._api_jstore.save(self._json_api)
original_key = self._settings.get_string('youtube.api.key')
original_id = self._settings.get_string('youtube.api.id')
original_secret = self._settings.get_string('youtube.api.secret')
if original_key and original_id and original_secret:
own_key, own_id, own_secret = self._strip_api_keys(original_key, original_id, original_secret)
if own_key and own_id and own_secret:
if (original_key != own_key) or (original_id != own_id) or (original_secret != own_secret):
self._settings.set_string('youtube.api.key', own_key)
self._settings.set_string('youtube.api.id', own_id)
self._settings.set_string('youtube.api.secret', own_secret)
if (j_key != own_key) or (j_id != own_id) or (j_secret != own_secret):
self._json_api['keys']['personal'] = {'api_key': own_key, 'client_id': own_id, 'client_secret': own_secret}
self._api_jstore.save(self._json_api)
self._json_api = self._api_jstore.get_data()
j_key = self._json_api['keys']['personal'].get('api_key', '')
j_id = self._json_api['keys']['personal'].get('client_id', '')
j_secret = self._json_api['keys']['personal'].get('client_secret', '')
if not original_key or not original_id or not original_secret and (j_key and j_secret and j_id):
self._settings.set_string('youtube.api.key', j_key)
self._settings.set_string('youtube.api.id', j_id)
self._settings.set_string('youtube.api.secret', j_secret)
switch = self.get_current_switch()
user = self.get_current_user()
access_token = self._settings.get_string('kodion.access_token', '')
refresh_token = self._settings.get_string('kodion.refresh_token', '')
token_expires = self._settings.get_int('kodion.access_token.expires', -1)
last_hash = self._settings.get_string('youtube.api.last.hash', '')
if not self._json_am['access_manager']['users'].get(user, {}).get('access_token') or \
not self._json_am['access_manager']['users'].get(user, {}).get('refresh_token'):
if access_token and refresh_token:
self._json_am['access_manager']['users'][user]['access_token'] = access_token
self._json_am['access_manager']['users'][user]['refresh_token'] = refresh_token
self._json_am['access_manager']['users'][user]['token_expires'] = token_expires
if switch == 'own':
own_key_hash = self._get_key_set_hash('own')
if last_hash == self._get_key_set_hash('own', True) or \
last_hash == own_key_hash:
self._json_am['access_manager']['users'][user]['last_key_hash'] = own_key_hash
self._am_jstore.save(self._json_am)
if access_token or refresh_token or last_hash:
self._settings.set_string('kodion.access_token', '')
self._settings.set_string('kodion.refresh_token', '')
self._settings.set_int('kodion.access_token.expires', -1)
self._settings.set_string('youtube.api.last.hash', '')
updated_hash = self._api_keys_changed(switch)
if updated_hash:
self._context.log_warning('User: |%s| Switching API key set to |%s|' % (user, switch))
self._json_am['access_manager']['users'][user]['last_key_hash'] = updated_hash
self._am_jstore.save(self._json_am)
self._context.log_debug('API key set changed: Signing out')
self._context.execute('RunPlugin(plugin://plugin.video.youtube/sign/out/?confirmed=true)')
else:
self._context.log_debug('User: |%s| Using API key set: |%s|' % (user, switch))
def get_current_switch(self):
return 'own'
def get_current_user(self):
self._json_am = self._am_jstore.get_data()
return self._json_am['access_manager'].get('current_user', '0')
def has_own_api_keys(self):
self._json_api = self._api_jstore.get_data()
own_key = self._json_api['keys']['personal']['api_key']
own_id = self._json_api['keys']['personal']['client_id']
own_secret = self._json_api['keys']['personal']['client_secret']
return False if not own_key or \
not own_id or \
not own_secret else True
def get_api_keys(self, switch):
self._json_api = self._api_jstore.get_data()
if switch == 'youtube-tv':
api_key = b64decode(key_sets['youtube-tv']['key']).decode('utf-8'),
client_id = u''.join([b64decode(key_sets['youtube-tv']['id']).decode('utf-8'), u'.apps.googleusercontent.com'])
client_secret = b64decode(key_sets['youtube-tv']['secret']).decode('utf-8')
elif switch == 'developer':
self._json_api = self._api_jstore.get_data()
return self._json_api['keys']['developer']
elif switch == 'own':
api_key = self._json_api['keys']['personal']['api_key']
client_id = u''.join([self._json_api['keys']['personal']['client_id'], u'.apps.googleusercontent.com'])
client_secret = self._json_api['keys']['personal']['client_secret']
else:
api_key = b64decode(key_sets['provided'][switch]['key']).decode('utf-8')
client_id = u''.join([b64decode(key_sets['provided'][switch]['id']).decode('utf-8'), u'.apps.googleusercontent.com'])
client_secret = b64decode(key_sets['provided'][switch]['secret']).decode('utf-8')
return api_key, client_id, client_secret
def _api_keys_changed(self, switch):
self._json_am = self._am_jstore.get_data()
user = self.get_current_user()
last_set_hash = self._json_am['access_manager']['users'].get(user, {}).get('last_key_hash', '')
current_set_hash = self._get_key_set_hash(switch)
if last_set_hash != current_set_hash:
self.changed = True
return current_set_hash
else:
self.changed = False
return None
def _get_key_set_hash(self, switch, old=False):
api_key, client_id, client_secret = self.get_api_keys(switch)
if old and switch == 'own':
client_id = client_id.replace(u'.apps.googleusercontent.com', u'')
m = md5()
m.update(api_key.encode('utf-8'))
m.update(client_id.encode('utf-8'))
m.update(client_secret.encode('utf-8'))
return m.hexdigest()
def _strip_api_keys(self, api_key, client_id, client_secret):
stripped_key = ''.join(api_key.split())
stripped_id = ''.join(client_id.replace('.apps.googleusercontent.com', '').split())
stripped_secret = ''.join(client_secret.split())
if api_key != stripped_key:
if stripped_key not in api_key:
self._context.log_debug('Personal API setting: |Key| Skipped: potentially mangled by stripping')
return_key = api_key
else:
self._context.log_debug('Personal API setting: |Key| had whitespace removed')
return_key = stripped_key
else:
return_key = api_key
if client_id != stripped_id:
if stripped_id not in client_id:
self._context.log_debug('Personal API setting: |Id| Skipped: potentially mangled by stripping')
return_id = client_id
else:
googleusercontent = ''
if '.apps.googleusercontent.com' in client_id:
googleusercontent = ' and .apps.googleusercontent.com'
self._context.log_debug('Personal API setting: |Id| had whitespace%s removed' % googleusercontent)
return_id = stripped_id
else:
return_id = client_id
if client_secret != stripped_secret:
if stripped_secret not in client_secret:
self._context.log_debug('Personal API setting: |Secret| Skipped: potentially mangled by stripping')
return_secret = client_secret
else:
self._context.log_debug('Personal API setting: |Secret| had whitespace removed')
return_secret = stripped_secret
else:
return_secret = client_secret
return return_key, return_id, return_secret
notification_data = {'use_httpd': (__settings.use_dash_videos() and
__settings.use_dash()) or
(__settings.api_config_page()),
'httpd_port': __settings.httpd_port(),
'whitelist': __settings.httpd_whitelist(),
'httpd_address': __settings.httpd_listen()
}
__context.send_notification('check_settings', notification_data)
_api_check = APICheck(__context, __settings)
keys_changed = _api_check.changed
current_user = _api_check.get_current_user()
api = dict()
youtube_tv = dict()
_current_switch = _api_check.get_current_switch()
api['key'], api['id'], api['secret'] = _api_check.get_api_keys(_current_switch)
youtube_tv['key'], youtube_tv['id'], youtube_tv['secret'] = _api_check.get_api_keys('youtube-tv')
developer_keys = _api_check.get_api_keys('developer')