I'm tryin to do a simple web3 app with Next/Js & Firebase.
People can connect with their wallet from solana, to list their NFT, then choose one for connect in a game-container.
I'm stuck because i want to get infos from all connected players listed in Firebase. then with the infos create some div in the game-container with all the connected players.
But, when i try to get the snapshot of all the players, the onValue doesn't fire and i don't know why...
nothing happend, no console log or anything.
That's my code and my database below
const database = getDatabase();
const reference = ref(database,'players/' + playerWallet);
const referenceDatabase = ref(database);
function initGame() {
const allPlayersRef = ref(database,'players/');
onValue(allPlayersRef, (snapshot) => { // NEVEER HAPEND IDK WHYYYYYYYYYYYYYYYY
if (snapshot.exists()){
console.log("Snap Exist");
} else {
console.log("snap is empty");
}
console.log("XXXXXXXXXXXXXXXXXXXXXXXXXX");
//start every change occurs
console.log("SNAP: "+snapshot.val());
players = snapshot.val() || {};
console.log("PLAYERS INFO : "+ players.playerName);
Are you sure the user has permission to read the data? If not, you'll get an error message in the console of where the code executes. Alternatively, you can also detect such a permissions error with:
onValue(allPlayersRef, (snapshot) => {
...
}, (error) => {
console.error(error);
});
You are right.
error handler
I have modified the rules and everything is workin now thanks !
Related
Description of the problem:
My App aim is to store family spending in Firebase Realtime Database. I want that, when a new spending is stored, a notification is sent to all other devices.
I try to send a notification to a single device and it works fine, but when I try to get all the tokens in an array, I have an error:
TypeError: Cannot convert undefined or null to object at Function.keys ().
code of index.js :
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.androidPushNotification = functions.database
.ref("{nodo}/spese/{spesaPush}")
.onCreate(async (snapshot, context) => {
const original = snapshot.val();
const getDeviceTokensPromise = admin.database()
.ref(`/utenti/{tutti}/token`).once('value');
let tokensSnapshot;
let tokens;
tokensSnapshot = await getDeviceTokensPromise;
// This is the line generating the errors.
// If I get only a specific token and
// use tokens = tokensSnapshot.val(); anything works fine
tokens = Object.keys(tokensSnapshot.val());
const result = original.chi + " ha speso " +
original.costo + " € per acquistare " +
original.desc;
console.log(result);
const payload = {
notification: {
title: 'New spending inserted!',
body: result,
}
};
const response = await admin.messaging().sendToDevice(tokens, payload);
return result;
});
It seems that values are not reached yet, but I thought that the keyword await lets system to wait until all data are available. From the log I noticed that the value I need is null and I don't understand why.
If I use this line of code:
const getDeviceTokensPromise = admin.database()
.ref(`/utenti/SpecificUser/token`).once('value');
....
//then
tokens = tokensSnapshot.val();
The notification is sent to the device that has the token under the name of "SpecificUser"
EDIT:
I provide a pic of my db. I notice that none of the field is null, so I don't know why I see this error
Thank you to anyone that helps me
i had same error and it is solve by database...
when i saw my database values unfortunately i stored undefined value so my whole result got error like you...
see your whole values and fields that store values properly.
I'm trying to implement easier to read documentIDs and through this strategy that Frank recommended but I've run into an error that I haven't been able to fix.
I can successfully read the value of highestCount from the COUNTER document but have an error when I try to update it.
The error states:
FirebaseError: Provided document reference is from a different Firestore instance
My Javascript code (using React):
const onSetCreation = async (e) => {
e.preventDefault();
var setNo = 0;
try {
await runTransaction(db, async (transaction) => {
const currentSetNo = await transaction.get(
doc(db, "users", userStatus.uid, "set", "COUNTER")
);
console.log(currentSetNo.data());
// if theres no counter, create one
if (!currentSetNo.exists()) {
transaction.update({ highestCount: 0 });
setNo = 0;
} else {
setNo = currentSetNo.data().highestCount + 1;
// update the COUNTER once iterated
transaction.update(currentSetNo, { highestCount: setNo });
}
});
// succesful update of COUNTER
console.log("Transaction successfully committed!");
} catch (e) {
console.log(e);
}
};
This function is triggered on a button click.
My Firestore structure
is users -> [userid] -> set -> COUNTER
Where counter is a document that holds highestCount which is to be updated everytime this function runs.
I'm able to console.log the value of COUNTER, just can't update it.
I haven't been able to find any similar problems.
I'm using the Web version 9 of Firestore, I've read this documentation for runTransaction.
Cheers
Okay, so I found the error. I was using the wrong reference in this line:
transaction.update(currentSetNo, { highestCount: setNo });
which should actually be
transaction.update(
doc(db, "users", userStatus.uid, "set", "COUNTER"),
{ highestCount: setNo }
);
Or whatever your db reference is, in replacement of currentSetNo in the first example.
I've got a near full-functioning realtime database presence system as described here but I am encountering a few issues. It seems that people are remaining online even after having disconnected a while ago. I'm not sure why but I've opened up my security rules to unauthenticated requests temporarily to no avail. It could be due the bug described here.
If the issue is the ladder, what would be the proper JavaScript implementation to avoid this issue? Is it a good solution to recreate the onDisconnect listener every 60 minutes? For reference, the code I'm using is shown below:
export function selfPresence(byUpdate) {
onValue(ref(rtdb, '.info/connected'), (snap) => {
isDBConnected = snap.val();
if (snap.val() === true) {
presencecon = push(ref(rtdb, `users/${user.uid}/connections`)); // Create new presence thing.
onDisconnect(presencecon).remove();
set(presencecon, true);
onDisconnect(ref(rtdb, `users/${user.uid}/lastOnline`)).set(serverTimestamp());
onDisconnect(ref(rtdb, `users/${user.uid}/currentlyListening`)).remove();
}
});
}
MY SOLUTION
I could not figure out how to get RTDB to act consistently so I opted for the code below instead. Basically, it just updates a boolean at a specific path so that if/when the issue DOES happen, the next time the user is online, it will overwrite the failure with new online listener.
onValue(ref(rtdb, '.info/connected'), (snap) => {
isDBConnected = snap.val();
if (snap.val()) {
onDisconnect(presencecon).set(false);
presencecon = ref(rtdb, `users/${user.uid}/online`);
isDBConnected = snap.val();
}
else {
remove(presencecon);
}
}
The below code updates a boolean at a specific path so that if/when the issue DOES happen, the next time the user is online, it will overwrite the failure with a new online listener.
onValue(ref(rtdb, '.info/connected'), (snap) => {
isDBConnected = snap.val();
if (snap.val()) {
onDisconnect(presencecon).set(false);
presencecon = ref(rtdb, `users/${user.uid}/online`);
isDBConnected = snap.val();
}
else {
remove(presencecon);
}
}
im trying to make my discord.js bot send an embed when someone joins, with as thumbnail their pfp, but it always leaves the same error.
code:
bot.on('guildMemberAdd', member => {
// Send the message to a designated channel on a server:
const WelcomeChannel = member.guild.channels.cache.find(ch => ch.name === config.WelcomeChannelVar);
var newMember = member
// Do nothing if the channel wasn't found on this server
if (!WelcomeChannel) return;
const welcomeEmbed = new Discord.MessageEmbed()
.setTitle(newMember + 'joined!')
.addField('username', member)
.setColor(0x348a58)
.setThumbnail(newMember.showAvatarURL())
.setFooter('wow very nice profile bro')
WelcomeChannel.send(welcomeEmbed);
member.send("welcome to frogpond! read the rules :)");
});
error:
TypeError: newMember.showAvatarURL is not a function
I've tried everything. can somebody help plz?
thanks!
I'm pretty sure that showAvatarURL() is not a function and you mean avatarURL() instead, so you should change your code to be like this:
const welcomeEmbed = new Discord.MessageEmbed()
// your stuff before thumbnail
.setThumbnail(newMember.user.avatarURL())
// your stuff after thumbnail
edit: the .user is important, because avatarURL is only a User function
It's because you wrote showAvatarURL() instead of displayAvatarURL().
I'm trying to get the Discord bot to create a database that is basically the user map (a row for each user and columns for ID, nick name, avatar URL, etc) when it receives a !getdata command.
I've gotten to the point where the database successfully takes data, in this case the username and user ID, but it displays all the unique values in two columns as long comma separated values (i.e. the username column displays 'user1,user2,user3').
I'm sure this is by design, but I'm really struggling with restructuring. I'd like to either have it take all the data from an object map (client.users or message.guild.members) but I cannot figure it out.
The other option, which is what I'm trying now, is to create a row for each user and then fill in the values that I want to store, but I'm getting nowhere fast.
I'm very new with SQLite (and node/DiscordJS/JS for that matter), so any advice is greatly appreciated.
Index.js
const Discord = require('discord.js');
const client = new Discord.Client();
const sql = require('sqlite3');
let db = new sql.Database("users.sqlite", (err) => {
if (err) {
console.log('Error connecting to the database', err)
} else {
console.log('Database connected.')
}
})
let token = process.env.CLIENT_TOKEN;
let prefix = process.env.PREFIX ;
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
db.run(`CREATE TABLE IF NOT EXISTS users(username TEXT, id TEXT)`);
})
client.on('message', function(message) {
if (!message.content.startsWith(prefix));
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
if (command === 'getdata') {
let username = message.guild.members.map(m=>m.user.username);
let userid = message.guild.members.map(m=>m.user.id);
db.run(`INSERT OR REPLACE INTO users(username, id) VALUES(?,?)`, [`${username}`,`${userid}`]);
return message.channel.send(`User database updated.`);
}
});
client.login(token);
If you're curious as to the formatting or way things are written, the answer is two fold:
I'm pretty new at this
This was the only way I could get the values in the database to return something other than null
Thanks in advance,
First off, welcome to the site.
I hope that I can shine some light here without diving into refactoring your code or making you change anything major.
One thing sticks out to me as to why you are storing an array instead of a single value.
let username = message.guild.members.map(m=>m.user.username);
let userid = message.guild.members.map(m=>m.user.id);
The .map call returns an array, not a single value.
Each user that issues a command is part of the message object. If I remember correctly, you would want this to be something like...
(simplified version)
const { username, id } = message.member.user;
db.run(`INSERT OR REPLACE INTO users(username, id) VALUES(?,?)`, [username, id]);
// ...
User documentation can be found here
Edit:
If you wanted to build the database for all users in that one command you could do something like the following with a bulk insert... (quick and dirty)
db.serialize(() => {
db.run('BEGIN TRANSACTION;');
// execute inserts in transaction
for (const m of message.guild.members) {
db.run('INSERT OR REPLACE INTO users(username, id) VALUES(?,?);', [m.user.username, m.user.id]);
}
// commit all inserts :)
db.run('COMMIT;')
});
message.channel.send('User database updated.');
Control flow documenation
Hopefully this points you in the right direction :)