Check if a user has a specific object with quick.db - node.js

Hello I am trying to check if someone has an object in his inventory witch quick.db
But when I try, whatever the artist is it always says that it's the inventory of the user. Here's the code that I use.
const db = require('quick.db');
let discord = require('discord.js');
module.exports = {
name : 'test',
description : "commande test",
async execute(message, args) {
const artist = message.content.slice(7).trim();
if(!artist){
message.channel.send("Spécifier l'artiste")
}
if(db.has(message.author.id, artist)){
message.channel.send("Artiste Present")
}
else{
message.channel.send("Non présent")
}
}
}
I use this to add information to the database
if (reaction.count == 2){
db.push(user.id, name_artist);

The problem is that you are only checking if the database has a specific user id as a key. According to the quick.db docs.
To check if an artist is stored in an array I would try this.
if (db.get(message.author.id).includes(artist)) {
message.channel.send("Artiste Present")
}
else {
message.channel.send("Non présent")
}

Related

Firebase Cloud Functions: Keeping things in sync

I have users and companies and want to store a company for each user and all of the users of each company in Firebase.
user={
"id":"tjkdEnc3skdm2Jjknd"
"name":"Adam",
"street":"Sideway 4",
"company":"dHend4sdkn25"
}
companies={
"id":"dHend4sdkn25",
"name":"Comp Ltd.",
"members":[
{
"id":"tjkdEnc3skdm2Jjknd"
"name":"Adam"
},{
"id":"dfjnUkJKB3sdn8n2kj"
"name":"Berta"
}
]
}
All explanations say that duplicate data is the best way to deal with and so I want to write some cloud functions to keep thigs in sync when editing on one of the sides.
Basically I started with
exports.userChangedCompany = functions.firestore
.document('users/{userId}')
.onUpdate((change, context) => {
const data = change.after.data();
const previousData = change.before.data();
if (data.company == previousData.company) {
return null;
}
else{
admin.firestore().doc('companies/'+data.company).set({ ... });
}
});
to update the companies when a user changed the company. Unfortunately I haven't found any hint how to set the new company-data properly.
Can someone please help me?
It sounds like you just need to remove user from members array of old company and add in that array of new company. You just need IDs of both companies.
async function updateCompanies(userId, username, oldCompanyId, newCompanyId) {
const companiesRef = await admin.firestore().collection("companies")
const userObj = {id: userId, name: username}
// Removing from old company and adding in new company
await Promise.all([
companiesRef.doc(oldCompanyId).update({members: admin.firestore.FieldValue.arrayRemove(userObj)}),
companiesRef.doc(newCompanyId).update({members: admin.firestore.FieldValue.arrayUnion(userObj)})
])
return true
}
You can just call this function in your cloud function. Just make sure you pass correct params. The reason why you need to pass the username as well is you have array of objects (members) and hence you need the complete object to add/remove using arrayUnion/arrayRemove.

How can I automatically append a property from a relation to the root object?

How can I automatically append a property from a relation to the root object, as if it were a column from the same table but actually it is coming from another table.
Supose I have an User model that hasMany Emails.
How can I only append the email from the first Email of the User model, so that everytime I query the User model I get it like a property?
Example:
What I'm doing:
(await User.query().where('id', id).with('emails').first()).toJSON()
{
"name": "Eleandro Duzentos",
"emails": [
{ "email": "eleandro#inbox.ru" },
{ "email": "eleandro#mail.ru" }
]
}
What I want:
(await User.find(id)).toJSON()
{
"name": "Eleandro Duzentos",
"email": "eleandro#inbox.ru"
}
Obs: I'm not putting the email on the same table because, there's a chance that a user may need more then one email in a long future, but for now, it has only one.
How can I do that?
For the customized JSON response i would suggest the use of serializers.
You can override the default serializers to get the desired result.
You can refer to this - https://adonisjs.com/docs/4.0/serializers
Here is my code. You could be inspired by it:
Model User:
...
const Email = use('App/Models/Email')
class User extends Model {
async getEmails() {
let list = []
let emails = await Email.query().where('user_id', this.id).fetch()
emails.rows.forEach(email => {
list.push({ name: this.username, email: email.email })
});
return list
}
emails() {
return this.hasMany('App/Models/Email')
}
}
module.exports = User
Controller :
...
let user = await User.find(1)
return await user.getEmails()
Output :
[
{"name":"CrBast","email":"test#crbast.ch"},
{"name":"CrBast","email":"test2#crbast.ch"}
]
Feel free to correct me if that's not what you want :)

Update mongodb document, if the document exists, else create

So I am trying to make a discord bot for me and my friends for tracking stats in CS GO 10 mans, and I am using cheerio for webscraping from the site that provides us the stats, and then pass them into mongodb. The scraping functionality works fine, but im trying to figure out how to avoid creating duplicate documents for each user. If I enter *userid 857575 it pulls the stats for that user, and puts in the DB, but if i call that multiple times, its making multiple documents in the DB. My question is, how would I get mongodb to update the document based on if the message author in discord matches the username in the db? So if username bob sends *userid3939 and bob already exists in the db, update the document. If bob doesnt exist, create document. code below, appreciate any tips.
module.exports.run = async (bot, message, args) => {
console.log(args);
var userUrl = 'https://popflash.site/user/' +args;
console.log(userUrl);
console.log(message.member.user.tag);
rp(userUrl)
.then(function (html) {
const arr = [];
var i = 0;
$('.stat-container', html).each(function (key, value) {
arr[i++] = $(this).find(".stat").text();
});
const stats = new Stats({
_id: mongoose.Types.ObjectId(),
userName: message.member.user.tag,
userId: args,
HLTV: arr[0],
ADR: arr[1],
HS: arr[2],
W: arr[3],
L: arr[4],
T: arr[5],
win_percent: arr[6]
});
stats.save()
.then(function (result) {
let botembed = new Discord.RichEmbed()
.setDescription(message.member.user + "'s 10 Man stats")
.setColor("#15f153")
.addField("stats", result)
return message.channel.send(botembed);
})
})
}
module.exports.help = {
name: "userid"
}
Through db.collection.update, you can specify the upsert: true option to get the behavior I think you're desiring. It will update an existing record if matched, otherwise it will create a new record.

Intercept E_UNIQUE when have multiple unique attributes

Sails/Waterline is intercepting the error, but there is no description about which one of the unique attributes led to the error.
Example: I have email and username, both unique, in my schema.
I suggest you look here for the solution of the problem:
https://github.com/balderdashy/sails/issues/6982
var emailAlreadyInUse = await User.count({emailAddress: newEmailAddress});
if(emailAlreadyInUse) {
throw 'emailAlreadyInUse';
}
var usernameAlreadyInUse = await User.count({username: newUsername});
if(usernameAlreadyInUse) {
throw 'usernameAlreadyInUse';
}

How do I increment a value for an existing object in Firebase?

I'm building a step counter app.
I got an iOS app that pushes the sum of each day to /users/{mobile}/steps/{date}/
When a new steps child is updated or added, I want to sum the value of all the steps for that particular user and update his stepsTotal.
To achieve that I need to
Find the original user and sum all the steps.
Save the new value to stepsTotal.
I would be most grateful if someone could give some help here. :-)
database
{
"users": {
"92291000": {
"firstName": "Tore",
"stepsTotal": "1500",
"steps": {
"02-09-2017": "500",
"03-09-2017": "1000"
},
import.js
var db = admin.database();
var dbRoot = db.ref("/");
var usersRef = dbRoot.child("users");
// This works
function saveUser(attributes) {
let mobile = attributes.mobile;
delete attributes['mobile']
let user = usersRef.child(mobile);
user.update(attributes);
}
function increaseSteps( { mobile=null, steps=null } = {}) {
// Find the User
console.log("looking for mobile", mobile); // OK
let userRef = usersRef.child(mobile);
// Here I'm not able to read the old data from the user.
userRef.transaction(function(user) {
console.log("user: ", user); // null
// ^ User is null.
});
/*
If I mangage to find user above, I expect to do something like this.
Or it is possible to only update *stepsTotal*?
*/
let attributes = {
firstName: user.firstName,
lastName: user.lastName,
stepsTotal: user.stepsTotal + steps,
}
user.update( attributes );
}
If I understand correctly, you have a problem in this snippet of the code:
let userRef = usersRef.child(mobile);
// Here I'm not able to read the old data from the user.
userRef.transaction(function(user) {
console.log("user: ", user); // null
// ^ User is null.
});
In Firebase Database transactions the initial value is often null. From the Firebase documentation on transactions:
Transaction Function is Called Multiple Times
Your transaction handler is called multiple times and must be able to handle null data. Even if there is existing data in your database it may not be locally cached when the transaction function is run.
This is due to how Firebase transactions work behind the scenes. To learn more about that, see my answers here Transcation updateFunction parameter is null and Firebase runTransaction not working.
The solution is to handle both cases: if the user node doesn't exist yet count the initial number of steps, otherwise update the number of steps:
let userRef = usersRef.child(mobile);
userRef.transaction(function(user) {
return (user || 0) + new_steps_for_user;
});

Resources