BuildFire: Push Notification Testing - buildfire

I'm have a plugin that I'd like to send push notifications with. Referencing the BuildFire SDK Wiki, I've followed the documentation, but never received any notifications. As a trouble shooting step I've created a bare bones plugin that does nothing else aside from scheduling a push notification.
Here's the code that I'm using:
let now = new Date();
const fiveMinutes = (1000 * 60 * 5);
const sendAt = new Date(now.getTime() + fiveMinutes);
buildfire.notifications.pushNotification.schedule({
title:"Notification title"
,text:"Notification text"
,at: sendAt
},function(e){
if(e) console.error(e);
});
I'm testing this using a simple test app, from within the BuildFire Previewer app. As this is not a real app, it doesn't have any certificates for Push Notification. Can I receive the pushNotification SDK calls from within a test app via the Previewer that doesn't have any certificates?
Additionally, I don't receive any errors when testing via the SDK or the control panel. I do get the the callback function as expected, and no exception data in returned.

You are correct. The Previewer app will not allow you to send push notifications properly and here is why...
The previewer app is set up with a certificate. However, When your hot loaded app sends a push notification to queue up in the server. It will not find a certificate matching your hot loaded app id. And thus fail on the server.

Related

how does users.watch (in gmail google api) listen for notifications?

I am confused as to how should the watch feature in the gmail API be implemented to recieve the push notificatons inside a node.js script. Should I call the method inside an infinite loop or something so that it doesn't stop listening for notifications for email once after the call is made?
Here's the sample code that I've written in node.js:
const getEmailNotification = () => {
return new Promise(async (resolve, reject) => {
try{
let auth = await authenticate();
const gmail = google.gmail({version: 'v1', auth});
await gmail.users.stop({
userId: '<email id>'
});
let watchResponse = await gmail.users.watch({
userId: '<email id>',
labelIds: ['INBOX'],
topicName: 'projects/<projectName>/topics/<topicName>'
})
return resolve(watchResponse);
} catch(err){
return reject(`Some error occurred`);
}
})
Thank you!
Summary
To receive push notifications through PUB/SUB you need to create a web-hook to receive them. What does this mean? You need a WEB application or any kind of service that exposes a URL where notifications can be received.
As stated in the Push subscription documentation:
The Pub/Sub server sends each message as an HTTPS request to the subscriber application at a pre-configured endpoint.
The endpoint acknowledges the message by returning an HTTP success status code. A non-success response indicates that the message should be resent.
Setup a channel for watch the notifications could be summarized in the following steps (the documentation you refer to indicates them):
Select/Create a project within the Google Cloud Console.
Create a new PUB/SUB topic
Create a subscription (PUSH) for that topic.
Add the necessary permissions, in this case add gmail-api-push#system.gserviceaccount.com as Pub/Sub Publisher.
Indicate what types of mail you want it to listen for via Users.watch() method (which is what you are doing in your script).
Example
I give you an example using Apps Script (it is an easy way to visualize it, but this could be achieved from any kind of WEB application, as you are using Node.js I suppose that you are familiarized with Express.js or related frameworks).
First I created a new Google Apps Script project, this will be my web-hook. Basically I want it to make a log of all HTTP/POST requests inside a Google Doc that I have previously created. For it I use the doPost() equal to app.post() in Express. If you want to know more about how Apps Script works, you can visit this link), but this is not the main topic.
Code.gs
const doPost = (e) => {
const doc = DocumentApp.openById(<DOC_ID>)
doc.getBody().appendParagraph(JSON.stringify(e, null, 2))
}
Later I made a new implementation as a Web App where I say that it is accessible by anyone, I write down the URL for later. This will be similar to deploying your Node.js application to the internet.
I select a project in the Cloud Console, as indicated in the Prerequisites of Cloud Pub/Sub.
Inside this project, I create a new topic that I call GmailAPIPush. After, click in Add Main (in the right bar of the Topics section ) and add gmail-api-push#system.gserviceaccount.com with the Pub/Sub Publisher role. This is a requirement that grants Gmail privileges to publish notification.
In the same project, I create a Subscription. I tell it to be of the Push type and add the URL of the Web App that I have previously created.
This is the most critical part and makes the difference of how you want your application to work. If you want to know which type of subscription best suits your needs (PUSH or PULL), you have a detailed documentation that will help you choose between these two types.
Finally we are left with the simplest part, configuring the Gmail account to send updates on the mailbox. I am going to do this from Apps Script, but it is exactly the same as with Node.
const watchUserGmail = () => {
const request = {
'labelIds': ['INBOX'],
'topicName': 'projects/my_project_name/topics/GmailAPIPush'
}
Gmail.Users.watch(request, 'me')
}
Once the function is executed, I send a test message, and voila, the notification appears in my document.
Returning to the case that you expose, I am going to try to explain it with a metaphor. Imagine you have a mailbox, and you are waiting for a very important letter. As you are nervous, you go every 5 minutes to check if the letter has arrived (similar to what you propose with setInterval), that makes that most of the times that you go to check your mailbox, there is nothing new. However, you train your dog to bark (push notification) every time the mailman comes, so you only go to check your mailbox when you know you have new letters.

How to integrate React native navigation with AWS Amplify push notifications in android?

I am trying to get FCM push notifications working in my react native project for android with react-native-notification library and aws-amplify. I have an issue with PushNotification.onRegister method is not called in android to get device token to send remote notifications.How can I make these two library working together in my react native project?
I followed aws-amplify documentation https://aws-amplify.github.io/docs/js/start?ref=amplify-rn-btn&platform=react-native
to include amplify library in react native project.
I then added push notifications set up as per https://aws-amplify.github.io/docs/js/push-notifications
I have included react-native-navigation library to support navigation in my react-native app as per
https://wix.github.io/react-native-navigation/#/docs/Installing
After the installation react-native navigation library pushNotification.onRegister method is not getting called to receive device token without which I am unable to send push notifications in android.
I have push notifications configured in App.js as per below
import PushNotification from '#aws-amplify/pushnotification';
import Analytics from '#aws-amplify/analytics';
import Auth from '#aws-amplify/auth';
// retrieve temporary AWS credentials and sign requests
Auth.configure(awsconfig);
// send analytics events to Amazon Pinpoint
Analytics.configure(awsconfig);
console.log(PushNotification);
PushNotification.configure(awsconfig);
Then in the constructor of App.js I am registering for PushNotification events.
Navigation.events().registerAppLaunchedListener(() => {
PushNotification.onNotification((notification) => {
// Note that the notification object structure is different from Android and IOS
console.log('in app notification', notification);
// required on iOS only (see fetchCompletionHandler docs: https://facebook.github.io/react-native/docs/pushnotificationios.html)
notification.finish(PushNotificationIOS.FetchResult.NoData);
});
// get the registration token
PushNotification.onRegister((token) => {
Alert.alert(token);
this.setState({token:token});
console.log('in app registration', token);
});
// get the notification data when notification is opened
PushNotification.onNotificationOpened((notification) => {
console.log('the notification is opened', notification);
});
});
This set up works fine and PushNotification.onRegister event is called and device token is getting printed if I don't include react-native-navigation library.
In iOS I am able to get device token with react-native-navigation library but in android it is not working. Any pointers on this issue would be greatly appreciated!
See here: https://github.com/aws-amplify/amplify-js/issues/2541#issuecomment-455245033
the Android app calls .onRegister() once only, when the app/device is completely new. The calls afterwards seems to load from cache.

How to catch Facebook messaging_optins with Azure Bot Channels Registration + Botbuilder SDK?

I've got a chatbot up and running, built using Node.JS Microsoft Bot Framework, and deployed to an Azure server as a Web App, with a Bot Channels Registration resource as the frontend endpoint.
This Bot Channels Registration is connected to Facebook Messenger (via a FB App) - meaning, the webhook for the Facebook App points to https://facebook.botframework.com/api/v1/bots/<BOT_CHANNELS_REGISTRATION_RESOURCE_NAME>.
This all works well for normal chat functionality.
However, I'd now like to add an opt-in checkbox to a separate web page I have. This checkbox works by pinging FB, which then sends a very specific payload to the already configured bot webhook.
{
"recipient":{
"id":"<PAGE_ID>"
},
"timestamp":<UNIX_TIMESTAMP>,
"optin":{
"ref":"<PASS_THROUGH_PARAM>",
"user_ref":"<UNIQUE_REF_PARAM>"
}
}
My question is this:
How does the Bot Channels Registration receive and handle the above payload? Will it just automatically forward it to the Messaging Endpoint I have configured in the Bot Channels Registration settings? Or will it get stuck, and never reach my actual bot Web App?
Finally, if it does reach my normal messages endpoint, how can I handle the specific payload with my botbuilder.ChatConnector() listener? Given that my web app code looks like (in essence)
var restify = require('restify');
var builder = require('botbuilder');
var dialogues = require('./dialogues');
var chatbot = function (config) {
var bot = {};
chatbot.listen = function () {
var stateStorage = new builder.MemoryBotStorage();
var connector = new builder.ChatConnector({
appId: process.env.APP_ID,
appPassword: process.env.APP_PASSWORD
});
bot = new builder.UniversalBot(connector, function (session) {
session.beginDialog(dialogues.base(bot).name);
}).set('storage', stateStorage);
return connector.listen();
};
return chatbot;
}
var server = restify.createServer();
// Listen for messages from users
server.post('/api/messages', chatbot.listen());
server.listen(process.env.port, function () {
console.log('%s listening to %s', server.name, server.url);
});
Thanks!
EDIT: I've figured out how to handle the above payload within my messaging endpoint - by adding a server.pre() handler to my server, e.g.
server.pre(function (req, res, next) {
if (req.body && req.body.optin_payload_specific_field){
// handle opt-in payload
} else {
return next();
}
});
However, via extra logging lines, it seems the opt-in payload isn't even making it to this endpoint. It seems to be stopped within the Bot Channels Registration. Currently looking for a way to resolve that major roadblock.
So, per #JJ_Wailes investigation, it seems like this is not a supported feature (in fact, it's a current feature request). See his comments on the original post for more details.
However, I did find a half-workaround to capture the user_ref identifier generated by the checkbox_plugin, for those interested:
1) From your external site, follow the steps from the documentation here for sending the initial user_ref to FB. FB will then make a callout to your bot, but per the above, that gets blocked by the Bot Channels Registration piece, so it's ignored.
2) From that same external site, use the user_ref to send a message to the user (just using the normal requests library). A successful send means that the user_ref was properly registered in FB by that step #1 call - a failure means you'll need to repeat step #1 (or use some other error handling flow).
3) After that, the next time the user responds to your bot in FB (as long as you don't send any other messages to them), the message your bot will receive will contain this as part of the payload:
{ ...
channelData:
{ ...
prior_message:
{ source: 'checkbox_plugin',
identifier: <user_ref> }
}
}
So I've currently added a check within my bot.use(), where if that section is present in the incoming message payload (session.message.sourceEvent.prior_message) and the source is "checkbox_plugin", I store the corresponding user_ref in the session.userData, and can work from there.
I would love to see this feature added into the supported Azure bot stack, but in the meantime hopefully this helps anyone else encountering this (admittedly niche) hurdle.

Receive GCM push notification in node.js app

I'm building a command-line application in node.js and would like to receive GCM push notifications (the command-line app will be interacting with the same set of services that iOS/Android apps use, hence wanted to use the same notification service).
Given that GCM can be used on iOS (and thus is not Android-specific) I am hoping it can be used from node.js as well.
I've seen many articles about sending push notifications from node.js, but haven't been able to find anything about using node.js on the receiving end.
i think if you have to send push notification ,to ios and andriod then fcm is better then gcm use this
router.post('/pushmessage', function (req, res) {
var serverKey = '';//put server key here
var fcm = new FCM(serverKey);
var token = "";// put token here which user you have to send push notification
var message = {
to: token,
collapse_key: 'your_collapse_key',
notification: {title: 'hello', body: 'test'},
data: {my_key: 'my value', contents: "abcv/"}
};
fcm.send(message, function (err, response) {
if (err) {
res.json({status: 0, message: err});
} else {
res.json({status: 1, message: response});
}
});
});
I believe you can using service workers.
Push is based on service workers because service workers operate in the background. This means the only time code is run for a push notification (in other words, the only time the battery is used) is when the user interacts with a notification by clicking it or closing it. If you're not familiar with them, check out the service worker introduction. We will use service worker code in later sections when we show you how to implement pushes and notifications.
So basically there is a background service that waits for push and thats what you are going to build.
Two technologies
Push and notification use different, but complementary, APIs: push is invoked when a server supplies information to a service worker; a notification is the action of a service worker or web page script showing information to a user.
self.addEventListener('push', function(event) {
const promiseChain = getData(event.data)
.then(data => {
return self.registration.getNotifications({tag: data.tag});
})
.then(notifications => {
//Do something with the notifications.
});
event.waitUntil(promiseChain);
});
https://developers.google.com/web/fundamentals/engage-and-retain/push-notifications/handling-messages
I don't think it possible (in a simple way)...
Android/iOS has an OS behind with a service that communicates with GCM...
If you are trying to run a CLI tool, you'll need to implement a service on top of the OS (Linux, Windows Mac) so it can receive notifications.
GCM sends the notifications against the device tokens which are generated from iOS/Android devices when they are registered with push notification servers. If you are thinking of receiving the notifications without devices tokens it is fundamentally incorrect.
It's not mandatory to depend only on GCM, today there are many packages are available for sending pushNotification.
Two node packages are listed below.
fcm-call - you can find documentation from https://www.npmjs.com/package/fcm-call
fcm-node
fcm-call is used - you can find documentation from https://www.npmjs.com/package/fcm-node/
let FCM = require('fcm-call');
const serverKey = '<Your Server Key>';
const referenceKey = '<Your reference key>'; //Device Key
let title = '<Your notification title here.>';
let message = '<Your message here>';
FCM.FCM(serverKey, referenceKey, title, message);
And Your notification will be sent within 2-3 seconds.
Happy Notification.

Google Cloud Pub/Sub API - Push E-mail

I'm using node.js to create an app that gets a PUSH from Gmail each time an email is received, checks it against a third party database in a CRM and creates a new field in the CRM if the e-mail is contained there. I'm having trouble using Google's new Cloud Pub/Sub, which seems to be the only way to get push from Gmail without constant polling.
I've gone through the instructions here: https://cloud.google.com/pubsub/prereqs but I don't understand how exactly this is supposed to work from an app on my desktop. It seems that pub/sub can connect to a verified domain, but I can't get it to connect directly toto the .js script that I have on my computer. I've saved the api key in a json file and use the following:
var gcloud = require('gcloud');
var pubsub;
// From Google Compute Engine:
pubsub = gcloud.pubsub({
projectId: 'my-project',
});
// Or from elsewhere:
pubsub = gcloud.pubsub({
projectId: 'my-project',
keyFilename: '/path/to/keyfile.json'
});
// Create a new topic.
pubsub.createTopic('my-new-topic', function(err, topic) {});
// Reference an existing topic.
var topic = pubsub.topic('my-existing-topic');
// Publish a message to the topic.
topic.publish('New message!', function(err) {});
// Subscribe to the topic.
topic.subscribe('new-subscription', function(err, subscription) {
// Register listeners to start pulling for messages.
function onError(err) {}
function onMessage(message) {}
subscription.on('error', onError);
subscription.on('message', onMessage);
// Remove listeners to stop pulling for messages.
subscription.removeListener('message', onMessage);
subscription.removeListener('error', onError);
});
However, I get errors as if it isn't connecting to server and on the API list I see only errors, no actual successes. I'm clearly doing something wrong, any idea what it might be?
Thank you in advance!
TL;DR
Your cannot subscribe to push notifications from the client side.
Set up an HTTPS server to handle the messages. Messages will be sent
to the URL endpoint that you configure, representing that server's
location. Your server must be reachable via a DNS name and must
present a signed SSL certificate. (App Engine applications are
preconfigured with SSL certificates.)
Just subscribe to the push notifications on your server, and when you get the notification, you can figure out who it concerns. The data you will get from the notifications is what user that it concerns, and the relevant historyId, like so:
// This is all the data the notifications will give you.
{"emailAddress": "user#example.com", "historyId": "9876543210"}
Then you could e.g. emit an event through Socket.io to the relevant user if he is online, and have him do a sync with the supplied historyId on the client side.

Resources