I'm saving the users data in an array see the below code
server code
socket.on('add user', function(data) {
if (users.indexOf(data.id) == -1) {
users.push({
id: socket.id,
userId: data.id,
firstName: data.firstName,
lastName: data.lastName
});
}
len = users.length;
len--;
io.emit('user join', users, users[len].userId, users[len].id);
});
I'm sending request from front end to a user for that first i'm checking whether user in online or not for sending request to specific user. If user there I'm assigning user socket.id to userId variable based on that I'm sending data see the below code
server code
socket.on('addNewFriend', function(userId) {
console.log(userId);
for(var i=0;i<users.length;i++){
if(users[i].userId==userId){
var socketid=users[i].id;
console.log(socketid);
io.to(socketid).emit('addFriend',"hai");
}
}
});
Instead of keeping just the socket Id, keep the socket connection itself as well.
users.push({
id: socket.id,
socket: socket
userId: data.id,
firstName: data.firstName,
lastName: data.lastName
});
It would be easier, if you use a map, instead of an array to save users,
users[socket.id] = {
socket: socket
userId: data.id,
firstName: data.firstName,
lastName: data.lastName
}
Then when you want to send a message, use the socket connection,
users[socketId].socket.emit(/*args*/)
If you save sockets in an array instead, you will need to filter the user object manually and then do the same.
Edit: So the full code for the listener is as below,
socket.on('addNewFriend', function(userId) {
for(var i=0;i<users.length;i++){
if(users[i].userId == userId){
var socketId = users[i].id;
console.log(socketId);
users[socketId].socket.emit('addFriend', "hai");
}
}
});
Related
So, I having an issue of sending a DM to a specific person without an author tag, and without a mention of the person. I tried duplicating the mention array:
/*jshint esversion: 6*/
const commando = require('discord.js-commando');
class Msgowner extends commando.Command {
constructor(client) {
super(client, {
name: 'msgowner',
group: 'info',
memberName: 'msgowner',
description: 'Gives rules on mock or legit duels.',
examples: ['ladderrules type'],
});
}
async run(message) {
var user = {
id: '12345',
username: 'Bloodmorphed',
discriminator: '12345',
avatar: 'd510ca3d384a25b55d5ce7f4c259b2d0',
bot: false,
lastMessageID: null,
lastMessage: null,
};
user.send('Test');
}
}
module.exports = Msgowner;
There is a reason why I need to send DMs this way, but I can't seem to figure out how. (The error it gives now is a unknown function). Also replacing id and discriminator with generic numbers, but they are correct in my code.
Try something like this - get the member you're looking for using message.channel.members.find() method:
async run(message) {
// get Collection of members in channel
let members = message.channel.members;
// find specific member in collection - enter user's id in place of '<id number>'
let guildMember = members.find('id', '<id number>');
// send Direct Message to member
guildMember.send('test message');
}
Edit: It looks like it's also possible to find users outside the current channel by doing something like this:
async run(message) {
// get client from message's channel
let client = message.channel.client;
// fetch user via given user id
let user = client.fetchUser('<id number>')
.then(user => {
// once promise returns with user, send user a DM
user.send('Test message');
});
}
Okay, found my answer:
async run(message) {
var user = {
id: '12345,
username: 'Bloodmorphed',
discriminator: '12345',
avatar: 'd510ca3d384a25b55d5ce7f4c259b2d0',
bot: false,
lastMessageID: null,
lastMessage: null,
};
console.log(user);
message.member.user.send('Test');
}
}
module.exports = Msgowner;
EDIT: This was NOT the answer, still looking for one.
I wrote a function to create a user profile.
I use the synchronise module to get rid of the callback hell.
When I do this, everything works fine:
var sql = jsonSql.build({
type: 'insert',
table: 'tbl_user',
values: {firstname: data.firstname, lastname: data.lastname, email: data.email, website: data.website, password: data.hashedPassword},
});
try {
var query = sync.await(db.query(sql.query, sql.values, sync.defer()));
} catch (err) {
res.status(500).send(err);
return;
}
When sql finds a user with an already used mail address it sends an error. Perfect.
Then I thought it would be a good idea to separate the code where the user is written into the database, because maybe you want to create a user in the admin-backend and then I could reuse the smaller function.
The smaller function:
function createUserInDB(data) {
var sql = jsonSql.build({
type: 'insert',
table: 'tbl_user',
values: {firstname: data.firstname, lastname: data.lastname, email: data.email, website: data.website, password: data.hashedPassword},
});
return db.query(sql.query, sql.values);
}
Which now gets called from the main function:
try {
var query = sync.await(userService.createUserInDB(data, sync.defer()));
console.dir(query);
} catch(err) {
console.dir(err);
res.status(500).send(err);
return;
}
This does not work.
How can I get the result of the smaller function (as error or query result) in my main function, so I am able to use try / catch?
I finally solved it.
function createUserInDB(data, resolve) {
sync.fiber(function() {
data.hashedPassword = bcrypt.hashSync(data.password, 10);
var sql = jsonSql.build({
type: 'insert',
table: 'tbl_user',
values: {firstname: data.firstname, lastname: data.lastname, email: data.email, website: data.website, password: data.hashedPassword},
});
try {
var query = sync.await(db.query(sql.query, sql.values, sync.defer()));
//first argument would be error
resolve(null, query);
} catch(err) {
resolve(err);
}
});
}
Basically, add the callback function to the function parameter and then just resolve it inside the fiber.
I'm planning to to create a route where a user could add another user as his/her friend, so that they could chat to each other once they are friends.
So basically once User A has sent a request to User B, User B will get a live notification about the request via socket.io
The problem right now is that, I couldn't come up with my own solution on how to implement the above scenario, from what I know, I should create two routes GET and POST
I'm using mongoose for database query, insert , update and delete
Here's my code
// GET route for getting the user's information -- Simple route
router.get('/users/:facebook_name', function(req, res) {
User.findOne(facebook_name, function(err, user) {
if (!user) {
res.json({message: "Couldn't find a user by that name"});
return;
}
res.json(user);
});
});
// POST route for adding a friend
router.post('/friendships/create/:facebook_name', ensureAuthenticated, function(req, res) {
// What should i put in this route to make the adding a friend feature works?
User.findOneAndUpdate(facebook_name, function(err, user) {
if (user) {
res.json({message: "You already send a friend request to that person"});
return;
}
// Send a live notification to the other user
socket.emit('sending request', {message: "added you as a friend"});
});
});
user Schema code -- Not really sure about this one either
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
friends: [{ type: Schema.Types.ObjectId, ref: 'User'}],
facebook: {
id: String,
token: String,
// email: String,
displayName: String,
photo: String
}
});
// Should I even create this schema?
var FriendsRequest = new Schema({
madeBy: [{ type: Schema.Types.ObjectId, ref: 'User'}],
})
module.exports = mongoose.model('User', UserSchema);
module.exports = mongoose.model('FriendsRequest', FriendsRequest);
I'm not entirely honest with you guys, in the POST route, i have no freaking idea on how to write the logic, because I'm really confuse right now, how the User B gonna get the live request notification? Should i create another route for that?
This is my problem when it comes to building slightly complex apps , i just couldn't come up with a good logic on how to do a certain feature even though it looks pretty easy. I've been stuck in this problem for almost 4 hours, browsing and reading the net, but I believe SO is the only place for me to find a clue on how to do something.
Thank you.
What you can do is create socket for each facebookName(if unique).
On Client Side:
socket.on('connection', function (data) {
socket.emit('setFacebookName', facebookName); });
}
Server saves each socket with facebookName:
socket.on('setFacebookName', function (facebookName) {
users[facebookName]=socket;
});
Now, when user sends chat request to that user in this request
// POST route for adding a friend
router.post('/friendships/create/:facebook_name', ensureAuthenticated, function(req, res) {
// What should i put in this route to make the adding a friend feature works?
User.findOneAndUpdate(facebook_name, function(err, user) {
if (user) {
res.json({message: "You already send a friend request to that person"});
return;
}
// Send a live notification to the other user
sendLiveNotification(facebook_name);
});
});
function sendLiveNotification(facebookName){
socket.on('send notification', function (facebookName) {
users[facebookName].emit('sending request', "has sent friend request");
});
}
You're trying to get a two step process, so you will need at least two calls where one is a request from the requester, and the other is the decision whether or not to allow that request from the requestee. You can handle your callback for the first function utilizing a Boolean where if it's a new request the user could be prompted with a popup on the client.
A good purpose of Mongoose is the extensions to the Schema that you can make, so here I'm adding two functions: one from the requester requesting requestee's friendship, and the other the decision of the requestee
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
friendsAccepted: [{ type: Schema.Types.ObjectId, ref: 'User'}],
friendsRequested: [{ type: Schema.Types.ObjectId, ref: 'User'}],
friendsPending: [{ type: Schema.Types.ObjectId, ref: 'User'}],
friendsRejected: [{ type: Schema.Types.ObjectId, ref: 'User'}],
facebook: {
id: String,
token: String,
// email: String,
displayName: String,
photo: String
}
});
UserSchema.statics.requesterInitiatedRequestForFriendship = function(requesterID, requesteeID, cb) {
mongoose.model('UserSchema').findOne({_id: requesterID}).exec(function(err, requester) {
if (err) return cb(err);
mongoose.model('UserSchema').findOne({_id: requesteeID}).exec(function(err, requestee) {
if (err) return cb(err);
if (requestee.friendsAccepted(requesterID) === -1 &&
requestee.friendsRequested(requesterID) === -1 &&
requestee.friendsPending(requesterID) === -1 &&
requestee.friendsRejected(requesterID) === -1) {
requestee.friendsPending.push(requesterID);
requester.friendsRequested.push(requesterID);
requestee.save();
requester.save();
cb(null, true);
} else {
cb(null, false);
};
});
});
};
UserSchema.statics.requesteeDecidedOnFriendship = function(requesterID, requesteeID, allowed, cb) {
mongoose.model('UserSchema').findOne({_id: requesterID}).exec(function(err, requester) {
if (err) return cb(err);
mongoose.model('UserSchema').findOne({_id: requesteeID}).exec(function(err, requestee) {
if (err) return cb(err);
if ((requestee.friendsAccepted(requesterID) === -1 &&
requestee.friendsRequested(requesterID) === -1 &&
requestee.friendsPending(requesterID) > -1 &&
requestee.friendsRejected(requesterID) === -1) &&
requester.friendsRequested(requesteeID) > -1) {
requestee.friendsPending.forEach(function(uid, idx) {
if (uid === requesterID) {
requestee.friendsPending.splice(idx, 1);
return;
};
});
requester.friendsRequested.forEach(function(uid, idx) {
if (uid === requesteeID) {
requester.friendsRequested.splice(idx, 1);
return;
};
});
if (allowed) {
requestee.friendsAccepted.push(requesterID);
requester.friendsAccepted.push(requesteeID);
} else {
requestee.friendsRejected.push(requesterID);
requester.friendsRejected.push(requesteeID);
}
requestee.save();
requester.save();
};
cb(null);
});
});
}
module.exports = mongoose.model('User', UserSchema);
So a couple things happening:
hasn't been tested
it's not DRY
it's limited without an additional Friendship Schema
With a Friendship Schema, you can define levels of rejection (e.g. "not at this time", etc.), you can more well flush out details and granular control for the changing behavior of friendships. In the above, you can see that once you're rejected, it's pretty fatalistic in that it's determined at no time you shall become friends! So to get more of that type of behavior, I'd definitely go with a Friendship Schema with it's statics and methods flushed out, as should be users.
Mailchimp is almost a perfect company, except their Node API documentation is non-existent. How can I add a subscriber to my new list and include their first name and last name? The code below successfully adds the subscriber, but first and last names are not being added.
var MCapi = require('mailchimp-api');
MC = new MCapi.Mailchimp('***********************-us3');
addUserToMailchimp = function(user, callback) {
var merge_vars = [
{ EMAIL: user.email },
{ LNAME: user.name.substring(user.name.lastIndexOf(" ")+1) },
{ FNAME: user.name.split(' ')[0] }
];
MC.lists.subscribe({id: '1af87a08af', email:{email: user.email}, merge_vars: merge_vars, double_optin: false }, function(data) {
console.log(data);
}, function(error) {
console.log(error);
});
}; // addUserToMailchimp
The supplied merge variables should be passed as a single object, not an array of objects. Please see my example below:
var mcReq = {
id: 'mail-chimp-list-id',
email: { email: 'subscriber-email-address' },
merge_vars: {
EMAIL: 'subscriber-email-address',
FNAME: 'subscriber-first-name',
LNAME: 'subscriber-last-name'
}
};
// submit subscription request to mail chimp
mc.lists.subscribe(mcReq, function(data) {
console.log(data);
}, function(error) {
console.log(error);
});
It looks like you supplied your actual mail chimp API key in your question. If so, you should remove it immediately.
I'm having trouble understanding how to retrieve an XMPP roster (and eventually the presence state of each contact) in node-xmpp (GTalk account).
My example code can login and connect, but I'm a bit lost as to what to send and listen for:
var xmpp = require('node-xmpp')
jid = 'example#gmail.com'
password = 'xxxxxxxxxxxxxx'
// Establish a connection
var conn = new xmpp.Client({
jid: jid,
password: password,
host: 'talk.google.com',
port: 5222
})
conn.on('online', function() {
console.log('ONLINE')
var roster = new xmpp.Element('iq', {
type: 'get',
from: jid,
id: new Date().getTime()
}).c('query', { xmlns: 'jabber:iq:roster' })
conn.send(roster) // Now what?
})
conn.on('error', function(e) {
console.log(e)
})
Looks like the structure of my roster query was wrong, this works correctly:
conn.on('online', function() {
console.log('ONLINE')
var roster = new xmpp.Element('iq', {
id: 'roster_0',
type: 'get'
}).c('query', {
xmlns: 'jabber:iq:roster'
})
conn.send(roster)
})