Firebase Cloud Messaging - getMessaging is not a function - node.js

Trying to send a message from a node.js app in firebase to an android device using code snippets from the firebase website.
https://firebase.google.com/docs/cloud-messaging/android/send-multiple
Keep getting getMessaging is not a function.
My call is await admin.messaging().getMessaging().send(...)
Can't find what is wrong.

The getMessaging() function that you are referring to is a top level function that can be imported from firebase-admin/messaging SDK as shown below:
import { getMessaging } from "firebase-admin/messaging";
This is equivalent of admin.messaging() and both return an instance of Messaging class.
If you are following Firebase documentation to send messages, the code should be:
import { getMessaging } from "firebase-admin/messaging"; // not just "firebase-admin"
const messaging = getMessaging();
await messaging.send(...)
The Admin SDK is not fully modular yet like the the client SDK so rest of the syntax remains same. Also checkout What is the difference between admin.firestore, admin.firestore() and getFirestore()

You're using firebase-admin sdk which does have different syntax. For your use-case, you should instead use:
await admin.messaging().send(...);
For more information, checkout this documentation.

Related

How can I send a Notification via Firebase Cloud Messaging from a cloud function?

The documentation at
https://firebase.google.com/docs/reference/admin/node/firebase-admin.messaging.md#getmessaging
does not explain where the "firebase-admin/messaging" module is. What is the require path to get this module?
for instance
const { getMessaging } = require("firebase-admin/messaging");
does not work.
I also looked into the cloud functions sdk at https://firebase.google.com/docs/reference/functions#functions.pubsub where I see the Message class but no way to send a message.
Finally found it:
const messaging = admin.messaging();
which means that the documentation at https://firebase.google.com/docs/cloud-messaging/send-message?authuser=0 is outdated.

Firebase test auth cloud functions locally

exports.sendWelcomeEmail = functions.auth.user().onCreate((user) => {
console.log(user.uid);
console.log(user.email);
console.log(user.displayName);
});
exports.getUserInfo = functions.https.onCall(async (data, context) => {
// get array of user IDs and returns information (from Users collection)
const userIDs = data.userIDs;
const result = [];
const querySnapData = await admin.firestore().collection("Users").get();
querySnapData.forEach((ele) => {
if (userIDs.indexOf(ele.id) !== -1 && ele.id !== context.auth.uid) {
result.push(ele.data());
}
});
return { res: result };
});
I've got these two functions in my project - one is callable function and the other one is auth trigger functions.
So in my client app, I run
firebase.functions().useFunctionsEmulator('http://localhost:5001');
let getUserInfo = functions.httpsCallable('getUserInfo');
getUserInfo({userIDs: data}).then(res => doSomething);
And to run the cloud functions locally
firebase emulators:start
But it says
functions[sendWelcomeEmail]: function ignored because the auth emulator does not exist or is not running.
So in the client App, getUserInfo works pretty well but can't trigger onCreate.
But I was not able to find any document about auth emulator.
Any link/article/video or answer is appreciated.
The Firebase Emulator Suite currently Cloud Firestore, Realtime Database, Cloud Functions, and Cloud Pub/Sub. It does not yet emulate Firebase Authentication APIs. So any auth calls you make will be executed against the real project that is associated with the emulators.
This also means that your functions.auth.user().onCreate((user) => { Cloud Function will not be triggered in the emulators at the moment. You'll have to deploy it to the servers to test this trigger.
To learn when an auth emulator is available, I recommend keeping an eye on Firebase's release notes, and on the main documentation page for the emulator suite that lists the supported products. You can also follow along more closely on Github, either in the commits, or in this feature request.
firebase recently released the Authentication Emulator, you can check it via the release notes here: https://firebase.google.com/support/releases#october_26_2020, and further guide here: https://firebase.google.com/docs/emulator-suite/connect_auth
So as #Franek van Puffelen wrote above, it is not done yet.
Was able to test auth functions locally like below.
function sendWelcomeEmail(user) {
console.log(user.uid);
console.log(user.email);
console.log(user.displayName);
}
exports.sendWelcomeEmail = functions.auth.user().onCreate((user) => sendWelcomeEmail(user));

What is the difference between Firebase SDK and Firebase SDK for cloud functions?

I don't understand the difference between Firebase SDK and Firebase SDK for cloud functions. I mean, when you run in command line "firebase init" in node.js, node modules will be downloaded to initialize a new project. But if i run "npm install firebase" different node modules appears, with similar names and different contents. So the question is: which SDK should I use to run functions and authentication in the same code? (I got a lot of require error from importing similar things and I don't know how to solve the problem).
Here is the code:
const functions = require('firebase-functions');
var firebase = require('firebase');
firebase.initializeApp();
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
exports.delete = functions.https.onRequest((request, response) => {
console.log("delete");
});
The error says firebase.auth() is not a function, maybe for bad import and I don't know which package I need to import
npm install firebase installs modules to be used in client code that accesses Firebase products such as Firebase Authentication, Realtime Database, Firestore, and Cloud Storage.
npm install firebase-functions install modules to be used when writing backend code to deploy to Cloud Functions.
You're trying to use the Firebase Authentication client side library to listen to auth state changes in Cloud Functions. This isn't going to work, since that auth library only works on web clients.

Node.JS - firebase.auth() is not a function

I'm trying to use firebase Auth on a Node.JS server because Firebase Admin SDK doesn't implement all functions I need. Like firebase.auth.sendPasswordResetEmail(email).
But, when I try to get auth() I get following error:
let auth = fire.auth()
^
TypeError: fire.auth is not a function
My code is very simple:
let admin = require('firebase-admin');
let firebase = require('firebase');
const fire = firebase.initializeApp(config, "firebase");
let auth = fire.auth()
I'm, also, using Firebase Admin SDK for other functions and its auth() works fine.
There is some problem with use regular Firebase SDK on a Node.JS server?
EDIT:
I need both SDK because firebase-admin doesn't have functions like firebase.auth.sendPasswordResetEmail(email) or others.
Also, initializeApp is necessary for select the project in which I would operate.
Try deleting and re-installing node_modules. If the problem persists, you can add Firebase Authentication SDK to your script from the CDN:
<script src="https://www.gstatic.com/firebasejs/6.4.1/firebase-auth.js"></script>.
Refer here for the latest version: https://firebase.google.com/docs/web/setup

Implementing isRequestFromAssistant in Node.js on actions-on-google project fulfillment

I am having trouble implementing the isRequestFromAssistant method to verify requests to my fulfillment webhook. Using Node.js, I instantiate the following variables at the start of my index.js file:
const App = require('actions-on-google').ApiAiApp;
const app = new App({ request, response });
I then use "app" with the .ask and .tell and other methods throughout my functions.
The code I see in the docs for implementing isRequestFromAssistant is:
const app = new ActionsSdkApp({request, response});
app.isRequestFromAssistant('my-project-id')
.then(() => {
app.ask('Hey there, thanks for stopping by!');
})
.catch(err => {
response.status(400).send();
});
If I leave out the first line and use my existing app variable, created with the .ApiAi method instead of the .ActionsSdkApp method, it doesn't work. If I create a new variable App1 and app1 using the .ActionsSdkApp method and change the above code to be app1.isRequestFromAssistant, it also doesn't work. I have tried other variations with no luck.
When I say it doesn't work, I mean I receive a 500 Internal Server Error when I call it. I am hosting it with NGROK currently. I am still a beginner with Node.js, although I have managed to get the other 700 lines of code working just fine, learning mostly from Google searches and reading these forums.
You have a few things going on here which, individually or separately, may be causing the problem.
First - make sure you have the most recent version of the actions-on-google library. The isRequestFromAssistant() function was added in version 1.6.0, I believe.
Second - Make sure you're creating the right kind of App instance. If you're using Dialogflow (formerly API.AI), you should be creating it with something like
const App = require('actions-on-google').DialogflowApp;
const app = new App( {request, response} );
or
const { DialogflowApp } = require('actions-on-google');
const app = new DialogflowApp( {request, response} );
(They both do the same thing, but you'll see both forms in documentation.) You should switch to DialogflowApp from ApiAiApp (which your example uses) to reflect the new name, but the old form has been retained.
If you're using the Actions SDK directly (not using Dialogflow / API.AI), then you should be using the ActionsSdkApp object, something like
const { ActionsSdkApp } = require('actions-on-google');
const app = new ActionsSdkApp({request: request, response: response});
(Again, you'll see variants on this, but they're all fundamentally the same.)
Third - Make sure you're using the right function that matches the object you're using. The isRequestFromAssistant() function is only if you are using the Actions SDK.
If you are using Dialogflow, the corresponding function is isRequestFromDialogflow(). The parameters are different, however, since it requires you to set confirmation information as part of your Dialogflow configuration.
Finally - If you're getting a 500 error, then check your logs (or the output from stderr) for the node.js server that is running. Typically there will be an error message there that points you in the right direction. If not - posting that error message as part of your StackOverflow question is always helpful.
Set the secure (randomly generated) auth header & key values in the dialogflow Fulfillment page, then in nodejs:
if (app.isRequestFromDialogflow("replace_with_key", "replace_with_value")) {
console.log("Request came from dialogflow!");
// rest of bot
} else {
console.log("Request did not come from dialogflow!");
response.status(400).send();
}
Also see: https://developers.google.com/actions/reference/nodejs/DialogflowApp#isRequestFromDialogflow

Resources