Is it possible to setup a web hook for anytime a push notification is sent via Parse?
I want to retrieve the details of the push notification and set a column against any devices the push notification was sent to
No hook that I'm aware of, but you could run all of your pushes through one place in your code (either client or a cloud function), and do whatever post-push work you want to do there. Presuming JS and advanced targeting, it could look like this:
function pushToInstallations(query, data) {
var params = { where: query, data: data};
return Parse.Push.send(params).then(function() {
// this is the interesting part, run the installation query
return query.find();
}).then(function(installations) {
var date = new Date();
// presumes underscore, but a regular for loop works too
_.each(installations, function(installation) {
installation.set("mostRecentPushDate", date);
});
return Parse.Object.saveAll(installations);
});
}
Then, wherever in your code you were building an installation query and calling push, call your new pushing function instead, like this:
var query = new Parse.Query(Parse.Installation);
query.equalTo('someColumn', someValue);
pushToInstallations(query, {alert: "some message"}).then(function(installations) {
// these installations passed back were pushed to and updated
}, function(error) {
// handle error
});
Related
how's it going?
I've using this plugin for a long time, but today I needed to do some notifications in my app. I need to store my data in device and then, when I got internet connection, I'll send this for my servers. But ok, this is not important.
What I'm trying to do is:
Get my data from server;
Store my data in device using nativeStorage;
Getting data and putting in my storage
myFactory.getMyData().then(function(success) {
$cordovaNativeStorage.setItem("mydata", success);
}, function(err) {...});
OK, my data was correctly stored. Next I'll loop in thru this data and show in view.
$cordovaNativeStorage.getItem("mydata").then(function (success)
{
for (var i in success)
{
$scope.myData.push(success[i]);
}
}, function (err){
getMyData(); // function who will get my data from server
});
OK until now.
Next I'll send this data to another view and show my data. But when I do ANY modifications in that data (even if I change directly in object or in nativeStorage), that modification do not persists if I back to the main view.
$cordovaNativeStorage.getItem("myData").then(function (success){
success[myIndex].anyProperty = 'abc';
});
Is that a bug or am I not understanding something?
When you're calling $cordovaNativeStorage.setItem(), Native storage actually save JSON string rather than JSON object.Same with $cordovaNativeStorage.getItem(), it will return JSON string. Thus, you must parse it first before manipulating the object .
$cordovaNativeStorage.getItem("myData").then(function (jsonString){
if (jsonString) {
var jsonObj = JSON.parse(jsonString);
jsonObj.anyProperty = 'abc';
}
});
TL;DR: I want a PouchDB db that acts like Ember Data: fetch from the local store first, and if not found, go to the remote. Replicate only that document in both cases.
I have a single document type called Post in my PouchDB/CouchDB servers. I want PouchDB to look at the local store, and if it has the document, return the document and start replicating. If not, go to the remote CouchDB server, fetch the document, store it in the local PouchDB instance, then start replicating only that document. I don't want to replicate the entire DB in this case, only things the user has already fetched.
I could achieve it by writing something like this:
var local = new PouchDB('local');
var remote = new PouchDB('http://localhost:5984/posts');
function getDocument(id) {
return local.get(id).catch(function(err) {
if (err.status === 404) {
return remote.get(id).then(function(doc) {
return local.put(id);
});
}
throw error;
});
}
This doesn't handle the replication issue either, but it's the general direction of what I want to do.
I can write this code myself I guess, but I'm wondering if there's some built-in way to do this.
Unfortunately what you describe doesn't quite exist (at least as a built-in function). You can definitely fall back from local to remote using the code above (which is perfect BTW :)), but local.put() will give you problems, because the local doc will end up with a different _rev than the remote doc, which could mess with replication later on down the line (it would be interpreted as a conflict).
You should be able to use {revs: true} to fetch the doc with its revision history, then insert with {new_edits: false} to properly replicate the missing doc, while preserving revision history (this is what the replicator does under the hood). That would look like this:
var local = new PouchDB('local');
var remote = new PouchDB('http://localhost:5984/posts');
function getDocument(id) {
return local.get(id).catch(function(err) {
if (err.status === 404) {
// revs: true gives us the critical "_revisions" object,
// which contains the revision history metadata
return remote.get(id, {revs: true}).then(function(doc) {
// new_edits: false inserts the doc while preserving revision
// history, which is equivalent to what replication does
return local.bulkDocs([doc], {new_edits: false});
}).then(function () {
return local.get(id); // finally, return the doc to the user
});
}
throw error;
});
}
That should work! Let me know if that helps.
I have scheduled a parse push notification using cloud code. Now is there a way
change the date/time of that notification.
remove this notification from schedule.
var query = new Parse.Query(Parse.Installation);
query.equalTo('group_id', 'xxx');
Parse.Push.send({
where: query,
data: {
alert: "You previously created a reminder for the game today"
},
push_time: new Date(2014, 12, 30)
}, {
success: function() {
// Push was successful
},
error: function(error) {
// Handle error
}
});
There currently is NO API methods for this. I will update my answer when any major updates to their SDK have been published.
A work around is schedule a local push notification within Apples/Googles allowance and alter it thereafter when necessary.
Conversely,
Another way you could do it but will be code heavy; but create a push notification class on Parse Backend. Have pointers to users and create a few columns, one specifically will be a Parse Date with the proposed notification time. Update when necessary through the users device actions that way your not locked down to the one notification method set in stone. Everything is handled via cloud.
I have created a Background Job in Parse Cloud Code that sends out email notifications based on a date in one of my Parse classes.
Here is the idea: Query the class that contains the date. Iterate over each object returned and check the date field. If the date is equal to today, send out an email notification, change the date to null and save it back to Parse.
However, it seems that not all the objects are saved back to Parse. I suspect this an issue with my promise chains, but I am having a hard time diagnosing the exact issue or how to fix it. Below is relevant code
Parse.Cloud.job("job", function(request, status) {
// Query for all users
var query = new Parse.Query(className);
query.each(function(object) {
if (condition) {
object.set(key, false);
object.save(null, {
success:function(object){
// This never executes!
},
error: function(error){
}
}).then(function(){
// This never executes
console.log("Save objects successful");
},
function(error){
status.error("Uh oh, something went wrong saving object");
});
// Set hiatus end successful
Mailgun.sendEmail({
});
}
});
});
This line console.log("Save objects successful"); in the objects.save() promise chain does not ever get executed - even when the subscription object is successfully saved to Parse.
Additionally, if there are more than 5 objects returned by the query, only the first 5 are successfully saved back to Parse. Any additional saves are not executed and email notifications are not sent.
I'd clean it up as follows, relying on Promise.when ...
var savePromises = []; // this will collect save promises
var emailPromises = []; // this will collect email promises
// your code to setup the query here
// notice that this uses find() here, not each()
query.find(function(subscriptions) {
_.each(subscriptions, function(subscription) { // or a for loop, if you don't use underscore
// modify each subscription, then
savePromises.push(subscription.save());
// prepare each email then
var emailPromise = Mailgun.sendEmail({ /* your email params object here */ });
emailPromises.push(emailPromise);
});
// now do the saves
return Parse.Promise.when(savePromises);
}).then(function() {
// now do the emails
return Parse.Promise.when(emailPromises);
}).then(function() {
// Set the job's success status
status.success("Subscriptions successfully fetched");
// and so on with your code
You might also consider combining the saves and the emails into one big array of promises, but it might be better to do it in two batches serially since they have different failure modes.
tldr - What is the best pattern create a 'proprietary database' with data from an API? In this case, using Meteor JS and collections in mongo db.
Steps
1. Ping API
2. Insert Data into Mongo at some interval
In lib/collections.js
Prices = new Mongo.Collection("prices");
Basic stock api call, in server.js:
Meteor.methods({
getPrice: function () {
var result = Meteor.http.call("GET", "http://api.fakestockprices.com/ticker/GOOG.json");
return result.data;
}
});
Assume the JSON is returned clean and tidy, and I want to store the entire object (how you manipulate what is returned is not important, storing the return value is)
We could manipulate the data in the Meteor.method function above but should we? In Angular services are used to call API, but its recommended to modularize and keep the API call in its own function. Lets borrow that, and Meteor.call the above getPrice.
Assume this also done in server.js (please correct).
Meteor.call("getPrice", function(error, result) {
if (error)
console.log(error)
var price = result;
Meteor.setInterval(function() {
Prices.insert(price);
}, 1800000); // 30min
});
Once in the db, a pub/sub could be established, which I'll omit and link to this overview.
You may want to take a look at the synced-cron package.
With a cron job it's pretty easy, just call your method:
// server.js
SyncedCron.start();
SyncedCron.add({
name: "get Price",
schedule: function(parser){
return parser.text('every 30 minutes');
},
job: function(){
return Meteor.call("getPrice");
}
});
Then in getPrice you can do var result = HTTP.call(/* etc */); and Prices.insert(result);. You would want some additional checks of course, as you have pointed out.