I'm trying to do the following thing. I have my database like this
clients
|___clientnumber: 4
|___name1
|_device_token: kJ-aguwn7sSHsjKSL....
|_notificationtrigger: 8
What I want to do is that when a client puts a number in my app inside his node "name1" it will trigger a notification when clientnumber is 8 , so, client number will be 4, then 5, then 6 and so on till 8, when it hits 8 I wrote this function in order to send the user a notification telling him that the clientnumber 8 is ready.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.sendClientesNotification = functions.database.ref('/clients/clientnumber')
.onWrite((snapshot, context) => {
const newClient = snapshot.after.val();
const oldClient = snapshot.before.val();
console.log('New client: '+newClient);
console.log('Old client: '+oldClient);
// get the user device token
const getDeviceTokensPromise = admin.database()
.ref(`/clients/name1/device_token`).once('value');
const getClientNotificationTrigger = admin.database()
.ref(`/clients/name1/notificationtrigger`).once('value');
//I use a promise to get the values above and return, and then I create the notification
return Promise.all([getDeviceTokensPromise, getClientNotificationTrigger]).then(results => {
const devicetoken = results[0].val();
const clientNumberTrigger = results[1].val();
console.log('New notification for '+devicetoken+' for the number '+clientNumberTrigger);
if(clientNumberTrigger = newClient){
const payload = {
notification: {
title: "Alert",
body: "alert triggered",
icon: "default",
sound:"default",
vibrate:"true"
}
};
}
return admin.messaging().sendToDevice(devicetoken, payload);
});
});
Now, I will explain what I'm doing right here.
First I'm pointing to the reference clientnumber and successfully getting the value before and after it changes here
const newClient = snapshot.after.val();
const oldClient = snapshot.before.val();
console.log('New client: '+newClient);
console.log('Turno anterior: '+oldClient);
then I'm querying the values inside my client in order to have device_token and then notificationtrigger and using a promise to get the two values, comparing if they are identically and then returning a notification with the current user device_token
The errors I'm facing are this two
The first one I think is from this line
const clientNumberTrigger = results[1].val();
and the second one I don't know why is happening, I think that I need to add a conditional expression before my if statment
I'm starting up with firebase functions and slowly learning some javascript in the process.
as the error says: you are trying to compare two values using a single equals symbol (=) while you should use three instead:
switch this:
if(clientNumberTrigger = newClient) { ... }
to this:
if(clientNumberTrigger === newClient) { ... }
and at least this error should be gone.
Related
I am trying to use a value (Discord User ID stored as a string) stored via quick.db in my code, but it returns me the error user_id: Value "[object Promise]" is not snowflake. I've spent hours trying to figure it out but it just doesn't work. If I store the ID directly in the code it works just fine and I can fetch the user.
This is my "ready.js" file. The cron package lets me define at what time of the day that part of code is being executed. I don't think it's a part of the problem.
const Discord = require("discord.js")
const cron = require('cron');
const path = require('path');
const { QuickDB } = require("quick.db");
const db = new QuickDB()
module.exports = client => {
console.log(`${client.user.username} ist online`)
client.user.setActivity('Online!', { type: 'PLAYING' });
let userid1 = db.get("id1.string");
let scheduledMessage = new cron.CronJob('00 00 08 * * *', () => {
client.users.fetch(userid1).then(user => {
user.send('Test').catch(err => {
let channel = client.channels.cache.get('998568073034465341')
channel.send(`${user} blocked the bot`)
})
})
})
scheduledMessage.start()
}
This is where I want to utilize a User ID stored via quick.db in "id1.string"
client.users.fetch(userid1).then(user => {
-> This doesn't work
client.users.fetch(400120540989227010).then(user => {
-> This is working fine
I've already tried using
`${userid1}`
but this also doesn't work
I'd be so happy if someone could help me with that.
db.get("id1.string") is an async function, meaning unless you put await behind it, it will returns a Promise who isn't finished yet. It's like wanting to send a discord message. You can't just get the message immediatly since because of your connection and the api's connection. It takes time. So to bypass this you have to use the await keyword before the .get method (and async the main function here) so that it won't execute the rest of the code until you get what you want from the database.
let userid1 = db.get("id1.string"); // What you have now
let userid1 = await db.get("id1.string"); // What you should do instead
module.exports = client => { // What you have now
module.exports = async client => { // What you should do instead
Just starting to use Firebase functions and have the sample working, but confused because the update event doesn't occur if I change the 'messages' collection to a different name, eg 'listings'. I change the word 'messages' in two places, on the 'add' and the 'makeUppercase' line. I get the response OK, it writes the data to the collection, but doesn't fire the event. Must be simple, but can't google it.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.addMessage = functions.https.onRequest(async (req, res) => {
// Grab the location parameter.
const inputcode = req.query.code || 'blank';
// Push the new message into Cloud Firestore using the Firebase Admin SDK.
const writeResult = await admin.firestore().collection('messages').add({inputcode: inputcode});
// Send back a message that we've succesfully written the message
res.json({result: `Message with ID: ${writeResult.id} added.`});
});
exports.makeUppercase = functions.firestore.document('/messages/{documentId}')
.onCreate((snap, context) => {
// Grab the current value of what was written to Cloud Firestore.
const inputcode = snap.data().inputcode;
// Access the parameter `{documentId}` with `context.params`
functions.logger.log('Uppercasing', context.params.documentId, inputcode);
const areacode = inputcode.toUpperCase();
const written = new Date();
return snap.ref.set({written, areacode}, {merge: true});
});
I'm using the local firebase emulator to do this test, by the way.
This is the new version, ony changing 'messages' to 'vvvv' in two places.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.addMessage = functions.https.onRequest(async (req, res) => {
// Grab the location parameter.
const inputcode = req.query.code || 'blank';
// Push the new message into Cloud Firestore using the Firebase Admin SDK.
const writeResult = await admin.firestore().collection('vvvvv').add({inputcode: inputcode});
// Send back a message that we've succesfully written the message
res.json({result: `Message with ID: ${writeResult.id} added.`});
});
exports.makeUppercase = functions.firestore.document('/vvvvv/{documentId}')
.onCreate((snap, context) => {
// Grab the current value of what was written to Cloud Firestore.
const inputcode = snap.data().inputcode;
// Access the parameter `{documentId}` with `context.params`
functions.logger.log('Uppercasing', context.params.documentId, inputcode);
const areacode = inputcode.toUpperCase();
const written = new Date();
return snap.ref.set({written, areacode}, {merge: true});
});
OK. Doug, your suggestion sank in after an hour or so! I've restarted everything and think that I understand. If I change the name in those two places, without restarting, the collection.add function takes place and I can see the record in the new collection, but the onCreate event didn't fire. I had to restart the whole service to restart buth parts. I was getting confused because one part was working and not the other. Thanks for your patience.
I was wondering if anyone could tell me what I am doing wrong. I am trying to write a firebase function to send a notification. That part works, but I am trying to get the value of a particular child. Yet I keep getting the following error message: "TypeError: Cannot read property 'child' of undefined"
This is my server-side code:
'use strict'
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/notifications/{receiver_user_id}/{notification_key}').onWrite((data, context)=>{
const receiver_user_id = context.params.receiver_user_id;
const notification_key = context.params.notification_key;
console.log('We have a notification to send to : ', receiver_user_id);
// Grab the current value of what was written to the Realtime Database.
const original = data.after.val();
console.log('Uppercasing', context.params.notification_key, original);
const sender_fullname = snapshot.child('notifying_user_fullname').val();
console.log('fullname value: ', sender_fullname);
if(!data.after.val()){
console.log('A notification has been deleted: ', notification_key);
return null;
}
const DeviceToken = admin.database().ref(`/tokens/${receiver_user_id}/device_token`).once('value');
return DeviceToken.then(result=>{
const token_id = result.val();
const payload = {
notification: {
title: sender_fullname,
body: "You have a new message!",
icon: "default"
}
};
return admin.messaging().sendToDevice(token_id, payload).then(response=>{
console.log('Message has been sent');
});
});
});
The snapshot prints out just fine. And when I remove the snapshot and sender_fullname constants the notification is delivered just fine. But, like I said, I keep getting a TypeError message when the code is executed this way. Does anyone know how to get the value of a child at a certain location in realtime database. If it helps, this is what the data snapshot looks like:
If anyone can help that would be great. Thank you in advance
You have a variable snapshot that was never defined, at least not that you're showing here. Here's where you're using it:
const sender_fullname = snapshot.child('notifying_user_fullname').val();
Trying to call method on something that's not defined would give you that error message.
I want to send notification to users when they receive new messages with the below JavaScript code
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.pushNotification = functions.database.ref('/messages/{user_id}/{message_id}').onWrite( (change, context) => {
const user_id = context.params.user_id;
const message_id = context.params.message_id;
console.log('We Have A Notification for :', user_id);
if (!change.after.val()){
return console.log("A Notification Has Been Deleted From The Database: ", message_id)
}
const fromUser = admin.database().ref(`/messages/${user_id}/${message_id}`).once('value');
return fromUser.then(fromUserResult => {
const from_user_id = fromUserResult.val().from;
console.log("You have new notification from : ", from_user_id)
const userQuery = admin.database().ref(`/Users/${from_user_id}/name`).once('value');
const deviceToken = admin.database().ref(`/Users/${user_id}/device_token`).once('value');
return Promise.all([userQuery, deviceToken]).then(result => {
const userName = result[0].val();
const token_id = result[1].val();
const payload = {
notification: {
title: "Chat+",
body: `You have a new notification from ${userName}`,
icon: "default",
click_action: "com.mani.eric.quickch_TARGET_NOTIFICATION"
},
};
return admin.messaging().sendToDevice(token_id, payload ).then(Response =>{
console.log('this is the notification')
});
});
});
});
the notification actually gets delivered but on both devices(sender and receiver gets same notification) with the user name of the sender as null.
my question now is, how can i retrieve the sender user name and display the notification only on the receivers device?
You have a type on the path that triggers the function:
functions.database.ref('/messages/{user_id/{message_id}')
Should be:
functions.database.ref('/messages/{user_id}/{message_id}')
So with a closing parenthesis after user_id.
Please read how to create a minimal, complete, verifiable example, as the code you shared is quite a bit more complex than needed to reproduce the problem. For example, your console.log('We Have A Notification for :', user_id); already should show that user_id is null, so the code after that can't work, and is irrelevant to the problem. Reducing the scope of the problem this way increases the chances that you'll find the cause yourself. Or at worst, it reduces the code we need to look at, which increases the chance that somebody will spot the problem and answer.
I'm trying to implement a trigger using Firebase Functions, that duplicates some data in the database. I want to watch all additions at votes/user/vote, the structure is:
And the code I tried is:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.duplicateFeedback = functions.database.ref('/votes/{userId}/voteId')
.onWrite(event => {
const userId = event.params.userId;
const voteId = event.data.key();
const vote = event.data.val();
console.log(`New feedback from user ${userId}: { description: "${vote.feedback}", score: ${vote.rating}}`);
return;
});
But I can't even get it triggered.. Any clues what's wrong with my function? I bet is related with the reference, but I can't figure out what exactly.
Right now, the function is triggered by a write to
exports.duplicateFeedback = functions.database.ref('/votes/{userId}/voteId')
which would be triggered by something like this:
votes: {
00000_josemi_foo: {
voteId: {
// data
}
}
}
But you're not looking for the child voteId, you're looking for any child of {userId}, such as -33, so you need to use a wildcard:
exports.duplicateFeedback = functions.database.ref('/votes/{userId}/{voteId}')