Skip to content
This repository was archived by the owner on Sep 1, 2025. It is now read-only.

Conversation

m0ngr31
Copy link
Owner

@m0ngr31 m0ngr31 commented Dec 30, 2016

This is a big update and the precursor to v2.5!

I have moved to flask-ask to help make the skill as clean as possible. This move allows the skill easier compatibility, and I believe it will make translation work very trivial since everything is in a template file now. Using something like babel should allow easy translation going forward (German first. We'll see what other languages Amazon will expand to soon).

I have moved the necessary code from wsgi.py to alexa.py and the main application method is now just app. So there will be some changes needed to upgrade current versions.

This is not ready for a merge into master yet due to documentation needing to be updated. However it is ready for testing.

Please let me know if you have any questions.

@m0ngr31 m0ngr31 requested a review from jingai December 30, 2016 07:14
@digiltd
Copy link
Contributor

digiltd commented Dec 31, 2016

You have been busy :)

Could this also be a good time refactor the code into smaller modules?

The language issue is definitely something that we need to make sure is able to be addressed and if possible get it working for the initial release.

I will have a test and make some suggestions (I had a look at a flask-ask conversion a little while ago also).

How does the new .env file work in regards to timezones?

@m0ngr31
Copy link
Owner Author

m0ngr31 commented Dec 31, 2016

How does the new .env file work in regards to timezones?

Timezones shouldn't be needed anymore since we're not verifiying the timestamp. According to this https://alexatutorial.com/flask-ask/configuration.html we shouldn't be at least. I guess if you want to enable it, it'd still figure it out without the timezone data.

Could this also be a good time refactor the code into smaller modules?

I actually don't mind how it is now that the WSGI and Lambda still is ripped out of alexa.py. It's just intents in there now which is how it should be.

The language issue is definitely something that we need to make sure is able to be addressed and if possible get it working for the initial release.

Yeah, it's been something I keep getting emails about and I'm excited to get some good stuff going for our German speaking friends.

@jingai
Copy link
Collaborator

jingai commented Dec 31, 2016

Time zone is used to determine the local end time of the currently playing item.

@m0ngr31
Copy link
Owner Author

m0ngr31 commented Dec 31, 2016

Okay, that's my bad. We can add that back in no problem then.

@jingai
Copy link
Collaborator

jingai commented Dec 31, 2016

Trying to check this out, but.. how do you call a Flask-Ask app from mod_wsgi?

The Flask documentation says to just import it as application:

from alexa import app as application

But that is giving me nothing at all. I tried importing the Ask object, but it says that object is not callable.

@jingai
Copy link
Collaborator

jingai commented Jan 1, 2017

Digging a bit further, it seems it's kind of working.. but I'm getting this odd routing exception:

FormDataRoutingRedirect: A request was sent to this URL (https://mydomain/kodi-alexa/) but a redirect was issued automatically by the routing system to "https://mydomain/kodi-alexa/". Make sure to directly send your POST-request to this URL since we can't make browsers or HTTP clients redirect with form data reliably or without user interaction.

I don't really understand Flask well enough yet to know why, though.

@jingai
Copy link
Collaborator

jingai commented Jan 1, 2017

Ok, that pisses me off and leaves a bad taste in my mouth, frankly.. apparently, it needed the final slash in the URL.... several hours later and it's something stupid, of course.. but still, their 'routing system' is clearly not very smart..

@jingai
Copy link
Collaborator

jingai commented Jan 1, 2017

Went through every Intent systematically and things are mostly working. Only encountered a failure on the WhatNewAlbums intent:

[Sat Dec 31 20:34:02.575985 2016] [wsgi:error] [pid 15066] [client 72.21.217.78:29336] UnicodeEncodeError: 'ascii' codec can't encode character u'\\xef' in position 33: ordinal not in range(128)

Haven't looked into it really, but it seems we might need to sanitize the responses some.

@m0ngr31
Copy link
Owner Author

m0ngr31 commented Jan 2, 2017

Ok, that pisses me off and leaves a bad taste in my mouth, frankly.. apparently, it needed the final slash in the URL.... several hours later and it's something stupid, of course.. but still, their 'routing system' is clearly not very smart..

Sorry to hear that. I'm hoping the switch will ultimately be worth the initial hassle though. The lambda process is a bit different too.

Went through every Intent systematically and things are mostly working.

Thanks for doing that. I haven't made it through every single one myself.

Haven't looked into it really, but it seems we might need to sanitize the responses some.

That doesn't surprise me that much. This is as good of a time to do it as ever.

@jingai
Copy link
Collaborator

jingai commented Jan 2, 2017

Yeah, it's a positive change. The Flask documentation's just not the greatest to be honest and am a bit worried about debugging issues when they arise for others.

Mostly it'd be nice if it provided output for at least errors by default without having to enable debug mode. I might have missed that in the documentation, though.

As for the responses, it seems something just got converted to ASCII along the way that should have remained unicode. If you don't spot it within the week, I'll have a look. Have to go back to the real job tomorrow though and am likely to be kept busy there for a little while.

@m0ngr31
Copy link
Owner Author

m0ngr31 commented Jan 3, 2017

As for the responses, it seems something just got converted to ASCII along the way that should have remained unicode.

I think I fixed this in my last commit.

@jingai
Copy link
Collaborator

jingai commented Jan 3, 2017

As for the responses, it seems something just got converted to ASCII along the way that should have remained unicode.

I think I fixed this in my last commit.

On my list of things to check when I get off work.

@jingai
Copy link
Collaborator

jingai commented Jan 3, 2017

I think we may have hit a limit with regard to how big the Intent model can be. I can't be sure, of course, but I think every time you reference a slot in the Intent model, it creates a copy of it and there's some overall limit that (at least to my knowledge) Amazon hasn't exposed. Probably because they thought no one would hit it :)

If I try to save the current Intent model, it appears to succeed, though it takes a really long time to do so. However, when using the simulator, I get:

Error: No intent model has been built for this skill

If I remove my songs from the MUSICSONGS slot (simply because it's the largest list, sitting at 26000 entries), everything works again.

Not really sure what to do about this, since users' libraries are lopsided in different ways; i.e., mine has many more songs, but others might have a crazy number of shows, or movies, etc.

@jingai
Copy link
Collaborator

jingai commented Jan 3, 2017

The WhatNewAlbums Intent still produces the same encoding error as before. I suspect any other Intent with non-ASCII characters in the response will too.

Sending request to http://localhost:8080/jsonrpc
[2017-01-03 18:02:53,799] ERROR in app: Exception on / [POST]
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1517, in handle_user_exception  
    reraise(exc_type, exc_value, tb)
  File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/lib/python2.7/dist-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/local/lib/python2.7/dist-packages/flask_ask/core.py", line 516, in _flask_view_func
    result = self._map_intent_to_view_func(self.request.intent)()
  File "/var/www/ha/echo/kodi-alexa/alexa.py", line 1746, in alexa_what_new_albums
    return statement(response_text).simple_card(card_title, response_text)
  File "/usr/local/lib/python2.7/dist-packages/flask_ask/models.py", line 106, in __init__   
    super(statement, self).__init__(speech)
  File "/usr/local/lib/python2.7/dist-packages/flask_ask/models.py", line 53, in __init__
    'outputSpeech': _output_speech(speech)
  File "/usr/local/lib/python2.7/dist-packages/flask_ask/models.py", line 244, in _output_speech
    xmldoc = ElementTree.fromstring(speech)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1311, in XML
    parser.feed(text)
  File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 1651, in feed
    self._parser.Parse(data, 0)
UnicodeEncodeError: 'ascii' codec can't encode character u'\\xed' in position 51: ordinal not in range(128)```

@m0ngr31
Copy link
Owner Author

m0ngr31 commented Jan 3, 2017

Not really sure what to do about this, since users' libraries are lopsided in different ways; i.e., mine has many more songs, but others might have a crazy number of shows, or movies, etc.

Might just need to limit the Slot Generator to 10k or something and see if that works. It's not ideal, but it'll give us a decent idea about how many they allow.

The WhatNewAlbums Intent still produces the same encoding error as before. I suspect any other Intent with non-ASCII characters in the response will too.

Try it again after the commit I just made. I think it's a special case on this intent.

@m0ngr31
Copy link
Owner Author

m0ngr31 commented Jan 3, 2017

Okay, I added German translations for card and voice responses (just used Google Translate, so I'm sure it's awful), but it's working and automatically translates if it's configured as a German skill.

Also, last night I pushed up some new intents that handle streaming party mode and all music by an artist to your Echo/Dot/Tap. This requires a bit of setup. You have to configure a mongoDB server and add information about it to the .env file as well as accept a warning I put in there about passwords being sent over the wire in plaintext.

One of the biggest hassles with steaming music is that Amazon won't allow non HTTPS urls, and if it has an SSL cert, it can't be self-signed. For a lot of people this is too complex, so I wrote a little HTTPS proxy that'll work (again, if they accept the warning message). It's configured so that you can run your own proxy (mine is just here on Github), or you can just have a Let's Encrypt cert on your local machine if you are running an reverse-proxy for Kodi already.

@jingai
Copy link
Collaborator

jingai commented Jan 3, 2017

Not really sure what to do about this, since users' libraries are lopsided in different ways; i.e., mine has many more songs, but others might have a crazy number of shows, or movies, etc.

Might just need to limit the Slot Generator to 10k or something and see if that works. It's not ideal, but it'll give us a decent idea about how many they allow.

The problem is that I don't believe it's a limit on any given slot, or even the total of all slots. I think it's the cumulative number of entries in the slot references by the Intent model. That is, I think simply referencing slots increases some counter (or maybe it's just an overflow, who knows) that has a ceiling on it that Amazon has not disclosed.

I think this because I tested it pretty thoroughly a little while ago while I was writing the generic search/play code. The 50k items in slots limit is published by Amazon, but I don't have 50k items in my slots in total. However, adding a new Intent that referenced existing slots caused it to fail, just as what you added makes it fail in the same manor on my installation.

Basically, I think the Intent model has some undisclosed maximum size, and Amazon isn't referencing the slots, but instead copying them into the model each time they're referenced.

@jingai
Copy link
Collaborator

jingai commented Jan 3, 2017

The WhatNewAlbums Intent still produces the same encoding error as before. I suspect any other Intent with non-ASCII characters in the response will too.

Try it again after the commit I just made. I think it's a special case on this intent.

It is indeed fixed, though it adds 'and' in between every item:

You have Storm by Vanessa Mae, and Ölürüm Sana by Tarkan, and She Was a Boy by Yael Naïm, and Peace And Love, Inc. by Information Society, and Love In The Time Of Science by Emilíana Torrini, and more

@m0ngr31
Copy link
Owner Author

m0ngr31 commented Jan 3, 2017

I saw that. It's just a logic issue. Should be a pretty easy fix.

@m0ngr31
Copy link
Owner Author

m0ngr31 commented Jan 3, 2017

Give it a shot now.

@jingai
Copy link
Collaborator

jingai commented Jan 3, 2017

Yup, that's good now.

@jingai
Copy link
Collaborator

jingai commented Jan 3, 2017

Also, last night I pushed up some new intents that handle streaming party mode and all music by an artist to your Echo/Dot/Tap.

It'd be good to factor out the generic code for this so we don't duplicate all of the existing music playback methods. But it'd probably be better to close out the Flask-Ask changes before doing so, because I've already got code ready for more generic playback that refactors some of it.

I was holding off on releasing the generic search/play code because of the Intent model size issue though. I think before we can merge this branch we need to figure out how to properly solve that.

KODI_PASSWORD=

SKILL_APPID=
SKILL_VERIFY_CERT=
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that Flask-Ask enables cert verification by default, but do we want to provide a way to disable it?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't provide a SKILL_APPID, I don't turn on verification.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are two separate things though. SKILL_APPID is to verify that the application ID matches what we expect, whereas SKILL_VERIFY_CERT is for verifying the certificate.

I personally want them both enabled at all times, but others might just want one or the other.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also don't see where you explicitly enable cert verification? From the documentation (and I've verified it in execution too), Flask-Ask enables it by default.

Wasn't sure if we wanted a way to disable it, though. Personally I'd never turn it off, so it's no big deal to me if you'd rather just let Flask-Ask handle it.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well you know more than I do about the verification stuff. I haven't done anything with it. I would have to assume though that flask-ask takes care of the cert verification. Although I wasn't aware of it until you mentioned it.

I'm manually adding the APPID verification if the env variable exists though.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh.. but Amazon still verifies the cert before executing the Lambda function, right?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, Amazon isn't doing anything with it now. Everything is routed through API Gateway and it's treated the same as if it wasn't a real lambda as far as I can tell.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh ok. So we probably want the cert verification enabled in Flask-Ask at all times anyway.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't think of any reason not to have it enabled now.


SKILL_APPID=
SKILL_VERIFY_CERT=
# SKILL_APPID=
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just so I understand, was there a reason for commenting this out rather than just leaving it empty in the example?

NewShowInquiry if we have {Show}
OpenRemote open controller
OpenRemote open controls
OpenRemote open remote
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bear in mind that I had used "open" as the command to execute addons, so this means any addon with the name of controller, controls, and remote won't open via voice command.

edit: it appears "open menu" would have the same issue.

music.py Outdated
import os
import collections

from pymongo import MongoClient
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll probably have some users complain that pymongo isn't an optional dependency, just FYI.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'll work this into the if check to see if they've agreed to the warnings.

@jingai
Copy link
Collaborator

jingai commented Jan 4, 2017

Okay, I added German translations for card and voice responses (just used Google Translate, so I'm sure it's awful), but it's working and automatically translates if it's configured as a German skill.

@ausweider provided some initial effort for German here: danielmasur@03e1313

Could have a look at how he/she chose to translate the strings since he/she is a native speaker. It's a bit outdated, but could provide some direction.

@digiltd
Copy link
Contributor

digiltd commented Jan 5, 2017

Re Slots and dealing with 20k of them.

The ASK documentation is vague, I might have the wrong end of the stick completely, I would be interested to discuss...

From what I have read it is my understanding that the purpose of a slot is to help identify and extract particular parts from the entire sentence. A number as a number, a name as a name, a song as a song etc. And to help identify what you are looking for you provide examples for what each slot might contain. Alexa uses the examples to "intelligently" match similar patterns.

It is then up to the Skill to deal with the contents of the heard slot. All Alexa does is identify the song was a song and not a town name.

Forgetting all the different complicated ways Alexa analyses the data she is trying to pattern match, instead lets assume that she is only looking at word count.

A simple example is you have a slot of 10 song titles that were all exactly five words long, and a slot of 10 artists that were all exactly two words long. When you tell the Skill to "play radio gaga", chances are it will identify "radio gaga" as an artist and send the "search artists" request to Kodi and end up playing Lady Gaga.

If you swapped one of the five word song titles with a two word title (so 1x two-word and 9x five-word), then it would (I assume) still identify "radio gaga" as an artist. Alexa could see that there is a small percentage of two word songs but based on what she knows (100% of artists contain two words, 90% of song titles five words and only 10% of song titles are two words) she would have to treat it as an artist.

This is not the best example as the problem (as I am sure you know) with songs, artists and films as they are all super varied and you could easily swap a list of songs with a list of films and not spot the differences.

@jingai have you tried (can you try?) using a curated slot list of 200 songs/artists/albums that covered a broad spectrum of each and then tested it with examples that were not in the slot lists?

@jingai
Copy link
Collaborator

jingai commented Jan 5, 2017

The problem is I wouldn't really know how to curate it without fully understanding how Amazon uses them. Their descriptions of how it matches things to slots is vague at best.

I was thinking of modifying the slot generator to choose N (200, 1000, 5000, whatever works; bigger is better in my experience, so it'd be matter of choosing N where the skill doesn't break) random items for each slot. But I need to set aside a decent chunk of time to test it.

If string length is also a factor, we could distribute the random choices so we get a roughly equal distribution of samples at varying lengths too.

@jingai
Copy link
Collaborator

jingai commented Jan 5, 2017

The other thing to think about is if a user doesn't have enough of a given media type in their library for the Slot to turn "generic".

Might need the Slot generator to spit out some canned entries in that case.

@digiltd
Copy link
Contributor

digiltd commented Jan 5, 2017

Hopefully the new built-in intents will help when they arrive.

When the UK didn't have IFTTT integration with our Echos, we used a workaround where we could send any phrase to the Maker Channel (webhooks) on IFTTT. I used to use a list of phrases for the sample utterances which would allow me to pass any phrase to the channel.

hello
hi there
it's cold here
my name is Alexa
the weather outside is frightful
the meaning of life is forty-two
what is the weather in Miami Beach
you get nothing you lose good day sir
the quick brown fox jumps over the lazy dog
we are the music makers we are the dreamers of dreams

@jingai
Copy link
Collaborator

jingai commented Jan 5, 2017

Yes, but we need to do something in the meantime so those with large libraries aren't faced with an odd failure case like this (Amazon telling the user the Intent model was built just fine, then failing at runtime).

Simply choosing, say, 2500 random items from the library for each slot would probably work for now. Just need to test it.

@jingai
Copy link
Collaborator

jingai commented Apr 13, 2017

Rebased onto current master in preparation for merge. If you have a local copy of this branch, you'll need to delete and re-pull.

@jingai
Copy link
Collaborator

jingai commented Apr 13, 2017

All that's left is testing now -- touched a lot recently by stripping out streaming music.

@danielmasur
Copy link
Contributor

Unfortunately I won't be available till after April 24th. @sveni-lee

@jingai jingai merged commit a4b15a7 into master Apr 14, 2017
@jingai jingai deleted the flask-ask branch April 14, 2017 15:18
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants