Can you trigger a Google Cloud Functions via firebase event without a server? - firebase

I will be implementing an elastic search index alongside my firebase application so that it can better support ad-hoc full text searches and geo searches. Thus, I need to sync firebase data to the elastic search index and all the examples require a server process that listens for firebase events.
e.g. https://github.com/firebase/flashlight
However, it would be great if I can just have a google cloud function triggered by an insert in a firebase node. I see that google cloud functions has various triggers: pub sub, storage and direct... can any of these bridge to a firebase node event without an intermediate server?

firebaser here
We just released Cloud Functions for Firebase. This allows you to run JavaScript functions on Google's servers in response to Firebase events (such as database changes, users signing in and much more).

I believe Cloud Functions for Firebase are what you are looking for.
Here are a few links:
Official Documentation
Intro video
Google Cloud Functions and Firebase (Google Cloud Next '17)

yes, you can trigger a Google Cloud Functions via firebase event without a server.
As per documents,Firebase allows for example you can send notifications using a cloud function when a user write into firebase database.
For that, I had to write a javascript as below
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/articles/{articleId}')
.onWrite(event => {
// Grab the current value of what was written to the Realtime Database.
var eventSnapshot = event.data;
var str1 = "Author is ";
var str = str1.concat(eventSnapshot.child("author").val());
console.log(str);
var topic = "android";
var payload = {
data: {
title: eventSnapshot.child("title").val(),
author: eventSnapshot.child("author").val()
}
};
// Send a message to devices subscribed to the provided topic.
return admin.messaging().sendToTopic(topic, payload)
.then(function (response) {
// See the MessagingTopicResponse reference documentation for the
// contents of response.
console.log("Successfully sent message:", response);
})
.catch(function (error) {
console.log("Error sending message:", error);
});
});

Related

Why I can not connect to Firebase?

I'm trying to connect my app to firebase but the only response I get is not the response json I need from firebase. I included my call to firebase below. Is the url not correct? The response I'm getting back is not the json object made with firebase that I created.
``
<script>
(async function call () {
console.log("hello")
const endpoint = url
console.log(endpoint)
async function initiation () {
const result = await fetch(endpoint, {mode: "no-cors"})
const data = await result
console.log(data)
}
initiation()
})()
</script>
``
is your database in us-central1?
according to documentation [1] "the form https://<"databaseName">.firebaseio.com (for us-central1 databases) or https://<"databaseName"><"region">.firebasedatabase.app (for databases in all other locations)."
If its in another region you should try with https://<"databaseName"><"region">.firebasedatabase.app
[1]https://firebase.google.com/docs/database/web/start#initialize_the_javascript_sdk
The structure within your code seems odd, if you are implementing the CDN you need to initiate your app with your project credentials, right now you are only accessing a real-time database as a public request and does not provide any additional validators as the database is most likely to have Security Rules enabled.
To request data from the endpoint, you need to also include a .json at the end of the URL https://[PROJECT_ID].firebaseio.com/users/jack/name.json
Source: https://firebase.google.com/docs/reference/rest/database#section-get

How can scheduled Firebase Cloud Messaging notifications be made outside of the Firebase Console?

Inside the Firebase Console, under the Cloud Messaging view, users are able to create test notifications. This functionality also allows you to schedule the time at which the notification will send to a device or set of devices.
Is it possible to create and send scheduled FCM notifications to specific devices by using firebase cloud functions and the Firebase Admin SDK? Is there an alternative way to solving this?
The current way that I send scheduled messages to users is like so:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const schedule = require('node-schedule');
admin.initializeApp();
exports.setScheduledNotification = functions.https.onRequest(async (req, res) => {
const key = req.query.notification_key;
const message = {
notification: {
title: 'Test Notification',
body: 'Test Notification body.'
}
};
var currentDate = new Date();
var laterDate = new Date(currentDate.getTime() + (1 * 60000));
var job = schedule.scheduleJob(key, laterDate, () => {
const snapshot = admin.messaging().sendToDevice(key, message);
});
return res.status(200).send(`Message has been scheduled.`);
});
First of all, I am unsure how node-schedule interacts with firebase cloud functions. The logs appear that the function terminates very quickly which I would think would be correct. The longer the operation runs the more costly it is in our firebase bills. The notification does still run on a scheduled time though. I'm confused on how that all is working behind the scenes.
Secondly, I am having issues canceling these scheduled notifications. The notifications will most likely be on a 2hr timed schedule from the point it gets created. Before the 2hrs is up, I'd like the have the ability to cancel/overwrite the notification with an updated scheduled time.
I tried this to cancel the notification and it failed to find the previously created notification. Here is the code for that:
exports.cancelScheduledNotification = functions.https.onRequest(async (req, res) => {
const key = req.query.notification_key;
var job = schedule.scheduledJobs[key];
job.cancel();
return res.status(200).send(`Message has been canceled.`);
});
Is it possible to tap into the scheduling functionality of firebase cloud messaging outside of the firebase console? Or am I stuck with hacking my way around this issue?
A Cloud Function can run for a maximum of 9 minutes. So unless you're using node-schedule for periods shorter than that, your current approach won't work. Even if it would work, or if you are scheduling for less than 9 minutes in advance, using this approach is very uneconomic as you'll be paying for the Cloud Functions for all this time while it's waiting.
A more common approach is to store information about what message you want to be delivered to whom at what time in a database, and then use regular scheduled functions to periodically check what messages to send. For more on this, see these previous questions:
Firebase scheduled notification in android
How to schedule push notifcations for react native expo?
Schedule jobs in Firebase
Ionic: Is it possible to delay incoming push FCM push notification from showing to my device until a specific time
Cloud Functions for Firebase trigger on time?
How to create cron jobs dynamically in firebase
A recent improvement on this is to use the Cloud Tasks API to programmatically schedule Cloud Functions to be called at a specific time with a specific payload, and then use that to send the message through FCM. Doug Stevenson wrote a great blog post about this here: How to schedule a Cloud Function to run in the future with Cloud Tasks (to build a Firestore document TTL). While the post is about deleting documents at a certain time, you can combine it with the previous approach to schedule FCM messages too.
Scheduling of tasks is now also described in the documentation on enqueueing functions with Cloud Tasks
A final option, and one I'd actually recommend nowadays, is to separate the delivery of the message from the display of the notification.
Display of data messages (unlike notification messages) is never handled by the system, and always left to your application. So you can deliver the FCM data message straight away that then contains the time to display the message, and then wake the device up to display the message (often called a local notification) at that time.
To make Frank's answer more tangible, I am including some sample code below for scheduled cloud functions, that can help you achieve the 'scheduled FCM notifications'.
You should store the information required to send your notification(s) in Firestore (e.g. the when-to-notify parameter and the FCM token(s) of the users you want to send the notification to) and run a cloud function every minute to evaluate if there is any notification that needs to be delivered.
The function checks what Firestore documents have a WhenToNofity parameter that is due, and send the notifications to the receiver tokens immediately. Once sent, the function sets the boolean 'notificationSent' to true, to avoid that the users receive the same notification again on the next iteration.
The code below achieves just that:
const admin = require('firebase-admin');
admin.initializeApp();
const database = admin.firestore();
exports.sendNotification = functions.pubsub.schedule('* * * * *').onRun(async (context) => {
//check whether notification should be sent
//send it if yes
const query = await database.collection("experiences")
.where("whenToNotify", '<=', admin.firestore.Timestamp.now())
.where("notificationSent", "==", false).get();
query.forEach(async snapshot => {
sendNotification(snapshot.data().tokens);
await database.doc('experiences/' + snapshot.id).update({
"notificationSent": true,
});
});
function sendNotification(tokens) {
let title = "INSERT YOUR TITLE";
let body = "INSERT YOUR BODY";
const message = {
notification: { title: title, body: body},
tokens: tokens,
android: {
notification: {
sound: "default"
}
},
apns: {
payload: {
aps: {
sound: "default"
}
}
}
};
admin.messaging().sendMulticast(message).then(response => {
return console.log("Successful Message Sent");
}).catch(error => {
console.log(error);
return console.log("Error Sending Message");
});
}
return console.log('End Of Function');
});
If you're unfamiliar with setting up cloud functions, you can check how to set them up here. Cloud functions require a billing account, but you get 1M cloud invocations per month for free, which is more than enough to cover the costs of this approach.
Once done, you can insert your function in the index.js file.

Is there cloud functions that trigger if database changes and send notification to users subscriber to 'topics'

I am working in an android app project for my college minor project. Everything is working but now i want to add a notification feature, i.e whenever a admin posts a notice every user subscriber to that topic gets notification, i tried to follow different tutorials and documents but since i have no programming background in js/nodejs/php i couldn't understand the cloud functions.
Can anyone write the functions or lead me to the answer?
i want the function to be triggered when a new notice is added inside /Notice and send notification to all users subscribe to Notice..
i wrote the following code, after some study,
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotices =
functions.database.ref('/Notices/{nID}').onCreate((event) => {const data =
event.data;
if(!data.changed()){
console.log('Nothing changed');
return;
}else{
console.log(data.val());
}
const payLoad = {
notification:{
title: 'Message received',
body: 'You received a new message',
sound: "default"
}
};
const options = {
priority: "high",
timeToLive: 60*60*2
};
return admin.messaging().sendToTopic("bctb", payLoad, options);});
and got the error in console of firebase,what am i doing wrong here,
TypeError: Cannot read property 'changed' of undefined
at exports.sendNotices.functions.database.ref.onCreate
(/user_code/index.js:8:13)
at cloudFunctionNewSignature (/user_code/node_modules/firebase-
functions/lib/cloud-functions.js:105:23)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-
functions.js:135:20)
at /var/tmp/worker/worker.js:770:24
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
Since you are not familiar with the Firebase Cloud Functions, I recommend you first go through official docs here, because without going through the basics you won't understand how they work and then go through Firebase Cloud Messaging (FCM) docs here. Once you get to know how both the service work it'll be a lot easier for you to understand and write your own cloud function. For your ease here is how your function should be like.
You can do this by simply creating an onCreate trigger function. So it will look something like:
exports.SendNotification = functions.database.ref('/Notice/{nid}')
.onCreate((snapshot, context) => {
//Your notification code here
}
Here nid is the notice id that is just created. Firebase will automatically get this id. And for sending the notification you can use Firebase cloud messaging (FCM). In this cloud function you can create a notification payload.
//send notification
const payload = {
data:{
title: "New notice has been added!",
}
};
Now you can send this notification to the app using:
admin.messaging().sendToDevice(instID, payload);
Here, instID is the instance ID. Each app installed has a unique instance ID. For sending to multiple devices you'll have to wrap the code line above in an loop to send notifications to all of the subscribed users. For this you need instance IDs of all the subscribed users.
"I hear and I forget, I see and I remember, I do and I understand"
Best of luck.

Dialogflow fullfilment on firebase function if ask from telegram

I wrote function which work on firebase function and which take an answer on request if request come from the dialog console or the Google Assistant emulator. But if I ask from Telegram this function doesn't work.
Answer like Say that one more time? or if I filled the form Responses on web I have this response.
How connect firebase function with Telegram?
'use strict';
const {
dialogflow,
Permission,
Suggestions,
BasicCard,
} = require('actions-on-google');
const firebase = require('firebase');
const functions = require('firebase-functions');
const app = dialogflow({debug: true});
app.intent('simple word', (conv) => {
conv.ask(`it's ok`);
});
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
The problems is that you're using the actions-on-google library, which is specifically designed to send results to the Assistant.
If you want to be able to send results to Telegram, you need to use the dialogflow-fulfillment library, which handles things slightly differently.

Integrate Firebase with 3rd party API

I'd like to integrate my firebase project with some 3rd party API's, like the twitter API.
3rd party API
The following code will listen to new tweets containing the certain text 'little rocket man':
var Twitter = require('twitter');
// setup new twitter client
var client = new Twitter({
consumer_key: '',
consumer_secret: '',
access_token_key: '',
access_token_secret: ''
});
// open new twitter stream
let stream = this.client.stream('statuses/filter', { track: 'little rocket man' });
stream.on('data', (event: any) => {
let tweetText = event && event.text; // this should be written to the firebase db
});
Firebase Cloud Functions
The following firebase cloud functions listens to incoming HTTP GET requests on a specific route and saves data back to the firebase db:
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin'; // Firebase Admin SDK
admin.initializeApp(functions.config().firebase);
// this example uses a HTTP trigger, but how can I trigger it whenever new tweets containint 'little rocket man' are detected??
exports.addMessage = functions.https.onRequest((req, res) => {
const original = req.query.text;
admin.database().ref('/messages').push({original: original}).then(snapshot => {
res.redirect(303, snapshot.ref);
});
});
Question
How can I write the tweets I'm recieving from the twitter client back to the firebase db? If possible, I'd like to run all the code on firebase cloud functions.
Disclaimer:
I'm new to firebase and although googling around for a few hours I wasn't able to find the solution to my problem on the net. I'd like to apologize in advance, should I have overseen it.
You can't use streaming APIs like this in Cloud Functions. A function may only respond to some distinct event, such as an HTTP request, or some change in your database. Functions can't run indefinitely.
If you want to collect tweets that match some query into your database, you can use IFTTT to periodically send them to a function as they become available. I recently finished a small project that does exactly that.

Resources