send push notification using lambda with aws sns for single device - amazon-sns

I did lot rnd for send push (ios) using aws SNS. I manually create a platform application and then add deviceToken and then push. It works well.
But I want to add the device to application Platform in lambda runtime and send push to that device token. Can any help me? Thanks in advance.

function sendPushMessage(deviecToken, pushMessage)
{
var SNS = require('sns-mobile'),EVENTS = SNS.EVENTS;
var SNS_KEY_ID = 'AWS_USER_AWSAccessKeyId',
SNS_ACCESS_KEY = 'AWS_USER_AWSSecretKey',
IOS_ARN = "SNS_APPLICATION_ARN";
var iosApp = new SNS({
platform: SNS.SUPPORTED_PLATFORMS.IOS,
region: 'us-west-1',
apiVersion: '2010-03-31',
accessKeyId: SNS_ACCESS_KEY,
secretAccessKey: SNS_KEY_ID,
platformApplicationArn: IOS_ARN,
sandbox: true
});
// Add a user, the endpointArn is their unique id
// endpointArn is required to send messages to the device
iosApp.addUser(deviecToken, JSON.stringify({
some: 'extra data'
}), function(err, endpointArn) {
if (err) {
// callback(null, err);
}
else{
let endpp = endpointArn;
// Send a simple String or data to the client
iosApp.sendMessage(endpp, pushMessage, function(err, messageId) {
if (err) {
// callback(null, err);
}
else{
// callback(null, messageId);
}
});
}
});
}
let response;
let test = (event, context, callback) => {
let deviceToken = "YOUR DEVICE TOKEN";
let apnPayload = { aps: { alert: { title: "Hello", body: "This is the content of our push notification." }, badge: 6 } };
let msg = {
"APNS_SANDBOX": JSON.stringify(apnPayload)
};
sendPushMessage(deviceToken, msg);
};
module.exports = test;
Note : First you have to " npm install sns-mobile " this package. Then create test lambda and copy paste this code. i m using this code and working well.

Related

Expo Push Notifications Generating Duplicate Tokens

SDK Version: 37
Platforms(Android/iOS/web/all): all
Every time I run await Notifications.getExpoPushTokenAsync(); the same token is generated. The token looks like: ExponentPushToken[NgTr99YO5fy0EQM4R]. I am able to get push notifications to this token so I know it is formatted correctly, I am just confused as to why it keeps pushing the same token to me when it should generate a new one. What am I missing?
const registerForPushNotificationsAsync = async () => {
if (Constants.isDevice) {
const {status: existingStatus} = await Permissions.getAsync(
Permissions.NOTIFICATIONS
);
let finalStatus = existingStatus;
if (existingStatus !== "granted") {
const {status} = await Permissions.askAsync(Permissions.NOTIFICATIONS);
finalStatus = status;
}
if (finalStatus !== "granted") {
return;
}
token = await Notifications.getExpoPushTokenAsync();
} else {
alert("Must use physical device for Push Notifications");
}
if (Platform.OS === "android") {
Notifications.createChannelAndroidAsync("default", {
name: "default",
sound: true,
priority: "max",
vibrate: [0, 250, 250, 250],
});
}
return token;
};
followed this documentation:
https://docs.expo.io/guides/push-notifications/
My mistake. The duplicate tokens were being created based off of what device i was using to create a new token. In my case I was making multiple profiles on the same device so I was receiving the same token for each profile which was throwing me off.
All is working as it should be.

Send email when user is created on firestore using Cloud Functions

I'm trying to send the email verification link after the user is created on my flutter app, but the email isn't sent and in my Cloud Functions Log I'm receiving the message when I deploy:
{"#type":"type.googleapis.com/google.cloud.audit.AuditLog","status":{"code":9,"message":"FAILED_PRECONDITION"},"authenticationInfo":{"principalEmail":"*************"},"requestMetadata":{"callerIp":"186.216.140.62","callerSuppliedUserAgent":"FirebaseCLI/6.5.0,gzip(gfe),gzip(gfe)","requestAttributes":{"time":"2019-03-29T23:21:10.130Z","auth":{}},"destinationAttributes":{}},"serviceName":"cloudfunctions.googleapis.com","methodName":"google.cloud.functions.v1.CloudFunctionsService.UpdateFunction","authorizationInfo":[{"permission":"cloudfunctions.functions.update","granted":true,"resourceAttributes":{}},{"resource":"projects/pppppp-9800a/locations/us-central1/functions/sendVerificationEmail","permission":"cloudfunctions.functions.update","granted":true,"resourceAttributes":{}}],"resourceName":"projects/pppppp-9800a/locations/us-central1/functions/sendVerificationEmail","request":{"#type":"type.googleapis.com/google.cloud.functions.v1.UpdateFunctionRequest","function":{"labels":{"deployment-tool":"cli-firebase"},"eventTrigger":{"eventType":"providers/cloud.firestore/eventTypes/document.create","resource":"projects/pppppp-9800a/databases/(default)/documents/users/{userId}","service":"firestore.googleapis.com"},"sourceUploadUrl":"https://storage.googleapis.com/gcf-upload-us-central1-dc1829cf-3a07-4951-be81-1a15f892ed8d/8ea3f162-c860-4846-9064-04a855efca2f.zip?GoogleAccessId=service-73683634264#gcf-admin-robot.iam.gserviceaccount.com&Expires=1553903464&Signature=******************","name":"projects/pppppp-9800a/locations/us-central1/functions/sendVerificationEmail"}}}
My code:
exports.sendVerificationEmail = functions.firestore.document('users/{userId}').onCreate((snap, context) => {
const user = snap.data();
console.log("----------------------");
console.log("user created: " + user.uidColumn);
admin.auth().generateEmailVerificationLink(user.email).then((link) => {
console.log("**********" + link);
sendVerificationEmail(user.emailColumn, link);
return 0;
}).catch(e => {
console.log(e);
})
return 0;
});
function sendVerificationEmail(email, link) {
var smtpConfig = {
host: 'smtp.gmail.com',
port: 465,
secure: true, // use SSL
auth: {
user: 'myappemail#gmail.com',
pass: 'password'
}
};
var transporter = nodemailer.createTransport(smtpConfig);
var mailOptions = {
from: "qeaapp#gmail.com", // sender address
to: email, // list of receivers
subject: "Email verification", // Subject line
text: "Email verification, press here to verify your email: " + link,
html: "<b>Hello there,<br> click here to verify</b>" // html body
};
transporter.sendMail(mailOptions, function (error, response) {
if (error) {
console.log(error);
} else {
console.log("Message sent: " + response.message);
}
return 0;
});
return 0;
}
When I the the command firebase deploy I get the message functions: failed to update function sendVerificationEmail
HTTP Error: 400, Change of function trigger type or event provider is not allowed
I'm new in JS and I don't know what these erros mean
Delete your first function called sendVerificationEmail, then redeploy. It looks like you maybe initially deployed it as something other than a Firestore trigger.

Using IBM Watson Text-to-Speech with Firebase Cloud Functions?

I'm trying to use set up a Firebase Cloud Function to access IBM Watson Text-to-Speech. The problem is writing the returned audiofile to my Firestore database.
This test to return the list of voices worked, logging the response to the Functions log:
exports.test = functions.firestore.document('IBM_Watson_Token/Test_Value').onUpdate((change, context) => {
var textToSpeech = new TextToSpeechV1({
username: 'groucho',
password: 'swordfish'
});
return textToSpeech.listVoices(null, function(error, voices) {
if (error) {
console.log(error);
} else {
console.log(JSON.stringify(voices, null, 2));
}
});
});
Here is the documentation example Node code for returning an audiofile and writing it to the server:
var TextToSpeechV1 = require('watson-developer-cloud/text-to-speech/v1');
var fs = require('fs');
var textToSpeech = new TextToSpeechV1({
username: '{username}',
password: '{password}'
});
var synthesizeParams = {
text: 'Hello world',
accept: 'audio/wav',
voice: 'en-US_AllisonVoice'
};
// Pipe the synthesized text to a file.
textToSpeech.synthesize(synthesizeParams).on('error', function(error) {
console.log(error);
}).pipe(fs.createWriteStream('hello_world.wav'));
Firebase doesn't allow writing files to the server using fs, you have to write to a Firestore database. I changed the last line of the example code to write to Firestore, using a promise:
exports.test = functions.firestore.document('IBM_Watson_Token/Test_Value').onUpdate((change, context) => {
var textToSpeech = new TextToSpeechV1({
username: 'groucho',
password: 'swordfish'
});
var synthesizeParams = {
text: 'Hello world',
accept: 'audio/wav',
voice: 'en-US_AllisonVoice'
};
return textToSpeech.synthesize(synthesizeParams).on('error', function(error) {
console.log(error);
}).then(function (audiofile) {
admin.firestore().collection('IBM_Watson_Token').doc('hello_world').set({
'audiofile': audiofile
})
})
.catch(function (error) {
console.log(error);
});
});
The error message was
TypeError: textToSpeech.synthesize(...).on(...).then is not a function
How do I save the audiofile that comes back from Watson to Firestore?
That would be because the synthesize method is not returning a promise. You will need to use a callback construct that looks like
textToSpeech.synthesize(params, function (err, body, response) {
if (err) {
...
} else {
// body is the audio
...
}
});

Firebase Callable function with JWT Authentication and Google Sheets V4 API

I want to implement firebase callable function with JWT Authentication and fetching data from Google Sheet, using Google Sheets V4 API.
For test I tried to use Example Spreadsheet but Sheets API not activated for that Spreadsheet and I cloned it on my own drive and use it for testing.
References:
My code based on solution described in this question How to use Google sheets API while inside a google cloud function and Accessing Google APIs using Service account in Node.JS
Also I have got two important information: "Service Account".json and API Key. I save API Key in api_key.json but didn't find examples how to use it with Google Sheets V4 API:
{
key: "xxxxxx"
}
test() callable function which doesn't require any authentication works fine:
exports.test = functions.https.onCall((data, context) => {
return { text: data.text };
});
Calling test() function somewhere on client (in Browser):
function getTest() {
console.log("clicked getTest()");
var test = firebase.functions().httpsCallable('test');
test({text: '12345'}).then(function(result) {
console.log(result);
}).catch(function(error) {
console.log(error.code);
console.log(error.message);
});
}
Calling getData() somewhere on client (in Browser):
function requestData() {
console.log("clicked requestData()");
//https://firebase.google.com/docs/functions/callable
//getData() function described in functions/index.js
var getData = firebase.functions().httpsCallable('getData');
getData(null).then(function (result) {
// Read result of the Cloud Function.
console.log(result); //<------- Expected rows from Spreadsheet????
}).catch(function(error) {
console.log(error.code);
console.log(error.message);
});
}
**Thank you, F10. I corrected code.
index.js:
'use strict'
const functions = require('firebase-functions');
const { google } = require('googleapis');
var serviceAccount = require("./credentials/owner-service-account-gcloud.json");
function getJwt() {
// Define the required scopes.
var scopes = [
'https://www.googleapis.com/auth/spreadsheets'
];
return new google.auth.JWT(
serviceAccount.client_email,
null,
serviceAccount.private_key,
scopes
);
}
function getSpreadsheetDate(jwt) {
return new Promise((resolve, reject) => {
jwt.authorize((error, access_token) => {
if (error) {
console.log('Error in jwt.authorize: ' + error);
reject(error);
} else {
// access_token ready to use to fetch data and return to client
const sheets = google.sheets({ version: 'v4', access_token });
// set auth as a global default:
google.options({ auth: jwt }); //<----------------------
const request = {
auth: jwt,
spreadsheetId: 'xxxx',
range: 'Class Data!A2:E', //'Class Data!A2:E',
}
sheets.spreadsheets.values.get(request, (err, response) => {
console.log("inside: sheets.spreadsheets.values.get() -------------------------------");
if (err) {
console.log('The Sheets API returned an error: ' + err);
//The API returned an error: Error: API key not valid. Please pass a valid API key.
reject(err);
};
try {
var numRows = response.data.values ? response.data.values.length : 0;
console.log('%d rows retrieved.', numRows);
console.log("response.data:-------------------------------");
console.log(response.data.values);
resolve(response.data.values);
} catch (err) {
console.log("Error processing Sheets API response: " + err);
reject(err);
}
})
}
})
})
}
exports.getData = functions.https.onCall((data, context) => {
console.log("getData()---------------------------");
if (!context.auth) {
throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' + 'while authenticated.');
} else {
console.log("context.auth ------------ OK");
const uid = context.auth.uid;
console.log(uid);
var jwt = getJwt();
console.log("getJwt() --------------- OK");
return getSpreadsheetDate(jwt); //<------------ Requested Spreadsheet's Data
}
})
exports.test = functions.https.onCall((data, context) => {
return { text: data.text };
});
There's a solution that uses googleapis instead of the auth library to do the authentication with JWT. Regarding your token inquiries, you could check the OAuth 2.0 for client-side web applications documentations, which explains the steps to do the authentication.

Firebase increase badge count with iOS

I'm developing an app with Firebase and I implemented push notifications right. And now I'm trying to show badge icon but I can't find a good information to do that. I read I should work on the server side and the example code is something like this.
"aps" :
{
"alert" : "Your notification message",
"badge" : badgecount ,
"sound" : "bingbong.aiff"
}
But I don't know where to add the code in my function.
This is how my function looks like:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.pushNotifications = functions.database.ref('/messages/{messageId}')
.onCreate(event => {
const data = event.data;
const fromId = data.fromId;
const toId = data.toId;
const message = data.message;
console.log(fromId + ' sent a message to' + toId);
return admin.database().ref('/users/' + fromId).once('value', snapshot => {
var user = snapshot.val();
var payload = {
notification: {
title: user.username,
body: message
}
}
admin.messaging().sendToDevice(user.fcmToken, payload)
.then(function(response) {
// See the MessagingDevicesResponse reference documentation for
// the contents of response.
console.log("Successfully sent message:", response);
})
.catch(function(error) {
console.log("Error sending message:", error);
});
})
Can someone give me an advice how to do this?
The "apns" object goes in the payload object as a sibling to notification:
var payload = {
notification: {
title: user.username,
body: message
},
apns: {
// badge and other ios only data here here
}
}
I would also suggest returning the admin.messaging() method: return admin.messagins().sendToDevice().ect. It might not be required, but Firebase suggests returning all thenable references.

Resources