Skip to content

Commit

Permalink
use web ui to choose between alexa and dueros
Browse files Browse the repository at this point in the history
  • Loading branch information
xiongyihui committed Jul 11, 2018
1 parent 34b899d commit f6f322d
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 60 deletions.
9 changes: 7 additions & 2 deletions avs/alexa.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from avs.interface.speech_synthesizer import SpeechSynthesizer
from avs.interface.system import System
import avs.config
import avs.auth

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -190,7 +191,7 @@ def _run(self):
'context': self.context,
'event': event
}
logger.info('metadata: {}'.format(json.dumps(metadata, indent=4)))
# logger.info('metadata: {}'.format(json.dumps(metadata, indent=4)))

json_part = '--{}\r\n'.format(eventchannel_boundary)
json_part += 'Content-Disposition: form-data; name="metadata"\r\n'
Expand Down Expand Up @@ -381,7 +382,11 @@ def __exit__(self, exc_type, exc_val, exc_tb):
def main():
logging.basicConfig(level=logging.INFO)

config = None if len(sys.argv) < 2 else sys.argv[1]
config = avs.config.DEFAULT_CONFIG_FILE if len(sys.argv) < 2 else sys.argv[1]

if not os.path.isfile(config):
print('Login amazon alexa or baidu dueros first')
avs.auth.auth(None, config)

audio = Audio()
alexa = Alexa(config)
Expand Down
109 changes: 73 additions & 36 deletions avs/auth.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import datetime
import json
import os
import time
import uuid

Expand All @@ -14,18 +15,9 @@

class MainHandler(tornado.web.RequestHandler):
def initialize(self, config, output):
self.config = avs.config.load(configfile=config)
self.config = config
self.output = output

if ('host_url' in self.config) and self.config['host_url'] == 'dueros-h2.baidu.com':
self.token_url = 'https://openapi.baidu.com/oauth/2.0/token'
self.oauth_url = 'https://openapi.baidu.com/oauth/2.0/authorize'
self.scope = 'basic'
else:
self.token_url = 'https://api.amazon.com/auth/o2/token'
self.oauth_url = 'https://www.amazon.com/ap/oa'
self.scope = 'alexa:all'

@tornado.web.asynchronous
def get(self):
redirect_uri = self.request.protocol + ":https://" + self.request.host + "/authresponse"
Expand All @@ -39,9 +31,15 @@ def get(self):
"redirect_uri": redirect_uri
}

r = requests.post(self.token_url, data=payload)
if self.config['host_url'] == 'dueros-h2.baidu.com':
token_url = 'https://openapi.baidu.com/oauth/2.0/token'
message = 'Succeed to login Baidu DuerOS'
else:
token_url = 'https://api.amazon.com/auth/o2/token'
message = 'Succeed to login Amazon Alexa Voice Service'

r = requests.post(token_url, data=payload)
config = r.json()
print(r.text)
self.config['refresh_token'] = config['refresh_token']

if 'access_token' in config:
Expand All @@ -53,32 +51,66 @@ def get(self):
print(json.dumps(self.config, indent=4))
avs.config.save(self.config, configfile=self.output)

self.write('Succeed to login Amazon Alexa Voice Service')
self.write(message)
self.finish()
tornado.ioloop.IOLoop.instance().stop()
else:
scope_data = json.dumps({
"alexa:all": {
"productID": self.config['product_id'],
"productInstanceAttributes": {
"deviceSerialNumber": uuid.uuid4().hex
}
elif self.request.path == '/alexa':
self.alexa_oauth()
elif self.request.path == '/dueros':
self.dueros_oauth()
elif self.request.path == '/':
index_html = os.path.realpath(os.path.join(os.path.dirname(__file__), 'resources/web/index.html'))
with open(index_html) as f:
self.write(f.read())
self.finish()

def alexa_oauth(self):
if 'client_secret' not in self.config:
self.config.update(avs.config.alexa())
if 'dueros-device-id' in self.config:
del self.config['dueros-device-id']
self.config.update(avs.config.alexa())

oauth_url = 'https://www.amazon.com/ap/oa'
redirect_uri = self.request.protocol + ":https://" + self.request.host + "/authresponse"

scope_data = json.dumps({
"alexa:all": {
"productID": self.config['product_id'],
"productInstanceAttributes": {
"deviceSerialNumber": uuid.uuid4().hex
}
})
payload = {
"client_id": self.config['client_id'],
"scope": self.scope,
# "scope_data": scope_data,
"response_type": "code",
"redirect_uri": redirect_uri
}
})
payload = {
"client_id": self.config['client_id'],
"scope": "alexa:all",
"scope_data": scope_data,
"response_type": "code",
"redirect_uri": redirect_uri
}

req = requests.Request('GET', oauth_url, params=payload)
p = req.prepare()
self.redirect(p.url)

def dueros_oauth(self):
if 'client_secret' not in self.config:
self.config.update(avs.config.dueros())

oauth_url = 'https://openapi.baidu.com/oauth/2.0/authorize'
redirect_uri = self.request.protocol + ":https://" + self.request.host + "/authresponse"

if ('host_url' not in self.config) or self.config['host_url'] != 'dueros-h2.baidu.com':
payload['scope_data'] = scope_data
payload = {
"client_id": self.config["client_id"],
"scope": "basic",
"response_type": "code",
"redirect_uri": redirect_uri
}

req = requests.Request('GET', self.oauth_url, params=payload)
p = req.prepare()
self.redirect(p.url)
req = requests.Request('GET', oauth_url, params=payload)
p = req.prepare()
self.redirect(p.url)


def open_webbrowser():
Expand All @@ -93,19 +125,24 @@ def open_webbrowser():
webbrowser.open('http:https://127.0.0.1:3000')


@click.command()
@click.option('--config', '-c', help='configuration json file with product_id, client_id and client_secret')
@click.option('--output', '-o', default=avs.config.DEFAULT_CONFIG_FILE, help='output json file with refresh token')
def main(config, output):
def auth(config, output):
import threading
threading.Thread(target=open_webbrowser).start()

config = avs.config.load(config) if config else {}

application = tornado.web.Application([(r".*", MainHandler, dict(config=config, output=output))])
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(3000)
tornado.ioloop.IOLoop.instance().start()
tornado.ioloop.IOLoop.instance().close()

@click.command()
@click.option('--config', '-c', help='configuration json file with product_id, client_id and client_secret')
@click.option('--output', '-o', default=avs.config.DEFAULT_CONFIG_FILE, help='output json file with refresh token')
def main(config, output):
auth(config, output)


if __name__ == '__main__':
main()
45 changes: 23 additions & 22 deletions avs/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,16 @@
DEFAULT_CONFIG_FILE = os.path.join(os.path.expanduser('~'), '.avs.json')


def load(configfile=None):
if configfile is None:
if os.path.isfile(DEFAULT_CONFIG_FILE):
configfile = DEFAULT_CONFIG_FILE
else:
if sys.argv[0].find('dueros-auth') >= 0:
product_id = "xiaojing-" + uuid.uuid4().hex
return {
"dueros-device-id": product_id,
"client_id": "lud6jnwdVFim4K4Zkoas3BkRVLvCO57Z",
"host_url": "dueros-h2.baidu.com",
"client_secret": "A017kke1GSSz7hp8Fj6ySoIWrnFraxf5",
"product_id": product_id
}

else:
return {
"product_id": "ReSpeaker",
"client_id": "amzn1.application-oa2-client.91b0cebd9074412cba1570a5dd03fc6e",
"client_secret": "fbd7a0e72953c1dd9a920670cf7f4115f694cd47c32a1513dc12a804c7f804e2"
}
def load(configfile=DEFAULT_CONFIG_FILE):
if not os.path.isfile(configfile):
raise RuntimeError('No configuration file')

with open(configfile, 'r') as f:
config = json.load(f)
require_keys = ['product_id', 'client_id', 'client_secret']
for key in require_keys:
if not ((key in config) and config[key]):
raise KeyError('{} should include "{}"'.format(configfile, key))
raise RuntimeError('{} should include "{}"'.format(configfile, key))

if ('host_url' not in config) or (not config['host_url']):
config['host_url'] = 'avs-alexa-na.amazon.com'
Expand All @@ -56,3 +38,22 @@ def save(config, configfile=None):

with open(configfile, 'w') as f:
json.dump(config, f, indent=4)


def dueros():
product_id = "xiaojing-" + uuid.uuid4().hex
return {
"dueros-device-id": product_id,
"client_id": "lud6jnwdVFim4K4Zkoas3BkRVLvCO57Z",
"host_url": "dueros-h2.baidu.com",
"client_secret": "A017kke1GSSz7hp8Fj6ySoIWrnFraxf5",
"product_id": product_id
}

def alexa():
return {
"product_id": "ReSpeaker",
"client_id": "amzn1.application-oa2-client.91b0cebd9074412cba1570a5dd03fc6e",
"host_url": "avs-alexa-na.amazon.com",
"client_secret": "fbd7a0e72953c1dd9a920670cf7f4115f694cd47c32a1513dc12a804c7f804e2"
}
61 changes: 61 additions & 0 deletions avs/resources/web/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- <link rel="stylesheet" href="https://unpkg.com/[email protected]/build/pure-min.css"> -->
<style>
html {
height: 100%;
}

body {
background: #4CAF50;
text-align: center;
font-family: monospace;
width: 100%;
height: 100%;
margin: 0px;
}

.one-third {
height: 33%;
margin:0 auto;
position: relative;
}

a {
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
text-decoration: none;
font-size: 2em;
color: black;
}

#alexa {
background: #aee571;
}

#dueros {
background: #7cb342;
}

#custom {
background: #4b830d;
height: 34%;
}
</style>
</head>
<body>
<div class="one-third" id="alexa">
<a href="/alexa">amazon alexa</a>
</div>
<div class="one-third" id="dueros">
<a href="/dueros">baidu dueros</a>
</div>
<div class="one-third" id="custom">
<a href="#">custom (todo)</a>
</div>
</body>
</html>

0 comments on commit f6f322d

Please sign in to comment.