Dynamic push notifications w/ Onesignal, Nuxtjs and Prismic CMS - progressive-web-apps

I'm building a PWA using Nuxtjs that's fetching blog content from a prismic api. OneSignal has been installed and configured following the documentation provided here and I was able to subscribe a user to the app and deliver the welcome push along with other push via OneSignal's dashboard.
I now want to send push notifications whenever new content is posted to the blog. Any help would be appreciated.
EDIT
I am triggering the push notification whenever a user goes to https://example.com/blog. NB: prismic sorts by latest post so this.docs[0] fetches the latest article from the array.
async fetch() {
try {
const query = await this.$prismic.api.query(this.$prismic.predicates.at('document.type', 'blog_posts'), {pageSize: 6}).then((query)=>{
this.docs = query.results;
const requestOptions = {
method: "POST",
headers: {"Content-Type": "application/json", "Authorization": `Basic ${process.env.API_KEY}`},
body: JSON.stringify({
app_id: process.env.APP_ID,
included_segments: ["All"],
contents: {en: this.docs[0].data.post_content[0].text},
headings: {en: this.docs[0].data.post_title[0].text},
chrome_web_image: this.docs[0].data.featured_image.url,
big_picture: this.docs[0].data.featured_image.url,
web_url: `https://example.com/blog/${this.docs[0].uid}`
})
}; fetch('https://onesignal.com/api/v1/notifications', requestOptions)
})
} catch (e) {
// Send to bugsnag
console.log(e)
}
}, fetchDelay: 500,

Prismic allows you set webhooks that trigger when a document is published. See prismic blog. Using express, I created one that will do two things:
Get all blog post from prismic
Send onesignal web push notification when post is published
See code snippet here: https://gitlab.com/-/snippets/2003202
References:
Prismic Node Integration
Bearer.sh Guide on webhook listeners

Related

WooCommerce REST API PUT on Variations does not work

I have logged this issue on GitHub but I understand it will take time to get attention. Is there another way of updating Product Variations?
https://github.com/woocommerce/woocommerce/issues/35555
When I PUT a stock_quantity or price update for a product variation nothing changes. This however works 100% on a product but not a variation. The below will have no effect even though I receive an OK status 200.
PUT: wp-json/wc/v3/products/6360/variations/6361
{
"stock_quantity": 7
}
I also tried using the batch endpoint but also nothing gets updated.
/wp-json/wc/v3/products/6360/variations/batch
"update": [
{
"id":6361,
"stock_quantity": 4
}
]
This is not a bug, I was using Postman and the 200 OK returned confused the issue.
Once I added the required Content-Type:application/json header, the record successfully updated.
I also made use of a deprecated NodeJS library woocommerce-api and later tried with the replacement woocommerce-rest-api but both does not seem to handle this correctly.
I can suggest to rather just axios directly to the woocommerce rest api:
const baseUrl = `${process.env.WOOCOMMERCE_URI}/wp-json/wc/v3/`;
const instance = {
headers: {'Content-Type': 'application/json'},
auth: {
username: process.env.WOOCOMMERCE_KEY,
password: process.env.WOOCOMMERCE_SECRET
}
};
let putUrl = `products/${woocommerceImport.onlineProductId}/variations/${woocommerceImport.onlineVariantId}`;
await axios.put(`${baseUrl}${putUrl}`, {
stock_quantity: stock
}, instance);

How to trigger Google Composer Airflow dag using appscript?

I want to trigger a Google Composer airflow dag using Appscript. Is there any way to do it via rest API or another way.
If it is possible please suggest the solution.
Airflow has an endpoint that allows to trigger a DAG through its REST API, however it’s not possible to access it directly, since within the Cloud Composer architecture, the Airflow web server is located under an App Engine flexible environment. By default, the Airflow web server is integrated with Identity-Aware Proxy (IAP) and authentication is required.
Based on that, I found an example in the Cloud Composer documentation, that guides you to trigger a DAG using Cloud Functions, although the code is in JavaScript I don’t think it’s possible to execute it by Google App Script.
On the other hand, a workaround is to follow the Triggering DAGs guide changing some settings as follows.
In the creation of the function instead of setting the trigger type as Cloud Storage set it as HTTP, and check the “Allow unauthenticated invocations” for test purpose. An URL will be displayed, the goal is that every time that URL is accessed the DAG is executed.
Modify the first part of the index.js file, since no data would be passed as parameters and also the makeIapPostRequest function to return the response of the API call.
exports.triggerDag = async (req, res) => { // Modification
// Fill in your Composer environment information here.
// The project that holds your function
const PROJECT_ID = 'your-project-id';
// Navigate to your webserver's login page and get this from the URL
const CLIENT_ID = 'your-iap-client-id';
// This should be part of your webserver's URL:
// {tenant-project-id}.appspot.com
const WEBSERVER_ID = 'your-tenant-project-id';
// The name of the DAG you wish to trigger
const DAG_NAME = 'composer_sample_trigger_response_dag';
// Other constants
const WEBSERVER_URL = `https://${WEBSERVER_ID}.appspot.com/api/experimental/dags/${DAG_NAME}/dag_runs`;
const USER_AGENT = 'gcf-event-trigger';
const BODY = {conf: ‘’}; // Modification
// Make the request
try {
const iap = await authorizeIap(CLIENT_ID, PROJECT_ID, USER_AGENT);
const apiReponse = await makeIapPostRequest(WEBSERVER_URL, BODY, iap.idToken, USER_AGENT); // Modification
res.status(200).send('DAG_running!'); // Modification
} catch (err) {
console.error('Error authorizing IAP:', err.message);
throw new Error(err);
}
};
const makeIapPostRequest = async (url, body, idToken, userAgent) => {
const res = await fetch(url, {
method: 'POST',
headers: {
'User-Agent': userAgent,
Authorization: `Bearer ${idToken}`,
},
body: JSON.stringify(body),
});
if (!res.ok) {
const err = await res.text();
console.error('Error making IAP post request:', err.message);
throw new Error(err);
}
return {
apiRes: res.ok, // Modification
};
};
At this point, anything else has to be changed, so in your Script file execute the next instructions in order to trigger the DAG.
function myFunction() {
var response = UrlFetchApp.fetch("Cloud-function-URL");
Logger.log(response.getAllHeaders());
}
Finally, verify in the Airflow web interface if the DAG was triggered.

Can't retrieve the play store reviews for my app

I am trying to get the reviews for my app from the playstore using the new reviews api from the android publisher service.
The app key is me.jadi (https://play.google.com/store/apps/details?id=me.jadi) as you can see it have reviews posted for it.
Here is the code I'm using:
var google = require('googleapis');
var secrets = require('./secrets.json');
var androidpublisher = google.androidpublisher('v2');
var authClient = new google.auth.JWT(
secrets.client_email, null, secrets.private_key,
['https://www.googleapis.com/auth/androidpublisher'], null);
authClient.authorize(function (err, tokens) {
if (err) {
return console.log(err);
}
androidpublisher.reviews.list({ auth: authClient, packageName: 'me.jadi' }, function (err, resp) {
if (err) {
return console.log(err);
}
});
});
It doesn't contain any errors for the auth nor for the actual service request. But the result is always an empty object.
So I'm trying to identify the problem,
is there something wrong with the code
do I need to opt-in specifically somewhere to use the API
does the API have any limitations, like geographic (the service is allowed only for the US devs)
or maybe the service have some bugs because it is still in beta
I found the answer my self, and I'll post it here for future reference.
The problem with my specific case was that I didn't have reviews posted or modified in the last week.
And the API documentation clearly states that it will keep history of the reviews in the last seven days.
Once I get a new review I tried the code and the review was successfully retrieved.

how to update an subscription without id in mail chimp rest api

I really like the new Mail Chimp REST API - it is easy to create subscriptions by PUT and those can be updated using the subscription id.
But I would like to update a subscription simply using the email address, because I do not want to save any new Mail Chimp Id in my Middle-ware application, as long as the email should be sufficient as identifier?
To update a List Member the API is:
/lists/{list_id}/members/{id}
but I would prefer a simpler way:
/lists/{list_id}/members/{email}
is something like this possible?
The subscriber's ID is the MD5 hash of their email address. Since you would have to make a function call to URL Encode the email address for your second way, using the first way is just as easy.
See this help document on managing subscribers for more details.
More specifics on updating a subscriber via MailChimp's REST API.
// node/javascript specific, but pretty basic PUT request to MailChimp API endpoint
// dependencies (npm)
var request = require('request'),
url = require('url'),
crypto = require('crypto');
// variables
var datacenter = "yourMailChimpDatacenter", // something like 'us11' (after '-' in api key)
listId = "yourMailChimpListId",
email = "subscriberEmailAddress",
apiKey = "yourMailChimpApiKey";
// mailchimp options
var options = {
url: url.parse('https://'+datacenter+'.api.mailchimp.com/3.0/lists/'+listId+'/members/'+crypto.createHash('md5').update(email).digest('hex')),
headers: {
'Authorization': 'authId '+apiKey // any string works for auth id
},
json: true,
body: {
email_address: email,
status_if_new: 'pending', // pending if new subscriber -> sends 'confirm your subscription' email
status: 'subscribed',
merge_fields: {
FNAME: "subscriberFirstName",
LNAME: "subscriberLastName"
},
interests: {
MailChimpListGroupId: true // if you're using groups within your list
}
}
};
// perform update
request.put(options, function(err, response, body) {
if (err) {
// handle error
} else {
console.log('subscriber added to mailchimp list');
}
});

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).