notification(daily update) is not working on google home mini device - actions-on-google

i created an app on dialogflow and deployed on google assistant,
it is working fine on both mobile assistant and google home, but the notification(daily update) is not working on google home mini device
well daily update working really fine in mobile device, and i didnt use any rich response like card and other thing which mini device doesnt support, then what is the possible reason?
Currently it is deployed home-notification-6b314 same google app is used for deployment of firebase function(as webhook), dialogflow app and and action on google
what should i do?
here is some code which i write on my webhook for reference:
// process.env.DEBUG = 'actions-on-google:*';
import * as functions from 'firebase-functions';
const { DialogflowApp } = require('actions-on-google');
const Actions = {
UNRECOGNIZED_DEEP_LINK: 'deeplink.unknown',
FINISH_UPDATE_SETUP: 'finish.update.setup',
};
const Parameters = {
CATEGORY: 'category',
UPDATE_INTENT: 'UPDATE_INTENT'
};
const DAILY_NOTIFICATION_ASKED = 'daily_notification_asked';
const PUSH_NOTIFICATION_ASKED = 'push_notification_asked';
export const webhook = functions.https.onRequest((request, response) => {
try {
const app = new DialogflowApp({ request, response });
console.log('Request headers: ' + JSON.stringify(request.headers));
console.log('Request body: ' + JSON.stringify(request.body));
// Map of action from Dialogflow to handling function
const actionMap = new Map();
actionMap.set(app.StandardIntents.CONFIGURE_UPDATES, configureUpdates);
actionMap.set(Actions.FINISH_UPDATE_SETUP, finishUpdateSetup);
actionMap.set("welcome", welcome);
actionMap.set("whatMissed", whatMissed);
actionMap.set("what_did_i_missed.what_did_i_missed-yes", whatMissed_yes);
app.handleRequest(actionMap);
} catch (e) {
console.log("catch error: ", e)
}
});
function welcome(app) {
app.ask(app.buildRichResponse()
.addSimpleResponse({
speech:
`<speak>
<s> Hi, I'm you medication assistant </s>
</speak>`
})
)
}
// Start opt-in flow for daily updates
function configureUpdates(app) {
console.log("====>> configure triggered1")
const intent = app.getArgument('UPDATE_INTENT');
console.log("##### INTENT: ", intent);
const category = app.getArgument('notification-category');
console.log("##### category: ", category);
app.askToRegisterDailyUpdate(
'what_did_i_missed',
[{ name: "some name", textValue: "some text" }]
);
}
// Confirm outcome of opt-in for daily updates.
function finishUpdateSetup(app) {
console.log("====>> finish triggered")
if (app.isUpdateRegistered()) {
app.tell("Ok, I'll start giving you notification that time.");
} else {
app.tell("something went wrong when i was scheduling up notification");
}
}
// # NOTE
// must have to enable notification 2 places,
// - first in google action dashboard(overview>Action discovery and updates>{intent-name}>Enable User updates and notifications>set title of notification)
// - second in google cloud console(Firebase Cloud Messaging API),
// otherwise i will just keep saying '{your app name} is not responding'
function whatMissed(app) {
const status = app.getArgument("boolean");
if (status === 'yes') {
app.tell("Ok, good job. keep it up!");
} else {
app.ask("would you like me to remind you again?");
}
}
function whatMissed_yes(app) {
app.askToRegisterDailyUpdate(
'what_did_i_missed',
[{ name: "some name", textValue: "some text" }]
);
}

"In this first iteration updates are system notifications on the user's Assistant-enabled phones, but we plan to expand to new surfaces."
https://developers.google.com/actions/assistant/updates/overview
Support person is also saying it is only supported in mobile device, and not in other surfaces like google home and mini.

Related

Braintree Google Pay sandbox opens live domain

I'm trying to integrate Google Pay at my page, as expected doing that first at Sandbox environment but I face a problem that when I click the Google Pay button it opens the live domain and asks me to enter a real card, although I setup up all related to Sandbox environment.
Here is the code following BT documentation.
var createGooglePaymentComponent = function(clientInstance){
var button = document.querySelector('#google-pay-button');
var paymentsClient = new google.payments.api.PaymentsClient({
environment: 'TEST' // Or 'PRODUCTION'
});
braintree.googlePayment.create({
client: clientInstance,
googlePayVersion: 2,
}, function (googlePaymentErr, googlePaymentInstance) {
paymentsClient.isReadyToPay({
apiVersion: 2,
apiVersionMinor: 0,
allowedPaymentMethods: googlePaymentInstance.createPaymentDataRequest().allowedPaymentMethods,
}).then(function(response) {
if (response.result) {
button.addEventListener('click', function (event) {
event.preventDefault();
var paymentDataRequest = googlePaymentInstance.createPaymentDataRequest({
transactionInfo: {
currencyCode: 'USD',
totalPriceStatus: 'FINAL',
totalPrice: '100.00',
}
});
var cardPaymentMethod = paymentDataRequest.allowedPaymentMethods[0];
cardPaymentMethod.parameters.billingAddressRequired = true;
paymentsClient.loadPaymentData(paymentDataRequest).then(function(paymentData) {
googlePaymentInstance.parseResponse(paymentData, function (err, result) {
if (err) {
// Handle parsing error
}
// Send result.nonce to your server
});
}).catch(function (err) {
});
});
}
}).catch(function (err) {
});
});
};
Here is a screenshot of what I get:
Any idea why does that happen?
Using Google Pay in the TEST environment will return a TEST payment credential which won't actually charge the payment method that you provide. It's understandable that you don't want to be using real payment details.
If you want to be able to choose from a list of predefined test cards, follow the instructions here: https://developers.google.com/pay/api/web/guides/resources/test-card-suite
In short, you will need to join the googlepay-test-mode-stub-data Google Group which will then display a list of test accounts when accessing the Google Pay payment sheet with that user.

How to send notifications following recent Firestore updates using Firebase FCM and Ionic Native

I am trying to set up Cloud Messaging Functions using https://www.youtube.com/watch?v=SOOjamH1bAA&t=317s
The code for my question is at 7:35 of this video. The full doc is in the link accessible from the video.
I am struggling with the recent updates to Firestore (see https://firebase.google.com/docs/functions/beta-v1-diff#cloud-firestore ), especially for time 7:35 of the youtube video link above. following the updates I changed the .onCreate to:
exports.newSubscriberNotification = functions.firestore
.document('subscribers/{subscriberId}')
.onCreate((snap,context) => { //I notice no async event...
const data = snap.data();
The problem is: 'await' expression is only allowed within an async function. This makes sense as there is no longer an 'async event' due to the update.
const devices = await devicesRef.get(); //see time 8:25 of video above.
If I add an async even above, the problem becomes: Property 'error' does not exist on type '“” | Promise' on the line:
devices.forEach(result => {...}) //see time 8:35 of video above.
I have tried multiple solutions found online but I'm digging myself in a hole. I think the problem is I am not triggering the index.ts function file (according to console.log() ).
Please bear with me - I am relatively new to app development.
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import { Subject } from 'rxjs/Subject';
import { tap } from 'rxjs/operators';
admin.initializeApp();
console.log('before initializeApp');
exports.newSubscriberNotification = functions.firestore
.document('subscribers/{subscriberId}') //odd
.onCreate((snap,context) => {
const data = snap.data();
console.log('const data fired');
const userId = data.userId
const subscriber = data.subscriberId
console.log('gathered data')
// Notification content
const payload = {
notification: {
title: 'New Subscriber',
body: `${subscriber} is following your content!`,
}
}
// ref to the device collection for the user
const db = admin.firestore();
const devicesRef = db.collection('devices').where('userId', '==', userId);
// get the user's tokens and send notifications
console.log('before await');
const devices = await devicesRef.get();
console.log('async function');
console.log('before devices');
//devices();
console.log('after devices');
const tokens = [];
// send a notification to each device token
devices.forEach(result => {
const token = result.data().token;
tokens.push( token )
})
return admin.messaging().sendToDevice(tokens, payload)
});

Can I create follow-up actions on Actions on Google?

I know that I can deep link into my Google Home application by adding to my actions.json.
I also know that I can parse raw string values from the app.StandardIntents.TEXT intent that's provided by default, which I am currently doing like so:
if(app.getRawInput() === 'make payment') {
app.ask('Enter payment information: ');
}
else if(app.getRawInput() === 'quit') {
app.tell('Goodbye!');
}
But does Actions on Google provide direct support for creating follow-up intents, possibly after certain user voice inputs?
An example of a conversation flow is:
OK Google, talk to my app.
Welcome to my app, I can order your most recent purchase or your saved favorite. Which would you prefer?
Recent purchase.
Should I use your preferred address and method of payment?
Yes.
OK, I've placed your order.
My previous answer won't work after testing.
Here is a tested version.
exports.conversationComponent = functions.https.onRequest((req, res) => {
const app = new ApiAiApp({request: req, response: res});
console.log('Request headers: ' + JSON.stringify(req.headers));
console.log('Request body: ' + JSON.stringify(req.body));
const registerCallback = (app, funcName)=>{
if (!app.callbackMap.get(funcName)){
console.error(`Function ${funcName} required to be in app.callbackMap before calling registerCallback`);
return;
}
app.setContext("callback_followup", 1, {funcName});
}
const deRegisterCallback = (app)=>{
const context = app.getContext("callback_followup");
const funcName = app.getContextArgument("callback_followup", "funcName").value;
const func = app.callbackMap.get(funcName);
app.setContext("callback_followup", 0);
return func;
}
app.callbackMap = new Map();
app.callbackMap.set('endSurvey', (app)=>{
if (app.getUserConfirmation()) {
app.tell('Stopped, bye!');
}
else {
app.tell('Lets continue.');
}
});
app.callbackMap.set('confirmationStartSurvey', (app)=>{
const context = app.getContext("callback_follwup");
if (app.getUserConfirmation()) {
registerCallback(app, 'endSurvey');
app.askForConfirmation('Great! I\'m glad you want to do it!, do you want to stop?');
} else {
app.tell('That\'s okay. Let\'s not do it now.');
}
});
// Welcome
function welcome (app) {
registerCallback(app, 'confirmationStartSurvey');
const prompt = "You have one survey in your task list, do you want to proceed now?";
app.askForConfirmation(prompt);
}
function confirmationCalbackFollowup (app) {
const context = app.getContext("callback_followup");
if (! context){
console.error("ERROR: confirmationCallbackFollowup should always has context named callback_followup. ");
return;
}
const callback = deRegisterCallback(app);
return callback(app);
}
const actionMap = new Map();
actionMap.set(WELCOME, welcome);
actionMap.set('confirmation.callback.followup', confirmationCalbackFollowup );
app.handleRequest(actionMap);
});
The previous solution won't work because app is generated everytime the action function is called. I tried to save a callback function into app.data but it won't be existing next intent coming. So I changed another way. Register the callback function to app.callbackMap inside the function. so it will be there anyway.
To make it work, one important thing is Api.Ai need to have context defined in the intent. See the Api.Ai Intent here.
Make sure you have event, context, and action of course. otherwise, this intent won't be triggered.
Please let me know if you can use this solution. sorry for my previous wrong solution.
thanks
Can you give an example of a conversation flow that has what you are trying to do?
If you can use API.AI, they have Follow Up intents in the docs.
I do not think your code
if(app.getRawInput() === 'make payment') {
app.ask('Enter payment information: ');
}
else if(app.getRawInput() === 'quit') {
app.tell('Goodbye!');
}
is a good idea. I would suggest you have two different intent to handle "Payment information" and "Quit".

implement Push Notifications in Ionic 2 with the Pub/Sub Model

Hi this is a duplicate of the question at
Push Notifications in Ionic 2 with the Pub/Sub Model
i have already implemented push notifications following this article >
https://medium.com/#ankushaggarwal/push-notifications-in-ionic-2-658461108c59#.xvoeao59a
what i want is to be able to send notifications to users when some events take place in the app like chat or booking or new job post.
how to go further , this is my first app.
NOTE: code is almost exactly the same as the tutorial, Java has only been converted to Kotlin
This is my acutal ionic side code (on login page). The push.on('registration') will be fired when the user opens the app, the variable this.device_id will later (on succesfull login) be sent to my Kotlin REST API so I know the device_id and have coupled it to a user. This way you can send targeted push notifications.
If you send a push notification from Kotlin (code shown below, looks a bit like Java), the (always open, even opens after startup) connection to Google will send your device (defined by the device_id a message with the notification data (title, message, etc.) after which your device will recognize the senderID and match it to use your ionic application.
initializeApp() {
this.platform.ready().then(() => {
let push = Push.init({
android: {
senderID: "1234567890"
},
ios: {
alert: "true",
badge: false,
sound: "true"
},
windows: {}
});
//TODO - after login
push.on('registration', (data) => {
this.device_id = data.registrationId;
});
push.on('notification', (data) => {
console.log('message', data.message);
let self = this;
//if user using app and push notification comes
if (data.additionalData.foreground) {
// if application open, show popup
let confirmAlert = this.alertCtrl.create({
title: data.title,
message: data.message,
buttons: [{
text: 'Negeer',
role: 'cancel'
}, {
text: 'Bekijk',
handler: () => {
//TODO: Your logic here
this.navCtrl.setRoot(EventsPage, {message: data.message});
}
}]
});
confirmAlert.present();
} else {
//if user NOT using app and push notification comes
//TODO: Your logic on click of push notification directly
this.navCtrl.setRoot(EventsPage, {message: data.message});
console.log("Push notification clicked");
}
});
push.on('error', (e) => {
console.log(e.message);
});
});
}
Kotlin code (converted from the Java example, basically the same
package mycompany.rest.controller
import mycompany.rest.domain.User
import java.io.OutputStream
import java.net.HttpURLConnection
import java.net.URL
class PushNotification {
companion object {
val SERVER_KEY = "sOmE_w31rD_F1r3Ba5E-KEy";
#JvmStatic fun sendPush(user: User, message: String, title: String) {
if(user.deviceId != "unknown"){
val pushMessage = "{\"data\":{\"title\":\"" +
title +
"\",\"message\":\"" +
message +
"\"},\"to\":\"" +
user.deviceId +
"\"}";
val url: URL = URL("https://fcm.googleapis.com/fcm/send")
val conn: HttpURLConnection = url.openConnection() as HttpURLConnection
conn.setRequestProperty("Authorization", "key=" + SERVER_KEY)
conn.setRequestProperty("Content-Type", "application/json")
conn.setRequestMethod("POST")
conn.setDoOutput(true)
//send the message content
val outputStream: OutputStream = conn.getOutputStream()
outputStream.write(pushMessage.toByteArray())
println(conn.responseCode)
println(conn.responseMessage)
}else {
println("Nope, not executed")
}
}
#JvmStatic fun sendPush(users: List<User>, message: String, title: String) {
for(u in users) {
PushNotification.sendPush(u, message, title)
}
}
}
}
Then the method can be called as PushNotification.sendPush(user1, "Hello world!", "my title");
(btw realized you won't need to run the pushnotification from a server (localhost/external). You can just create a main class which sends it with your hardcoded deviceId for testing purposes.

Soundcloud API sc.stream (track not loading on mobile sometime) - working on desktop

We are currently using the soundcloud API SDK for streaming and it does work on desktop but not 100% on mobile. (using responsive html. same api of course)
Sometime track is not lauch ? sometime it is.
I do not have specific error but on chrome network this line is show in red ??
http://api.soundcloud.com/tracks/146926142/stream?client_id=XXXXX
Redirect
We use a function to stream the track.
function streamTrack(id) {
var defer = $q.defer();
// Stream the track
SC.stream('/tracks/' + id, {
useHTML5Audio: false,
waitForWindowLoad: true,
onfinish: _scope.next,
whileplaying: function () {
var _this = this;
// Since we are in a callback, we need to tell angularJS to apply the change
if (timeout1) $timeout.cancel(timeout1);
timeout1 = $timeout(function () {
// Update the progress bar
_scope.progress = (_this.position / currentTrackDuration * 100) + '%';
_scope.timer = moment(_this.position).format('mm:ss');
$rootScope.$broadcast('trackRunning', { timerunning: _scope.timer });
});
}
}, function (sound) {
if (sound) {
defer.resolve(sound);
} else {
defer.reject();
}
});
return defer.promise;
}
If somebody has an idea pls.
Best Regards
Xavier