I'm working with the js/node api of getstream and I'm trying to add a realtime feature to the comments on the activities, but I'm receiving a 403 error, displaying I dont have permission.
I've tried using targetFeeds: '[timeline:userid]' but it wrecks the application.
Also I tried to use the notification feed as in the documents is being used, and I can set targetFeeds like this: '[notification:userid]' which obviously is not the desired thing to do because this will cause that every message on different activities of this user will be shown on the callback.
client.reactions.add("comment", activityId, {
"text": newComment,
"profileImage": 'https://i.pravatar.cc/300',
"timestamp": date,
"from": userId,
"id": foreignId,
},
{targetFeeds: [`CommentsFeed:${activityId}`]});
And the response of the 403 is the next one:
{
code: 17
detail: "You don't have permission to do this"
duration: "0.18ms"
exception: "NotAllowedException"
status_code: 403
}
The expected result is not having the 403, that will trigger the callback I implemented.
The default permission settings allow users to only write activities to their own feeds; in this case you are adding an activity to CommentsFeed:${activityId}.
You can request support (support#getstream.io) to whitelist this for you app(s). Just make sure to mention this case and include your applications.
Related
Overview
I am using the Node.js library actions-on-google client to build a smarthome action for the Garage Door device type. This action is deployed as a Cloud Function in GCP. I can confirm that the following works perfectly so far:
Accounting linking with our OAuth flow
Responding to sync intents (ie. onSync() in the client)
Responding to execute intents (ie. onExecute() in the client)
Problem
Despite that other callbacks (onSync() and onExecute()) work fine, we do not see any evidence of onQuery() being called no matter what. There aren't any errors showing in Stackdriver nor are their any logs being generated in Stackdriver under the "Google Actions" filter either.
We expect onQuery() to run when we ask Google Assistant things like is the garage door open? and is Matt's Door closed?
We tried removing async to see if the call was hanging
We tried removing headers in the lambda
We tried removing all other code and redploying to isolate onQuery()
Code
The following code shows the simple onQuery() callback. onExecute() and onSync code has been removed for clarity.
'use strict';
const functions = require('firebase-functions');
const {smarthome} = require('actions-on-google');
const app = smarthome({
jwt: require('./XXXXXXXXX-XXXXXXXXXX.json'),
debug: true,
});
//
// Note: Removed onSync() and onExecute() for clarity
//
app.onQuery(async (body, headers) => {
// Expecting to see these logging statements in
// Stackdriver like we do for onExecute() and
// onSync() ... but nothing ever shows up.
console.info('=== onQuery.body', body);
console.info('=== onQuery.headers', headers);
// We have hardcoded the following ID and a "closed"
// state. It matches a valid device ID to the testing
// account we are using.
return {
requestId: body.requestId,
payload: {
devices: {
'2489e4a92799728292b8d5a8b1c9d177': {
on: true,
online: true,
openPercent: 0,
}
}
}
};
});
exports.smarthome = functions.https.onRequest(app);
We considered the possibility that the JSON returned in the call to onSync() might be missing a trait or something that prevents it from responding to a query intent properly but we have not been able to identify anything that might be incorrect or missing. Here is the JSON payload returned from onSync():
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"payload": {
"agentUserId": "1836.15267389",
"devices": [{
"id": "1234",
"type": "action.devices.types.GARAGE",
"traits": [
"action.devices.traits.OpenClose"
],
"name": {
"defaultNames": ["Smart Garage Door"],
"name": "Matt's Door",
"nicknames": ["Matt's Door"]
},
"willReportState": true,
"attributes": {
"openDirection": [
"UP",
"DOWN"
]
},
"deviceInfo": {
"manufacturer": "ABC Corp",
"model": "test",
"hwVersion": "1.0",
"swVersion": "1.0"
}
}]
}
}
Expected Result
We expect Google Assistant to respond with "Garage door is closed" or some other equivalent. Instead, we receive "Sorry, I can't reach Matt's Door right now. Please try again."
Answering my own question here in case anyone else has this trouble. The reason why my action was handling the SYNC and EXECUTE intents but not the QUERY intent came down to what default/user names I assigned each device in the SYNC response.
Ultimately, I started using the following and my action began responding to QUERY intents as expected again:
...
name: {
defaultNames: ['Garage Door'],
name: door.name,
nicknames: [door.name, 'Garage Door']
},
...
where door.name is a name which is set by the user and is returned by an API call.
I'm using the Google Calendar API and am trying to receive push notifications when a calendar event is triggered https://developers.google.com/calendar/v3/push
I think everything is setup correctly...
gapi.client.calendar.events.watch({
calendarId: 'primary',
resource: {
id: uuid,
type: 'web_hook',
address: window.location.href,
},
}, (err, response) => {
if (err) {
console.log('err:', err);
} else {
console.log('response:', response);
}
}).then((res) => {
console.log('res:', res);
});
But I guess not. I get a 200 response when I call the above code
{
"kind": "api#channel",
"id": "...",
"resourceId": "...",
"resourceUri": "https://content.googleapis.com/calendar/v3/calendars/primary/events?alt=json&maxResults=250&alt=json",
"expiration": "1554203159000"
}
I believe I should also be receiving a sync message, but I am not (https://developers.google.com/calendar/v3/push#sync)
To test things I am modifying an event within the calendar itself (changing the title, date, deleting, etc), and I expect something to happen in my browser, but nothing.
I'm not familiar with Push notifications in general, so not exactly sure what to expect.
I'm already authenticated and displaying events as per https://developers.google.com/calendar/quickstart/js
What am I missing? Any help is really appreciated!
Thanks in advance!
I suspect you are miss understanding exactly what push notifications is.
There are two primary ways to track when a resource has changed. You can poll that resource often and check for any changes in the resource.
For example Your application could run every five minutes and make a request to Google asking to have the event returned to you. When that event is returned you will then check if there are any changes in the event created by the user. This method of checking for changes is very time consuming and requires resources to constantly poll the server looking for changes. A better way of doing it is using Push notifications
Push notifications notify your application when a change has been made.
This document describes how to use push notifications that inform your application when a resource changes.
Its set up by enabling a watch
POST https://www.googleapis.com/calendar/v3/calendars/my_calendar#gmail.com/events/watch
Authorization: Bearer auth_token_for_current_user
Content-Type: application/json
{
"id": "01234567-89ab-cdef-0123456789ab", // Your channel ID.
"type": "web_hook",
"address": "https:/examle.com/notifications", // Your receiving URL.
...
"token": "target=myApp-myCalendarChannelDest", // (Optional) Your channel token.
"expiration": 1426325213000 // (Optional) Your requested channel expiration time.
}
This tells Googles servers that you would like to be notified when ever someone makes a change to the event. This sets up a web hook to https:/examle.com/notifications which will be notified as soon as there is a change to the event.
Name of the event, date time are normally changes i dont think you will get a push notification if someone else is added to the event.
What this is not
The server is NOT going to send you a message 10 minutes before the event is due. Thats user notification and something completely different and not part of the Google Calendar api.
I have opened this as a bug with facebook here https://developers.facebook.com/bugs/105273653568982/
but thought I would ask here as well to see if anyone else has a solution:
The facebook open graph API says it is supposed to work for instagram as well as facebook, however when used from my server side code OR from the open graph explorer OR from postman, is only returning facebook media items, not instagram media items.
Eg a GET request for comments on my own facebook photo returns successfully:
Request:
https://developers.facebook.com/tools/explorer?method=GET&path=101205943227587%2Fcomments&version=v2.11&access_token=MYACCESSTOKEN
Result:
{
"data": [
{
"created_time": "2016-01-04T16:11:07+0000",
"message": "People might be abl",
"id": "101205943227587_1187008471313990"
}
],
"paging": {
"cursors": {
"before":"WTI5dGJXVnVkRjlqZAFhKemIzSTZANVEU0TnpBd09EUTNNVE14TXprNU1Eb3hORFV4T1RJek9EWTQZD","after":"WTI5dGJXVnVkRjlqZAFhKemIzSTZANVEU0TnpBd09EUTNNVE14TXprNU1Eb3hORFV4T1RJek9EWTQZD"
}
}
}
whereas endeavouring to get the same thing for an instagram post (again using my own media) doesn't work.
Request:
https://developers.facebook.com/tools/explorer?method=GET&path=1531969816055084767%2Fcomments&version=v2.11&access_token=MYACCESSTOKEN
Result:
{
"error": {
"message": "(#803) Some of the aliases you requested do not exist:
1531969816055084767",
"type": "OAuthException",
"code": 803,
"fbtrace_id": "D2xUM/kQWsJ"
}
}
None of the methods here
https://developers.facebook.com/docs/instagram-api/overview/
work for instagram media, eg attempting to get the info about Instagram's own account
GET graph.facebook.com
/25025320?fields=biography,id,username,website&access_token=MYACCESSTOKEN
returns an error
{
"error": {
"message": "Unsupported get request. Object with ID '25025320' does not exist, cannot be loaded due to missing permissions, or does not support this operation. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api",
"type": "GraphMethodException",
"code": 100,
"error_subcode": 33,
"fbtrace_id": "DCreoeyTARt"
}
}
My app has been approved to use the new api with the instagram_basic and instagram_manage_comments permissions, and I know the access token is valid as I am able to get facebook media and use the graph.facebook.com/me api so not sure why all instagram-related stuff is failing.
I am currently trying to send a PushNotification to a Device Group using FCM with the help of Firebase Cloud Functions but once the notification is sent, it returns with code 200 but with failure :
SUCCESS response= {
multicast_id: 8834986220110966000,
success: 0,
failure: 1,
canonical_ids: 0,
results: [ { error: 'InvalidRegistration' } ]
}
Here is the code I am using to send this notification... what am I missing?
const options = {
method: 'POST',
uri: 'https://fcm.googleapis.com/fcm/send',
headers: {
'Authorization': 'key=' + serverKey,
},
body: {
to: groupId,
data: {
subject: message
},
notification: {
title: title,
body: body,
badge: 1,
},
content_available: true
},
json: true
};
return rqstProm(options)
.then((parsedBody) => {
console.log('SUCCESS response=', parsedBody);
})
.catch((err) => {
console.log('FAILED err=', err);
});
Where JSON values title, body, subject, message are String
In my case, I was sending notifications to topic ("topics/my-topic"). I was missing prepending / in the starting of topic so I was getting the same issue. SO topic should be /topics/my-topic.
May be this helps!!
There is an easier way to send a message to a device group from a Cloud Function. Use admin.messaging().sendToDeviceGroup(). Sample code and instructions are in this guide.
I think your current method is failing because there is something wrong with the group notification key provided in groupId. It should be the string key value that was returned when you created the device group. The error codes are listed in this table. For 200/InvalidRegistration it says:
Check the format of the registration token you pass to the server.
Make sure it matches the registration token the client app receives
from registering with Firebase Notifications. Do not truncate or add
additional characters.
I was losing my mind with this InvalidRegistration error.
Eventually the problem was that I was subscribing my device to "example" but sending the notification json to: "example".
But we actually need to send to "/topics/example"
2 hours of my life wasted..
A registration token is tied to a certain group of senders. When a client app registers for FCM, it must specify which senders are allowed to send messages. You should use one of those sender IDs when sending messages to the client app.
Al you need to do is add a http header 'project_id' with your sender id.
I was getting InvalidRegistration:
Basic meaning: you are using the wrong token. Why? This may happen when you a new registrationToken is given to you in onNewToken (docs), but for some reason you are using the old token. That could happen when:
You're using a different push notification library which remembers token (stores it somewhere locally) and you didn't update that library with the new token.
Your application (or other library dependencies) implements another FirebaseMessagingService, and they conflict. Only one service can accept (react to) to the action sent by the FirebaseMessaging Android library's when a new token is given to it. You can double check this by opening the AndroidManifest.xml in Android Studio and selecting the Merged Manifest tab at the bottom of the tab. You can also place debuggers in each Service from each library you use. You'll see that only one service's onNewToken gets called.
When they conflict, one doesn't get the correct token, and the FCM registration token that gets registered would be wrong. Sending a message to a wrong registration, gets you InvalidRegistration.
for me, it was a mistake that I was passing an Id from my models instead of the tokens of the users
InvalidRegistration simply means that the token is either invalid or expired. You can uninstall the app and then reinstall and get a new token and then try with that token. This will definitely solve your problem.
You can read more here.
I need to get contacts emails with Google People API, but can't find a way to do it in docs. Currently I'm making the following request:
request.get('https://people.googleapis.com/v1/people/me/connections?access_token=tokenHere',
function (error, response, body) {
console.log(body);
});
And getting the following responce (I pin only the part of it, for example):
{
"resourceName": "people/c1705421824339784415",
"etag": "328OLZwdaiQ=",
"metadata": {
"sources": [
{
"type": "CONTACT",
"id": "17aae01d0ff8b2df",
"etag": "#328OLZwdaiQ="
}
],
"objectType": "PERSON"
},
"names": [
{
"metadata": {
"primary": true,
"source": {
"type": "CONTACT",
"id": "17aae01d0ff8b2df"
}
},
"displayName": "testGoogleContact",
"givenName": "testGoogleContact",
"displayNameLastFirst": "testGoogleContact"
}
]
}
To achieve this you need to use the Google Plus API: This is what I found on the Google Plus API Documentation page:
You can get an email address for the authenticated user by using the
email scope.
The following JavaScript code example demonstrates how to:
Use Google+ Sign-In to authenticate the user and get a valid OAuth 2.0
access token.
Use the token to make an HTTP GET request to the
https://www.googleapis.com/plus/v1/people/me
REST endpoint. Parse the response and display the user's email
address.
The JSON should like something like this:
{"kind":"plus#person","etag":"\"xw0en60W6-NurXn4VBU-CMjSPEw/mjjYoraGfq3Wi-8Nee4F3k7GYrs\"","emails":[{"value":"**EMAIL**","type":"account"}],"objectType":"person","id":"Person ID","displayName":"FULL NAME","name":{"familyName":"LAST NAME","givenName":"NAME"},"url":"https://plus.google.com/USER","image":{"url":"https://lh5.googleusercontent.com/-RTcRn6jTuoI/AAAAAAAAAAI/AAAAAAAAEpg/Y6cMxfwtbQ4/photo.jpg?sz=50","isDefault":false},"placesLived":[{"value":"CITY","primary":true}],"isPlusUser":true,"verified":false,"cover":{"layout":"banner","coverPhoto":{"url":"https://lh3.googleusercontent.com/SybH-BjYW2ft1rzayamGLg_VwW7ocgnQ5cAxH3ROEpODvyaEODpYKW55gmAxCXDUvfKggQ4=s630-fcrop64=1,00002778ffffffff","height":626,"width":940},"coverInfo":{"topImageOffset":0,"leftImageOffset":0}},"result":{"kind":"plus#person","etag":"\"xw0en60W6-NurXn4VBU-CMjSPEw/mjjYoraGfq3Wi-8Nee4F3k7GYrs\"","emails":[{"value":"**EMAIL HERE**","type":"account"}],"objectType":"person","id":"116508277095473789406","displayName":"FULL NAME","name":{"familyName":"LAST NAME","givenName":"NAME"},"url":"https://plus.google.com/USER","image":{"url":"https://lh5.googleusercontent.com/-RTcRn6jTuoI/AAAAAAAAAAI/AAAAAAAAEpg/Y6cMxfwtbQ4/photo.jpg?sz=50","isDefault":false},"placesLived":[{"value":"CITY I LIVE","primary":true}],"isPlusUser":true,"verified":false,"cover":{"layout":"banner","coverPhoto":{"url":"https://lh3.googleusercontent.com/SybH-BjYW2ft1rzayamGLg_VwW7ocgnQ5cAxH3ROEpODvyaEODpYKW55gmAxCXDUvfKggQ4=s630-fcrop64=1,00002778ffffffff","height":626,"width":940},"coverInfo":{"topImageOffset":0,"leftImageOffset":0}}}}
Source: Google Plus API documentation
In case anyone else comes across this question: the solution to retrieving the email addresses of an authorized user's contacts, what the OP seems to want (not the authorized user's own email address) is at Why can't I retrieve emails addresses and phone numbers with Google People API?.
Explanation: If you look at the section under "Query Parameters" on https://developers.google.com/people/api/rest/v1/people.connections/list, you'll see that requestMask is a parameter (documented at https://developers.google.com/people/api/rest/v1/RequestMask).
It says that you'll need to include the requestMask parameter in your query, because you're doing a people.list query (i.e. using the connections GET endpoint). The requestMask parameter basically tells the API what fields to pull: person.emailAddresses tells it to pull the peoples' email addresses, person.emailAddresses,person.names tells it to pull their email addresses and names, etc.
GET https://people.googleapis.com/v1/people/me/connections?sortOrder=FIRST_NAME_ASCENDING&fields=connections(emailAddresses%2Cnames)&key={YOUR_API_KEY}
Try this and it will give you the emails. Make sure your contacts has emails.
You can get the profile emails from the Google People API, by making a request to https://people.googleapis.com/v1/people/me.
If you want non public emails, you will need to request the email or https://www.googleapis.com/auth/user.emails.read scope as specified in https://developers.google.com/people/v1/how-tos/authorizing#profile-scopes