Get location from Alexa Skills Kit (ASK) - alexa-skills-kit

I'm looking for a way to get the user's location, ideally longitude/latitude but address would work too, from the Alexa Skill Kit request to my custom skill. Also, I don't want to have to have the user link to an account on my app's side.
Is this possible? If so, how?

Amazon has now (2017-04-05) added this capability. See their blog post about their new Device Address API.
Using this new API you can get the address (either postal code or full address) of the device, as specified in the customer’s device settings.
From that you could use a geocoding API (such as is part of the Google Maps API) to translate the address into location coordinates.

As per this thread on the Amazon Developer forums, there is not currently (as of May 2016) a way to get user location via the publicly available APIs. The only skills able to do so, such as Uber or Domino's, are utilizing APIs that are not available through the Alexa Skills Kit. However, there's hope that it may be added, as "Jamie#Amazon" left this reply in that discussion:
Hey there,
Thanks for posting.
This has now been added to the roadmap. Thanks for the feedback.
Jamie
However, at the time of writing, no further update has been provided regarding the implementation of such a feature.

As #Tom has pointed out, it is now possible to get the device address in your custom skill. If you are using Python to create your skill, it's pretty easy to implement the new API. I've written a detailed blog post about it here. It also describes how to get the corresponding coordinates for the retrieved address, so it might be useful for you. In short, here is a Python function to get you started. I use the very handy Flask-Ask library for my skill. Thus, it is easy to get the value of the deviceId and consentToken objects. These are included by Alexa in the JSON request sent to your skill. They are needed for constructing the request to the Amazon address API endpoint:
import requests
from flask_ask import Ask, context
def get_alexa_location():
URL = "https://api.amazonalexa.com/v1/devices/{}/settings" \
"/address".format(context.System.device.deviceId)
TOKEN = context.System.user.permissions.consentToken
HEADER = {'Accept': 'application/json',
'Authorization': 'Bearer {}'.format(TOKEN)}
r = requests.get(URL, headers=HEADER)
if r.status_code == 200:
return(r.json())
The function will return something like this on a successful call:
{u'city': u'Berlin', u'countryCode': u'DE',
u'addressLine1': u'42 Unter den Linden',
u'addressLine2': None, u'stateOrRegion': u'Berlin',
u'districtOrCounty': u'Berlin', u'postalCode': u'10117',
u'addressLine3': None}
You can use geopy to convert this address to coordinates.

It is now possible to get the user's real-time geolocation (longitude/latitude) using the Alexa Location Services, which avoids having to integrate with a separate geocoding API as suggested by other answers. See the related blogpost for official information about this feature's release.
Provided that the device is compatible (context.System.device.supportedInterfaces.Geolocation exists), the location services are running and the alexa::devices:all:geolocation:read permission has been granted to your skill , you can retrieve a Geolocation object through the request's context, which will be equivalent to the following JSON payload:
"Geolocation":{
"locationServices": {
"access": "ENABLED",
"status": "RUNNING",
},
"timestamp": "2018-03-25T00:00:00Z+00:00",
"coordinate": {
"latitudeInDegrees": 38.2,
"longitudeInDegrees": 28.3,
"accuracyInMeters": 12.1
},
"altitude": {
"altitudeInMeters": 120.1,
"accuracyInMeters": 30.1
},
"heading": {
"directionInDegrees": 180.0,
"accuracyInDegrees": 5.0
},
"speed": {
"speedInMetersPerSecond": 10.0,
"accuracyInMetresPerSecond": 1.1
}
}

Please follow the below URL to Get location from Alexa Skills Kit (ASK)
URL:
https://api.eu.amazonalexa.com/v1/devices/{devicesId}/settings/address/countryAndPostalCode
Your Header would be something like below :
Host:api.eu.amazonalexa.com[keep your host you can get is from developer account during testing from json]
Accept:application/json
Authorization:Bearer [KEEP YOUR apiAccessToken here]
if request went success your will get response as below:
{
"countryCode": "IN",
"postalCode": "560102"
}
Make sure you have enabled permission in the Alexa app, and grants the permission of the respective skill please refer the bellow URL for more details of permission configuration
https://developer.amazon.com/blogs/alexa/post/0c975fc7-17dd-4f5c-8343-a37024b66c99/alexa-skill-recipe-using-the-device-address-api-to-request-information

Related

Microsoft Graph API - sendMail API error - "The requested user 'foobar#private.com' is invalid."

I am trying to understand how to send mail using Microsoft Graph sendMail API after creating an Azure AD app with 'Application permissions' for Microsoft Graph 'Mail.Send' and 'User.Read'. I am successfully using the client_id, tenant_id and client_secret to obtain an apparently valid token and subsequently submitting a POST to the api like this (R code):
from_address <- "foobar#private.com"
url <- paste0("https://graph.microsoft.com/v1.0/users/", from_address, "/sendMail")
resp <- POST(url,
add_headers(.headers = c(content_type = "application/json",
Authorization = paste("Bearer", token))),
body = upload_file("mail.json"))
The content of "mail.json" is:
{
"message": {
"subject": "Meet for lunch?",
"body": {
"contentType": "Text",
"content": "The new cafeteria is open."
},
"toRecipients": [
{
"emailAddress": {
"address": "someone#somewhere.com"
}
}
]
}
}
However, I get this 404 response:
"{\"error\":{\"code\":\"ErrorInvalidUser\",\"message\":\"The requested user 'foobar#private.com' is invalid.\"}}"
The Microsoft account I am using is private and the address represented above with foobar#private.com is the main 'signin' mail address for the account. I'm not sure if this user needs some special permissions or if it has to be a "corporate account". The plan is to use this within a corporate Microsoft account to send mails but I am currently testing with a private account to determine how it works.
The syntax for the call is
POST /users/{id | userPrincipalName}/sendMail
The tricky part is, as far as I can tell, personal Microsoft accounts don't have a userPrincipalName. Your "foobar#private.com" is an email address, but it isn't used as an identifier within Azure Active Directory or Graph.
Instead, you have to use your ID. You can get this with
GET /me
and the ID is the id field in the response.
Note that you may run into a separate problem with using an email address in the call, when it comes to work & school accounts. Commonly, people will have an address like "firstname.lastname#company.com", but this is only an alias for convenience; their userPrincipalName might be something more cryptic like "id123456#companytenantname.com". For this reason, it's best to stick to IDs throughout.
The description of how to POST to the Microsoft Graph SendMail api are correct in the question. The problem was only in the configuration of the application in Microsoft Azure portal Active directory. The administrator of the tenant created an app with two permissions with 'Admin consent'. The first is a Delegated permission, Microsoft Graph: 'Sign in and read user profile' the second is an Application permission, Microsoft Graph: 'Send mail as any user'. The first is used to get a token that is valid for 1 hour and the second is used in the code you see in the question to send the mail itself with the aquired token. I have been told that there is a restriction in place that only makes it possible to send mail from one specific 'no-reply' address at the organization so you can't use the api to impersonate someone else. It is not clear to me how that restriction works just that is does.

Telegram `setTyping` API call

I'm trying to set my bot's typing status by sending the following POST request (based on the API docs):
https://api.telegram.org/bot{{botToken}}/setTyping
{
peer: {{chat_id}},
typing: true,
action: 'sendMessageTypingAction'
}
I've tried a few variations of it, such as changing the url to be /messages.setTyping and sending the action as {"_":"sendMessageTypingAction"} as seen here, but all I get is:
{
"ok": false,
"error_code": 404,
"description": "Not Found: method not found"
}
Anyone know what I'm doing wrong?
Thanks to #tashakori for pointing me in the right direction towards the Bot API. For posterity, what I needed to do was:
https://api.telegram.org/bot{{botToken}}/sendChatAction
{
chat_id: {{chatId}},
action: 'typing'
}
The link you have mentioned above belongs to Telegram Core APIs which is used for handling ordinary accounts of Telegram. These so-called Core APIs are not related to Telegram Bot APIs.
The only API that is somehow similar to SetTyping for bots is AnswerCallbackQuery, which can be used only when responding to the user's interaction with inline keyboards. (you can send a text to the user, saying that there is a process running in the background and whenever the user's answer is ready, you can send it using APIs like sendMessage)

google cloud vision api quickstart error opening file

I am following the following Google Cloud Vision quickstart:
https://cloud.google.com/vision/docs/quickstart
This is using the API Explorer, and I get
Error Opening File
I have created a bucket named vision2018, and checked Share Publicly for the file.
My portion of the request related to the file is:
"image":
{
"source":
{
"imageUri":"gs://vision2018/demo-image.jpg"
}
}
The response I get is:
{
"responses": [
{
"error": {
"code": 5,
"message": "Error opening file: gs://vision2018/demo-image.jpg\"."
}
}
]
}
}
What do I need to specify in order to access files in my GCP storage?
Alternatively, I read other Stack Overflows that talk about GOOGLE_APPLICATION_CREDENTIALS, Simple API Key, and "Create Service account key and download the key in JSON format", ... but these seem to be giving commands in the shell, which this quickstart doesn't even open.
Is there initial setup assumed prior to the quickstart?
I am not ready to call the api from code
You might want to doublecheck your request. I went to the quickstart, replaced the placeholder imageUri with gs://vision2018/demo-image.jpg and it worked just fine. The error message you posted is what would be displayed if you had given gs://vision2018/demo-image.jpg\" instead.
Regarding the second part of your question: these are authentication methods. In this particular case, under Authentication you will find a drop down which lets you chose between API key and Google OAuth 2.0. If you chose the former, you don't need to do anything as a demo key will be used just for the purposes of the quickstart. If you chose OAuth 2.0, a popup will appear prompting you to authenticate with a google account. All in all, what you need to do is follow step-by-step the instructions given by the quickstart.
I was receiving a similar JSON response from the Google Vision API:
"error": {
"code": 7,
"message": "Error opening file: gs://bucket/file.jpg."
}
The fix was to set the GCS file's permission to public-read:
gsutil acl set public-read gs://bucket/file.jpg
Finally I investigated what happened. The problem is that your API token is only grant for process the image (allow right to use OCR engine), but that API is not also for accessing object in GS.
Therefore "message": "Error opening file:
The problem is similar with this post:Authorize Google Cloud Vision API to Google Storage image Maybe the error message is a bit dumb than many years ago.
The solution also mentioned in the answer section, but if you want some thing more clear (expose security side-effect) here it is: Set GCS read-only public
Reason I want to keep using API because it's better for use it in mobile application, we cannot give the OAuth2.0 to any phone. However, still find a way to secure the read-public bucket.

Accessing YouTube API in Meteor project for logged in user

I'm working on a new Meteor project which involves users logging into the site using their Google accounts through OAuth (I'm using the Meteor accounts-google package for this) and when signing in I need them to be able to see some data from the YouTube Analytics API for their YouTube channel. As of now the data I am trying to get is their total daily views, which I then hope to display on a chart for a specified time period.
I have added the following scopes to my accounts-google login system:
Meteor.loginWithGoogle({
requestPermissions: ['https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile', 'https://www.googleapis.com/auth/yt-analytics.readonly', 'https://www.googleapis.com/auth/youtube.readonly'],
requestOfflineToken: true,
forceApprovalPrompt: true,
loginStyle: "popup"
});
This all seems to be working very well, once a user signs into the site and grants the site access to these I can then see the necessary info in my MongoDB database. Under user.services.google I can now see it has accessToken, idToken, expiresAt, refreshToken, etc.
I've also decided to use the google api nodejs client by implementing it through the meteorhacks:npm package for Meteor. I am using this to refresh tokens (as seen in this SO answer I found helpful).
Using the "Try It" API Explorer on the YouTube Analytics API Documentation page, I can get the type of data I'm looking for through this request:
GET https://www.googleapis.com/youtube/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2015-10-01&end-date=2015-10-31&metrics=views&dimensions=day&sort=-day&key={YOUR_API_KEY}
Now is where I've been completely stuck and really unsure of where to go from here. How can I implement this into my site? I've tried for quite some time now to make this work but everything I attempt isn't working, and there's no real direction. If anyone is willing to help out I'd greatly appreciate it. I'm fairly new to Meteor/JS/APIs so any information/examples is extremely appreciated, especially noob friendly stuff! ;)
One way to do it is to use a method and the http package: https://atmospherejs.com/meteor/http
Looking at the doc you provide, you may try something like this:
Define your method on the server side
// server-side
Meteor.methods({
getYoutubeReports: function(channelId, accessToken, params) {
params.ids = "channel=="+ channelId;
params.key = accessToken;
return HTTP.get("https://www.googleapis.com/youtube/analytics/v1/reports", {
params: params
});
}
});
You can then call it on the client side with the data you get from your the authentication (ie. CHANNEL_ID_OF_MY_USER & ACCESS_TOKEN_OF_MY_USER)
// client-side
var reports,
myParams = {
"start-date": "2015-10-01",
"end-date": "2015-10-31",
"metrics": "views",
"dimensions": "day",
"sort": "-day"
};
Meteor.call('getYoutubeReports', CHANNEL_ID_OF_MY_USER, ACCESS_TOKEN_OF_MY_USER, params, function(error, result) {
// store or do stuff with the result of the HTTP request here
console.log(result);
});
Feel free to custom myParams as your user need!
And if you want to some more tips about how to use HTTP request (really useful to call external API), The Meteor Chef wrote a really good article about it : https://themeteorchef.com/snippets/using-the-http-package/
I hope it helps!
I ended up using the percolate:google-api package to handle my API call.

What is the URL to make a Google Voice call using the direct access number?

I am trying to write a Google Voice app and was wondering if anyone knew the url and post parameters to make a call using the direct access number instead of the ring-back.
For example, to call 1-800-555-0111, enter
https://voice.google.com/u/0/calls?a=nc,%2B18005550111
I did not test it, but check this api: http://code.google.com/p/google-voice-java/
Specially, the voice.java at line 711, which is the method:
public String call(String originNumber, String destinationNumber,
String phoneType) throws IOException {
In line 737 they use:
URL callURL = new URL("https://www.google.com/voice/call/connect/");
and the full comments for the methods say:
// POST /voice/call/connect/
// outgoingNumber=[number to call]
// &forwardingNumber=[forwarding number]
// &subscriberNumber=undefined
// &phoneType=[phone type from google]
// &remember=0
// &_rnr_se=[pull from page]
I hope this helps.
I don't think there is an official API, but this site seems to have made some progress with the URLs you are after: http://posttopic.com/topic/google-voice-add-on-development , and there is an unofficial API here: http://sourceforge.net/projects/gvoicedotnet/
Google Voice does not expose an API to the service however, there are many 3rd party libraries that mock an API by screen scraping via Google Voice's HTML website. I better solution though is to use the google voice service via SIP. Search for "google voice sip asterisk" and you will find out about this. Basically if you install this software called asterisk it can make calls via google voice.
See this article for a start:
http://eggie5.com/10-installing-asterisk-on-osx

Resources