Issues 351 - Tartarus Integration

- Creating API to communicate with remote server
- Updating Identity data
- Adapting RemoteConfiguration load to new server
pull/420/head
Jonathan D'Orleans 2016-08-30 22:55:35 -04:00
parent 0ecb369397
commit 3280d57b18
8 changed files with 108 additions and 74 deletions

57
mycroft/api/__init__.py Normal file
View File

@ -0,0 +1,57 @@
import requests
from mycroft.configuration import ConfigurationManager
from mycroft.identity import IdentityManager
class Api(object):
def __init__(self, path):
self.path = path
config = ConfigurationManager.get()
config_server = config.get("server")
self.url = config_server.get("url")
self.version = config_server.get("version")
self.identity = IdentityManager().get()
def request(self, params):
method = params.get("method", "GET")
headers = self.build_headers(params)
body = self.build_body(params)
url = self.build_url(params)
return requests.request(method, url, headers=headers, data=body)
def build_headers(self, params):
headers = params.get("headers", {})
self.add_content_type(headers)
self.add_authorization(headers)
return headers
def add_content_type(self, headers):
if not headers["Content-Type"]:
headers["Content-Type"] = "application/json"
def add_authorization(self, headers):
if not headers["Authorization"]:
headers["Authorization"] = "Bearer " + self.identity.token
def build_body(self, params):
body = params.get("body")
if body and params["headers"]["Content-Type"] == "application/json":
for k, v in body:
if v == "":
body[k] = None
return body
def build_url(self, params):
path = params.get("path", "")
version = params.get("version", self.version)
return self.url + "/" + version + "/" + self.path + path
class DeviceApi(Api):
def __init__(self):
super(DeviceApi, self).__init__("device")
def find_setting(self):
params = {"path": "/" + self.identity.device_id + "/setting"}
return self.request(params)

View File

@ -80,7 +80,7 @@ class CerberusGoogleProxy(object):
timer.start()
identity = IdentityManager().get()
headers = {}
if identity.token:
if identity:
headers['Authorization'] = 'Bearer %s:%s' % (
identity.device_id, identity.token)

View File

@ -16,13 +16,11 @@
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.
import collections
import requests
from configobj import ConfigObj
from genericpath import exists, isfile
from os.path import join, dirname, expanduser
from mycroft.identity import IdentityManager
from mycroft.util import str2bool
from mycroft.api import DeviceApi
from mycroft.util.log import getLogger
__author__ = 'seanfitz, jdorleans'
@ -106,11 +104,11 @@ class RemoteConfiguration(object):
config in the [core] config section
"""
__remote_keys = {
"default_location": "location",
"default_language": "lang",
"timezone": "timezone"
"unit": "unit"
}
__api = DeviceApi()
@staticmethod
def validate_config(config):
if not (config and isinstance(config, dict)):
@ -119,20 +117,14 @@ class RemoteConfiguration(object):
@staticmethod
def load(config=None):
api = RemoteConfiguration.__api
RemoteConfiguration.validate_config(config)
auto_update = config.get("server", {}).get("auto_update", False)
identity = IdentityManager().get()
config_remote = config.get("remote_configuration", {})
enabled = str2bool(config_remote.get("enabled", "False"))
if enabled and identity.token:
url = config_remote.get("url")
auth_header = "Bearer %s:%s" % (identity.device_id, identity.token)
if auto_update:
try:
response = requests.get(url,
headers={"Authorization": auth_header})
user = response.json()
RemoteConfiguration.__load_attributes(config, user)
setting = api.find_setting().json()
RemoteConfiguration.__load_attributes(config, setting)
except Exception as e:
logger.error(
"Failed to fetch remote configuration: %s" % repr(e))
@ -142,18 +134,16 @@ class RemoteConfiguration(object):
return config
@staticmethod
def __load_attributes(config, user):
def __load_attributes(config, setting):
config_core = config["core"]
for att in user["attributes"]:
att_name = att.get("attribute_name")
name = RemoteConfiguration.__remote_keys.get(att_name)
for k, v in setting:
key = RemoteConfiguration.__remote_keys.get(k)
if name:
config_core[name] = str(att.get("attribute_value"))
logger.info(
"Accepting remote configuration: core[%s] == %s" %
(name, att["attribute_value"]))
if config_core.__contains__(key):
config_core[key] = str(v)
logger.info("Setting remote configuration: core[%s] == %s" %
(key, v))
class ConfigurationManager(object):

View File

@ -7,6 +7,11 @@ date.format = "%A, %B %d, %Y"
stop_threshold = 2 # in seconds
third_party_skills_dir = "~/.mycroft/third_party_skills"
[server]
url = "https://api.mycroft.ai"
version = "v1"
auto_update = True
[messagebus_service]
host = "0.0.0.0"
port = 8000
@ -28,10 +33,6 @@ port = 443
route = "/pairing"
ssl = True
[remote_configuration]
url = "https://cerberus.mycroft.ai/user"
enabled = True
[speech_client]
sample_rate = 16000
channels = 1

View File

@ -16,47 +16,33 @@
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.
from uuid import uuid4
import json
from mycroft.filesystem import FileSystemAccess
class DeviceIdentity(object):
def __init__(self, **kwargs):
self.device_id = kwargs.get('device_id')
self.owner = kwargs.get('owner')
self.token = kwargs.get('token')
@staticmethod
def load(identity_file_handle):
json_blob = json.load(identity_file_handle)
return DeviceIdentity(**json_blob)
def save(self, identity_file_handle):
json.dump(self.__dict__, identity_file_handle)
class IdentityManager(object):
FILE = 'identity.json'
def __init__(self):
self.filesystem = FileSystemAccess('identity')
self.file_system = FileSystemAccess('identity')
self.identity = None
self.initialize()
self.load()
def initialize(self):
if self.filesystem.exists('identity.json'):
self.identity = DeviceIdentity.load(self.filesystem.open(
'identity.json', 'r'))
else:
identity = DeviceIdentity(device_id=str(uuid4()))
self.update(identity)
def load(self):
with self.file_system.open(self.FILE, 'r') as f:
self.identity = DeviceIdentity(**json.load(f))
def update(self, identity):
def save(self, identity):
self.identity = identity
with self.filesystem.open('identity.json', 'w') as f:
self.identity.save(f)
def is_paired(self):
return self.identity is not None and self.identity.owner is not None
with self.file_system.open(self.FILE, 'w') as f:
json.dump(self.identity, f)
def get(self):
return self.identity

View File

@ -46,14 +46,11 @@ class DevicePairingClient(object):
pairing_code if pairing_code else generate_pairing_code())
def on_registration(self, message):
# TODO: actually accept the configuration message and store it in
# identity
payload = message.metadata
identity = self.identity_manager.get()
register_payload = message.metadata
if register_payload.get("device_id") == identity.device_id:
identity.token = register_payload.get('token')
identity.owner = register_payload.get('user')
self.identity_manager.update(identity)
if identity and payload.get("device_id") == identity.device_id:
identity.token = payload.get('token')
self.identity_manager.save(identity)
self.ws_client.close()
self.paired = True

View File

@ -37,7 +37,7 @@ class CerberusConfigSkill(MycroftSkill):
def handle_update_intent(self, message):
identity = IdentityManager().get()
if not identity.owner:
if identity:
self.speak_dialog("not.paired")
else:
ConfigurationManager.load_remote()

View File

@ -17,18 +17,17 @@
from StringIO import StringIO
from os.path import dirname, join
import re
import requests
import wolframalpha
from os.path import dirname, join
from six.moves import urllib
from mycroft.identity import IdentityManager
from mycroft.skills.core import MycroftSkill
from mycroft.util import CerberusAccessDenied
from mycroft.util.log import getLogger
from mycroft.messagebus.message import Message
__author__ = 'seanfitz'
@ -83,8 +82,12 @@ class CerberusWolframAlphaClient(object):
"""
Query Wolfram|Alpha with query using the v2.0 API
"""
response = {}
identity = IdentityManager().get()
bearer_token = 'Bearer %s:%s' % (identity.device_id, identity.token)
if identity:
bearer_token = 'Bearer %s:%s' % \
(identity.device_id, identity.token)
query = urllib.parse.urlencode(dict(input=query))
url = 'https://cerberus.mycroft.ai/wolframalpha/v2/query?' + query
headers = {'Authorization': bearer_token}