Firebase Cloud Message and Cloud Function Error - firebase

I´m trying to use Firebase Cloud Message to send notifications through
Firebase Cloud Functions.
So i´ve deployed a function on Cloud Functions which calls the function admin.sendMessageToTopic(),
but I´m getting the warning:
"Billing account not configured. External network is not accessible and quotas are severely limited. Configure billing account to remove these restrictions"
after this, the function proceeds with no error, but the Cloud Message doesn´t send the Message.
Here is the code which i´m getting this error:
exports.sendMessageToTopic = functions.https.onRequest((req, res) => {
const topic = req.query.topic
const title = req.query.title
const body = req.query.body
const message = {
data: {
title: title,
body: body
}
}
admin.messaging().sendToTopic(topic , message)
.then(result => {
console.log("sendMessageToTopic ok:", result)
res.send("sendMessageToTopic ok")
})
.catch(error => {
console.log("sendMessageToTopic ERROR:", error)
res.send("sendMessageToTopic ERROR: " + error)
})
})
If you guys know what should be the problem, please share the solution with us.
Thank you guys.

Related

solc inside firebase functions causes deployment error

I need to compile a smart contract inside a firebase function. I am using solc "solc": "^0.8.13", in my package.json.
Code of the firebase function responsible to create the contact is;
const functions = require("firebase-functions");
const admin = require('firebase-admin');
const solc = require('solc');
const fs = require("fs");
const Web3 = require('web3');
exports.createSC = functions.https.onCall((data, context) => {
if (!context.auth) return { data: data, status: 'error', code: 401, message: 'Not signed in' }
return new Promise((resolve, reject) => {
admin.auth().getUser(data.owner)
.then(userRecord => {
//below function compiles the contract and returns abi/binary code etc
let contract = instantiateContract('sources/SnaphashToken.sol');
//use web3 to actually deploy contract
let web3;
//...code emitted...
resolve(contractDeployResult)
})
.catch(error => {
console.error('Error fetching user data:', error)
reject({ status: 'error', code: 500, error })
})
});
})
this works perfectly well when deployed on functions simulator locally but when deployed on firebase cloud I get this exception;
i functions: updating Node.js 16 function ethereum-createSC(us-central1)...
Function failed on loading user code. This is likely due to a bug in the user code. Error message: Error: please examine your function logs to see the error cause: https://cloud.google.com/functions/docs/monitoring/logging#viewing_logs. Additional troubleshooting documentation can be found at https://cloud.google.com/functions/docs/troubleshooting#logging. Please visit https://cloud.google.com/functions/docs/troubleshooting for in-depth troubleshooting documentation.
Functions deploy had errors with the following functions:
ethereum-createSC(us-central1)
When I comment out const solc = require('solc') in my function, it deploys without problems. I really need to be able to deploy smart contracts after modifying based on user input and would appreciate a help on it
I found out that the subject function was causing deployment error because of Error: memory limit exceeded. I was able to see that after I checked detailed logs of the functions with firebase functions:log
2022-05-27T17:09:27.384860094Z E ethereum-createNft: Function cannot be initialized. Error: memory limit exceeded.
In order to fix this issue, I increased memory for the function from default 256MB to 1GB and timeoutSeconds from default 60 seconds to 120 seconds
exports.createNft = functions.runWith({memory:'1GB',timeoutSeconds:120}).https.onCall((data, context) => {
..code here..
});
And then deployment was successful

FirebaseMessagingError: Invalid registration token provided

I am trying to send push notifications to another iOS device using firebase cloud functions but I receive the following error below when attempting to do so:
'FirebaseMessagingError: Invalid registration token provided. Make sure it matches the registration token the client app receives from registering with FCM.'
This is the registration token I am trying to send to 6e04bb35f06e2d981d5603bbd229eeab5ee5649f6af7b4ecc3894be6ad1574d7 which is the same token I have saved in my realtime database:
Below is my onCreate function:
exports.onMessageCreate = functions.database.ref('/messages/{chatId}/{messageId}').onCreate((snapshot, context) => {
const chatId = context.params.chatId;
const receiverId = chatId.replace(context.auth.uid, '');
const root = snapshot.ref.root;
return admin.database().ref(`/users/${receiverId}/regToken`).once('value').then(tokenSnap => {
var regTokenRef = tokenSnap.val();
const payload = {
notification: {
title: 'title',
body: snapshot.val().text,
}
};
const options = { priority: "high" };
return admin.messaging().sendToDevice(regTokenRef, payload, options).then(function(response){
console.log("Successfully sent message: ", response);
console.log(response.results[0].error);
}).catch(function(error) {
console.log("Error sending message: ", error);
});
});
});
Do you know what may be causing this error? I am not too sure what I need to check here. Is the format wrong here? Does it need to be in quotes? I have looked at other links but they haven't really helped.
I am importing '#react-native-community/push-notification-ios' to generate the token. I think this may be the problem. I was having issues to use the messaging from firebase. Is this the issue?
Please see below the didFinishLaunchingWithOptions method updated in my AppDelegate.m file. Have I placed the below code correctly? When this is added it is causing my app to appear blank when launching the simulator with the FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app).? However, when removed my app launches but with still has the FirebaseError.
if ([FIRApp defaultApp] == nil) {
[FIRApp configure];
}
#react-native-community/push-notification-ios is not able to generate an FCM token, only APN token: https://github.com/react-native-push-notification-ios/push-notification-ios/issues/117
If you want to use firebase, you need to generate the token from the messaging package of firebase to have a FCM one.

Firebase functions run in one firebase project but giving internal error in the other

I have two firebase accounts one used for development(D) and the other for production(P). My development(D) firestore and functions run on us-central1. On production(P) firestore location is asia-south1 and functions run on us-central1
My firebase functions run properly in development (D) but are giving me the following error in production. Further, when I check the logs on the firebase functions console, there does not seem to be any activity. It appears as if the function has not been called.
Error returned by firebase function is :
Function call error Fri Apr 09 2021 09:25:32 GMT+0530 (India Standard Time)with{"code":"internal"}
Further the client is also displaying this message :
Access to fetch at 'https://us-central1-xxx.cloudfunctions.net/gpublish' from origin 'https://setmytest.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. zone-evergreen.js:1052 POST https://us-central1-xxx.cloudfunctions.net/gpublish net::ERR_FAILED
Here is the code from my angular app calling the function -
const process = this.fns.httpsCallable("gpublish");
process(data).subscribe(
(result) => {
console.log("function responded with result: " + JSON.stringify(result));
},
(err) => {
const date1 = new Date();
console.log("Function call error " + date1.toString() + "with" + JSON.stringify(err));
});
Here are the functions -
index.ts
import { gpublish } from "./gpublish/gpublish";
import { sendEmail } from "./sendEmail";
export {gpublish,sendEmail };
gpublish.ts
import * as functions from "firebase-functions";
const fs = require("fs");
const { google } = require("googleapis");
const script = google.script("v1");
const scriptId = "SCRIPT_ID";
const googleAuth = require("google-auth-library");
import { admin } from "../admin";
const db = admin.firestore();
export const gpublish = functions.https.onCall(async (data: any, res: any) => {
try {
const googleTest = data.test;
console.log("Publishing to google test of name " + googleTest.testName);
// read the credentials and construct the oauth client
const content = await fs.readFileSync("gapi_credentials.json");
const credentials = JSON.parse(content); // load the credentials
const { client_secret, client_id, redirect_uris } = credentials.web;
const functionsOauth2Client = new googleAuth.OAuth2Client(client_id,client_secret, redirect_uris); // Constuct an auth client
functionsOauth2Client.setCredentials({refresh_token: credentials.refresh_token}); // Authorize a client with credentials
// run the script
return runScript(functionsOauth2Client,scriptId,JSON.stringify(googleTest)
).then((scriptData: any) => {
console.log("Script data is" + JSON.stringify(scriptData));
sendEmail(googleTest, scriptData);
return JSON.stringify(scriptData);
});
} catch (err) {
return JSON.stringify(err);
}
});
function runScript(auth: any, scriptid: string, test: any) {
return new Promise(function (resolve, reject) {
script.scripts
.run({auth: auth,scriptId: scriptid, resource: {function: "doGet", devMode: true,parameters: test }
})
.then((respons: any) => { resolve(respons.data);})
.catch((error: any) => {reject(error);});
});
}
I have changed the service account key and google credentials correctly when deploying the functions in development and in production.
I have tried many things including the following:
Enabling CORS in Cloud Functions for Firebase
Google Cloud Functions enable CORS?
The function is running perfectly in Development firebase project but not in Production firebase project. Please help!
You need to check that your function has been deployed correctly.
A function that doesn't exist (404 Not Found) or a function that can't be accessed (403 Forbidden) will both give that error as the Firebase Function is never executed, which means the correct CORS headers are never sent back to the client.

Flutter: Firebase Pushnotification On Data Change

After getting the comment, i have deployed this folowing code to my firebase project and it was successfully deploed!.But there is no notifications been send to me.
Please check my Firebase Realtime database Screenshot here for better understanding.
[ITS SOLVED NOW:IT WILL SEND NOTIFICATIONS TO ONLY ONE ID ie My Admin Device]
WORKING CODE:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firbase);
exports.codeformypeople = functions.database.ref('items/{id}').onWrite(evt => {
const payload = {
notification: { title: 'New Customer Requested', body: 'Touch to Open The App', badge: '1', sound: 'default', }
};
const token ="Lsn-bHfBWC6igTfWQ1-h7GoFMxaDWayKIpWCrzC";//replace with ur token
if (token) {
console.log('Toke is availabel .');
return admin.messaging().sendToDevice(token, payload);
} else {
console.log('token error');
}
});
[
SEE THIS VIDEO LINK FOR MORE DETAILS
note:If your app is opened and minmized then it will show notification,but if the app is opened and you are using,or if the app is terminated force close then it will not work!!
You can use firebase cloud function to trigger notification. Here is snippet of cloud functions which i am using to trigger notification:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.pushNotification = functions.database.ref('/Notifications/{pushId}')
.onWrite(( change,context) => {
console.log("Push Notification event triggered");
var request = change.after.val();
var payload = {
data:{
username: request.userName,
}
};
admin.messaging().sendToDevice(request.userTokenId, payload)
.then(function(response){
console.log("Successfully sent message: ",response);
console.log(response.results[0].error);
})
.catch(function(error){
console.log("Error sending message: ", error)
})
})
Below i have provided my notification structure, you can see below.This function will trigger if any new data is being pushed in database notification node. To see what is output/error you are getting when this function is trigger go to firebase admin panel > Functions > Logs.
You have deployed function code perfectly, but you forgot to add refresh tokenId in your database as you can see in above picture i am saving userTokenId in my database and in function admin.messaging().sendToDevice(request.userTokenId, payload) i am using that tokenId, this tokenId is used to send notification to particular device, you can get this tokenId using FirebaseInstanceId.getInstance().getToken() and save this in your fbproject1 > items database sturcture. please refer this & this

Botbuilder doesn't respond after sending 'accepted' code when using cloud functions

I'm using Dialogflow as the handler for my botbuilder endpoint, which is a Azure Bot Service bot, and the handler is deployed on a Firebase Cloud Function, but for every botframework request I make, the function returns a 202 (that's the default behaviour of botbuilder I believe), and the function stops working in the middle of the code.
I saw in this response from Frank van Puffelen that the functions may halt if there's a response from the function.
Cloud Functions for Firebase: serializing Promises
Is this enough to stop my function from executing? If so, is there a way to stop this from happening?
Edit: I'm using the Universal Bot to setup the callback for the messages.
const bot = new builder.UniversalBot(this.connector, botFrameworkCallback)
.set('storage', new builder.MemoryBotStorage());
And here's the botFrameworkCallback:
const botFrameworkCallback = (session) => {
const message = session.message.text;
const userRef = new UserRef('user');
let userInfo;
userRef
.get()
.then((userInformation) => {
console.log('user information', userInformation);
userInfo = userInformation;
const userData: IUser = {
...userInfo,
ref: userRef
};
return makeDialogflowRequest(userData, message);
})
.then((intentResult: any) => {
console.log('intent result', intentResult);
const response = intentResult.answer;
session.send(response);
})
.catch((err) => {
console.log('Error on BotFramework', err);
const response = 'Sorry. An error happened while getting your response.';
session.send(response);
});
}
The whole integration part is there to give user specific responses, so this code does a lot of API requests, like Firestore ones, the Dialogflow one, and because of that we've set it up this way.

Resources