Parse - Sending push notifications using cloud code (Swift) - swift

I'm trying to set up push notifications from one user to another using Back4App which is a parse server. I have followed their guide here
the Javascript cloud code they use is below:
Parse.Cloud.define("pushsample", function (request, response) {
Parse.Push.send({
channels: ["News"],
data: {
title: "Hello from the Cloud Code",
alert: "Back4App rocks!",
}
}, {
success: function () {
// Push was successful
response.success("push sent");
console.log("Success: push sent");
},
error: function (error) {
// Push was unsucessful
response.error("error with push: " + error);
console.log("Error: " + error);
},
useMasterKey: true
});
});
I am updating a custom parse class called notifications within the app which I would also like to send to the user the notification is directed at. When saving this class I am grabbing the UserID which is also stored in the installation class used to send pushes. I am completely new to Javascript so am wondering if someone could tell me how to edit the above code to receive the userID from the method on the device and then run a query to send to just this user.

The push notification feature allows to configure options and customizing the push.
You can send a query to update one specific user. Please, take a look at the example below:
Parse.Cloud.define("sendPushToUser", async (request) => {
var query = new Parse.Query(Parse.Installation);
let userId = request.params.userId;
query.equalTo('userId', userId);
Parse.Push.send({
where: query,
data: {
alert: "Ricky Vaughn was injured in last night's game!",
name: "Vaughn"
}
})
.then(function() {
// Push was successful
}, function(error) {
// Handle error
});
});
At the moment, you can read more about these options here.

Related

Expose return value

I have this piece of code that I am working on. To provide context, I am using an event source to stream an server sent event. Once I receive the data/response I want to pass that into my template(handlebars) view. The code below is a GET request in which I am trying to display the data returned from SSEvents.addEventListener.
method: 'GET',
path: '/students',
config: {
handler: (request, reply) => {
SSEvents.addEventListener('score', function(e) {
const data = JSON.parse(e.data);
}, false);
reply.view('students', {result: data});
},
description: "Endpoint lists all users that have received at least one test score.",
tags: ['api']
}
}
The issue with this code is the constant "data" is not available outside of the scope of the event listener. I need to find a way to expose the constant so that I can use it in reply.view('students', {result: data});
NOTE: I have tried adding "reply.view('students', {result: data});" within the event listener and it throws the following error: reply interface called twice.
Any help would be appreciated.
--Thanks!
It should be working like this. How long it takes your event source to produce an answer? Did you call the reply method twice? This is only one call.
handler: (request, reply) => {
SSEvents.addEventListener('score', function(e) {
const data = JSON.parse(e.data);
return reply.view('students', {
result: data
});
}, false);
},
description: "Endpoint lists all users that have received at least one test score.",
tags: ['api']
}

How do I interrupt a sequence flow in OpenWhisk?

I'm writing a trigger on a Cloudant database that should convert each new document into a Slack notification.
I've created a sequence of two actions: one to prepare the Slack message, one to send it. To send the Slack message I'm using the package action provided by IBM Bluemix OpenWhisk.
Cloudant changes feed --> Prepare Text --> Slack Post --> response
As the triggers send me all Cloudant events (new/modified/deleted documents), how can I only forward to Slack the NEW document event and ignore things like deleted documents.
For synchronous processing, simply return an error in our action
function main(doc) {
if (doc._deleted) {
// ignore deleted documents
return { error: "ignoring deleted doc" };
} else {
// prepare the text for the Slack post action
const slackMessage = ...
return { text: slackMessage };
}
}
return new Error("ignoring deleted doc") works too.
Or using the Promise object, one can call reject(reason) to interrupt the flow of a sequence.
function main(doc) {
return new Promise((resolve, reject) => {
if (doc._deleted) {
// ignore deleted documents
reject({ error: "ignoring deleted doc" });
} else {
// prepare the text for the Slack post action
const slackMessage = ...
resolve({ text: slackMessage });
}
};
}
The call to reject will stop the sequence flow. Any of reject('interrupted!'), reject(new Error('interrupted!'), reject({ error: 'interrupted!' }).
Warning: reject() will not work. You must provide a reason to reject.

How to Catch Error When Data is not Sent on Angularfire when adding data to firebase?

Im using angularfire to save data into my firebase. Here is a quick code.
$scope.users.$add({
Name:$scope.username,
Age:$scope.newage,
Contact: $scope.newcontact,
});
alert('Saved to firebase');
I am successful in sending these data to my firebase however how can I catch an error if these data are not saved successfully? Any ideas?
EDIT
So after implementing then() function.
$scope.users.$add({
Name:'Frank',
Age:'20',
Contact: $scope.newcontact,
}).then(function(ref) {
alert('Saved.');
}).catch(function(error) {
console.error(error); //or
console.log(error);
alert('Not Saved.');
});
When connected to the internet. The then() function is fine. It waits for those data to be saved in firebase before showing the alert.
What I want is for it to tell me that data is not saved. catch error function is not firing when i am turning off my internet connection and submitting those data.
When you call $add() it returns a promise. To detect when the data was saved, implement then(). To detect when saving failed, implement catch():
var list = $firebaseArray(ref);
list.$add({ foo: "bar" }).then(function(ref) {
var id = ref.key;
console.log("added record with id " + id);
list.$indexFor(id); // returns location in the array
}).catch(function(error) {
console.error(error);
});
See the documentation for add().
Update
To detect when the data cannot be saved due to not having a network connection is a very different problem when it comes to the Firebase Database. Not being able to save in this case is not an error, but merely a temporary condition. This condition doesn't apply just to this set() operation, but to all read/write operation. For this reason, you should handle it more globally, by detecting connection state:
var connectedRef = firebase.database().ref(".info/connected");
connectedRef.on("value", function(snap) {
if (snap.val() === true) {
alert("connected");
} else {
alert("not connected");
}
});
By listening to .info/connected your code can know that the user is not connected to the Firebase Database and handle it according to your app's needs.

Apigee push notification - one

Apigee's push notification is documented here.
http://apigee.com/docs/api-baas/content/introducing-push-notifications
I tried this with the js sdk that Apigee provides here http://apigee.com/docs/app-services/content/installing-apigee-sdk-javascript. It looks like only the client can generate a notification to itself?
But I have a scenario where I would like to push notifications to multiple clients from a nodejs job that runs once every hour. Something like this, but from the nodejs sdk not from the js sdk.
var devicePath = "devices;ql=*/notifications";
How do I do this?
As remus points out above, you can do this with the usergrid module (https://www.npmjs.com/package/usergrid).
You are basically trying to construct an API call that looks like this (sending a message by referencing a device):
https://api.usergrid.com/myorg/myapp/devices/deviceUUID/notifications?access_token= access_token_goes_here '{"payloads":{"androidDev":"Hello World!!"}}'
Or like this (sending a message by referencing a user who is connected to a device)
https://api.usergrid.com/myorg/myapp/users/fred/notifications?access_token=access_token_goes_here '{"payloads":{"androidDev":"Hello World!!"}}'
You can do this with code that looks something like this:
var options = {
method:'POST',
endpoint:'devices/deviceUUID/notifications',
body:{ 'payloads':{'androidDev':'Hello World!!'} }
};
client.request(options, function (err, data) {
if (err) {
//error - POST failed
} else {
//data will contain raw results from API call
//success - POST worked
}
});
or
var options = {
method:'POST',
endpoint:'users/fred/notifications',
body:{ 'payloads':{'androidDev':'Hello World!!'} }
};
client.request(options, function (err, data) {
if (err) {
//error - POST failed
} else {
//data will contain raw results from API call
//success - POST worked
}
});
Note: the second call, that posts to the users/username/notifications endpoint assumes that you have already made a connection between the user and their device (e.g. POST /users/fred/devices/deviceUUID).

Baasbox and Javascript

I'm trying BaaSbox, a free Backend as a Service. But it has no out-of-the-box Javascript support I can use right away (yet, only iOS and Android)
I'm having trouble sending the right curl command from javascript, anyone happen to know a good resource or a simple working $.ajax template? I've tried a few examples from stackoverflow, but none of them specifically aimed at BaaSbox.
I've tried following the Java instructions on their site here. Just making a simple login work, but I keep getting the wrong responses from the server.
Or on the other hand, anyone know a good, free alternative to BaaSbox? I just want to be able to install it on my own server, no paid plans or whatever.
in the download page there is a preliminary version of the JS SDK (added few days ago).
The documentation is on the way, however in the zip file you can find a simple example.
For example to perform a signup:
//set the BaasBox parameters: these operations initialize the SDK
BaasBox.setEndPoint("http://localhost:9000"); //this is the address of your BaasBox instance
BaasBox.appcode = "1234567890"; //this is your instance AppCode
//register a new user
BaasBox.createUser("user", "pass", function (res, error) {
if (res) console.log("res is ", res);
else console.log("err is ", error);
});
Now you can login into BaasBox
//perform a login
$("#login").click(function() {
BaasBox.login("user", "pass", function (res, error) {
if (res) {
console.log("res is ", res);
//login ok, do something here.....
} else {
console.log("err is ", error);
//login ko, do something else here....
}
});
Once the user is logged in he can load the Documents belonging to a Collection (the SDK automatically manages the Session Token for you):
BaasBox.loadCollection("catalogue", function (res, error) { //catalogue is the name of the Collection
if (res) {
$.each (res, function (i, item) {
console.log("item " + item.id); //.id is a field of the Document
});
} else {
console.log("error: " + error);
}
});
However under the hood the SDK uses JQuery. So you can inspect it to know how to user $.ajax to call BaasBox.
For example the creatUser() method (signup) is:
createUser: function (user, pass, cb) {
var url = BaasBox.endPoint + '/user'
var req = $.ajax({
url: url,
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({
username: user,
password: pass
}),
success: function (res) {
var roles = [];
$(res.data.user.roles).each(function(idx,r){
roles.push(r.name);
})
setCurrentUser({"username" : res.data.user.name,
"token" : res.data['X-BB-SESSION'],
"roles": roles});
var u = getCurrentUser()
cb(u,null);
},
error: function (e) {
cb(null,JSON.parse(e.responseText))
}
});
}