I'm new to socket.io. I have a working message chat set up and I'm trying to add names to the messages. I have a var called name which holds each users name who has logged in. below is the code.
On the HTML page that holds the chat. chat-room.html
const room = 'waiting';
const socket = io('/tech');
$('form').submit(() => {
let msg = $('#m').val();
socket.emit('message', { msg, room });
$('#m').val('');
return false;
});
socket.on('connect', () => {
// emiting to everybody
socket.emit('join', { room: room });
})
socket.on('message', (msg) => {
$('#messages').append($('<li>').text(name + msg));
})
On the server script. index.js
const app = require('express')();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const port = 3001;
server.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
app.get('/', (req, res) => {
res.sendFile(__dirname + '/virtualsim/learning/chat-room.html');
});
app.get('/trainees', (req, res) => {
res.sendFile(__dirname + '/virtualsim/learning/chat-room2.html');
});
const tech = io.of('/tech');
tech.on('connection', (socket) => {
socket.on('join', (data) => {
socket.join(data.room);
tech.in(data.room).emit('message', `joined ${data.room} room!`);
})
socket.on('message', (data) => {
console.log(`message: ${data.msg}`);
tech.in(data.room).emit('message', data.msg);
});
socket.on('disconnect', () => {
console.log('user disconnected');
tech.emit('message', 'user disconnected');
})
})
Obvious, the way I have it now just sends back the user his or her name for every message sent, even messages send by other users. I need to add the variable name to the server script some how and I'm having difficulties getting it to work. Thanks for any help. John
Here is my Frontend code for set the username
<script>
const form = document.querySelector("form");
const input = document.querySelector(".input");
const messages = document.querySelector(".messages");
const username = prompt("Please enter a username: ", "");
const socket = io();
socket.on("old_message", {message: "hello"});
form.addEventListener("submit", function(event) {
event.preventDefault();
addMessage(username + ": " + input.value);
socket.emit("chat_message", {
message: input.value
});
input.value = "";
return false;
}, false);
socket.on("chat_message", function(data) {
addMessage(data.username + ": " + data.message);
});
socket.on("user_join", function(data) {
addMessage(data + " just joined the chat!");
});
socket.on("user_leave", function(data) {
addMessage(data + " has left the chat.");
});
socket.on("old_message", function() {
console.log('----data', data);
});
socket.on("getList", function(data) {
console.log('----MessageList', data);
});
addMessage("You have joined the chat as '" + username + "'.");
socket.emit("user_join", username);
socket.emit("old_message")
function addMessage(message) {
const li = document.createElement("li");
li.innerHTML = message;
messages.appendChild(li);
window.scrollTo(0, document.body.scrollHeight);
}
Here is backend code
const users = []; io.on('connection', (socket) => { socket.on('user_join', (data) => {
this.username = data;
// here check in DB with sender, receiver if record not exist then create
users.push({
socketId: socket.id,
userId: data,
});
socket.broadcast.emit('user_join', data); });
socket.on('chat_message', async (data) => {
const a = {
sender: data.senderId,
receiver: data.receiverId,
type: 'TEXT',
message: data.message,
};
await model.conversations.create(a);
data.username = this.username;
socket.broadcast.emit('chat_message', data); });
socket.on('disconnect', (data) => {
socket.broadcast.emit('user_leave', this.username); });
socket.on('old_message', async (data) => {
const messageList = await model.conversations.findAll({
where: {
sender: data.senderId,
receiver: data.receiverId,
},
});
socket.broadcast.emit('getList', messageList); }); });
Thanks for the answers back. I have figured out what I had to do.
First (on the HTML page) I had to emit the var name which holds all the users names to the server script on connect. This gives the proper name when one enters the room.
socket.on('connect', () => {
socket.emit('join', { room: room, name: name });
})
Then I added it to the messages being sent
$('form').submit(() => {
let msg = $('#m').val();
socket.emit('message', { name, msg, room });
$('#m').val('');
return false;
});
Then on the server script I added.
On connect
tech.in(data.room).emit('message', `${data.name} joined ${data.room} room!`);
Then again for the messages being sent
tech.in(data.room).emit('message', data.name + data.msg);
I'm sure there is a better way to join the names and messages but like I said I'm new to socket and I have spent way too much time on this :) If you know a better way please do let me know. Thanks!
prompt for the name first, then append it to the start of every message they emit
socket.emit(name+msg, ()=>{...});
Related
I want to broadcast a message to a user when they connect but only to that one user.
How do I get their socket ID when they connect so I can use io.to(theirSocketID).emit('chat message', 'Welcome');?
you can store the data everytime a user is connected in an array
var clients = [];
io.on("connection", (socket) => {
console.log("new user connected");
socket.on("new user", function (data) {
// console.log(clients[data])
if (data in clients) {
let index = clients.indexOf(data);
if (index !== -1) {
clients.splice(index, 1);
}
socket.nickname = data;
clients[socket.nickname] = socket;
} else {
socket.nickname = data;
clients[socket.nickname] = socket;
}
console.log("new user : " + socket.nickname);
});
and on disconnect
socket.on("disconnect", () => {
console.log("user disconnected");
delete clients[socket.nickname];
});
that is what i always do to store the socket id for private messaging
this is what my chat socket look like
socket.on("chat", function (data) {
var id = data.id;
if (clients.hasOwnProperty(id)) {
io.to(clients[id]["id"]).emit("chat", data);
console.log(clients[id]["id"]);
} else {
console.log("\nTarget Device Is Offline or Doesn't exist\n ");
});
you can also implement read / unread if target is connected or not
I am new to JS.
I am trying to build API server, this server must received data from other server using socket.
Currently I am using net library, I am facing a problem.
I should get data to check whether hardware worked or not, but I only get
undefiend(empty array).
I found some sources making async function to get called, but still I can't get it.
here is my code.
router.post("/Updated", async function(req, res, next) {
.....
//connect to station server for locking
var data = {
cmd: "lockStationQuery",
stationId: STATION_ID,
powerBankId: POWER_BANK_ID,
userId: USER_ID,
number: channelValue
};
var stringData = JSON.stringify(data);
var jsonData = JSON.parse(stringData);
var [client, recvData] = await getConnectionSocket(
USER_ID,
res,
merchant_uid,
amount
);
let successToWriteData = await writeData(client, stringData);
//Fail to send data to lock the Station
if (!successToWriteData) {
res.status(500).json({
RESULT: "FAIL",
REASON:
"error code 504"
});
res.end();
return;
}
console.log("received data", recvData); //this is empty array
jsonData = JSON.parse(recvData[0]);
Here is my getConnectionSocket function.
async function getConnectionSocket(USER_ID, res, merchant_uid, amount) {
//서버에 해당 포트로 접속
var client = "";
var recvData = [];
var local_port = "";
let status = {};
client = net.connect({ port: 8999, host: "localhost" }, function() {
console.log(
"connect log======================================================================"
);
console.log("connect success");
console.log("local = " + this.localAddress + ":" + this.localPort);
console.log("remote = " + this.remoteAddress + ":" + this.remotePort);
local_port = this.localPort;
this.setEncoding("utf8");
this.setTimeout(300000); // timeout : 10분
console.log("client setting Encoding:binary, timeout:300000");
console.log("client connect localport : " + local_port);
});
// 접속 종료 시 처리
client.on("close", function() {
console.log("client Socket Closed : " + " localport : " + local_port);
});
// 데이터 수신 후 처리
await client.on("data", function(data) {
console.log(
"data recv log======================================================================"
);
recvData.push(data);
console.log(recvData); //I want this data
console.log("data.length : " + data.length);
console.log("data recv : " + data);
let jsonData = JSON.parse(data);
if (jsonData.cmd === "removedPowerBank") {
if (jsonData.errorCode !== 0) {
//환불
console.log("환불 시작");
let cancel = cancelOrder(merchant_uid, USER_ID, res);
//여기서 환불 purchase db에 쓰기
} else {
console.log("PURCHASE 성공후 디비에 씀");
//구매 purchase db에 쓰기(getRentId에 썼음)
let purchased = writePurchaseDataInDB(
USER_ID,
res,
merchant_uid,
amount
);
console.log(purchased);
}
}
client.end();
});
client.on("end", function() {
console.log("client Socket End");
});
client.on("error", function(err) {
console.log("client Socket Error: " + JSON.stringify(err));
});
client.on("timeout", function() {
console.log("client Socket timeout: ");
});
client.on("drain", function() {
console.log("client Socket drain: ");
});
client.on("lookup", function() {
console.log("client Socket lookup: ");
});
return [client, recvData]; //recvData is always empty array
}
which way is best to address to resolve this?
Need some clarification on below point
are you getting correct value(s) in below log ? Or you undefined in them too.
console.log("data.length : " + data.length);
console.log("data recv : " + data);
also add this one
console.log("data type : " + typeof(data));
im trying to create a chat using nodejs for a project, the problem is that when i send a message and there is more than 1 user on the chat it repeats the message, for example (visual example), if i have 4 users in the chat it prints the message 4 times.
This is the code im using
socketio.js
var Messages = require('../controllers/chat_message')
var socket_io = require('socket.io');
var io = socket_io();
var socketio = {};
socketio.io = io;
var users = [];
io.on('connection', function(socket){
console.log('A user connected');
console.log(`Socket connected ${socket.id}`)
Messages.getpreviousMsgs()
.then(dados =>socket.emit('previousMessage', dados))
.catch(erro =>res.status(500).jsonp(erro))
socket.on('sendMessage', data => {
console.log(data);
Messages.create(data)
.then(dados =>console.log("Saved"))
.catch(erro =>res.status(500).jsonp(erro))
});
socket.on('join', function (user){
socket.username = user.username;
users.push(socket.username);
io.emit('user joined', { 'username': user.username, users:users });
});
socket.on('typing', function (msg) {
io.emit('typing', { 'message': msg.message, 'username': msg.username });
});
socket.on('new_message', function (msg) {
io.emit('chat message', { 'message': msg.message, 'username': msg.username });
});
socket.on('disconnect', function(){
console.log('user disconnected');
users.splice(users.indexOf(socket.username), 1);
io.emit('user disconnected', { 'username': socket.username });
});
});
module.exports = socketio;
chat_script.js
var username = Math.random().toString(36).substr(2,8);
socket.emit('join', { username: username });
socket.on('user joined', function (data) {
$(".js-userjoined").html(data.username + ' Joined chat room');
console.log(data.users);
$.each(data.users, function(index, user) {
console.log(user);
$(".js-usersinchat").append('<span id ='+user+'> <strong>'+user+'</strong></span>');
});
});
socket.on('user disconnected', function (data) {
$("#"+data.username).remove();
});
socket.on('previousMessage', function(messages){
for(message of messages){
$('#messages').append('<div class="row message-bubble"><p class="text-muted">'+message.author+'</p><p>'+ message.message+' </p> </div>');
}
});
//an event emitted from server
socket.on('chat message', function (data) {
var string = '<div class="row message-bubble"><p class="text-muted">' + data.username+'</p><p>'+data.message+'</p></div>';
if (data.username.length && data.message.length){
var messageObject = {
author:data.username,
message: data.message,
};
socket.emit('sendMessage',messageObject);
}
$('#messages').append(string);
});
$(function () {
var timeout;
function timeoutFunction() {
typing = false;
socket.emit("typing", { message: '', username: '' });
}
$("#sendmessage").on('click', function () {
var message = $("#txtmessage").val();
$("#txtmessage").val('');
$('.typing').html("");
socket.emit('new_message', { message: message, username: username });
});
$('#txtmessage').keyup(function () {
console.log('happening');
typing = true;
socket.emit('typing', { message: 'typing...', username: username});
clearTimeout(timeout);
timeout = setTimeout(timeoutFunction, 2000);
});
});
socket.on('typing', function (data) {
if (data.username && data.message) {
$('.typing').html("User: " + data.username + ' ' + data.message);
} else {
$('.typing').html("");
}
});
var typing = false;
var timeout = undefined;
function timeoutFunction(){
typing = false;
socket.emit(noLongerTypingMessage);
}
I hope i was clear
Try remove this line:
socket.emit('sendMessage',messageObject);
Here on chat_script.js:
//an event emitted from server
socket.on('chat message', function (data) {
var string = '<div class="row message-bubble"><p class="text-muted">' + data.username+'</p><p>'+data.message+'</p></div>';
if (data.username.length && data.message.length){
var messageObject = {
author:data.username,
message: data.message,
};
// THIS LINE BELOW:
socket.emit('sendMessage',messageObject);
}
$('#messages').append(string);
});
I have used this Firebase Database code in a previous project:
const getDeviceUser = admin.database().ref(`/users/${notification.to}/`).once('value');
I am now trying to convert it for Firestore. I am basically trying to get my users fcm's when a notification is being sent. I have tried many things, but haven't seen the new way to accomplish this.
EDIT: here is my code.
exports.sendFavoriteNotification = functions.firestore.document('users/{userUid}/notifications/{notificationId}').onCreate(event => {
const notification = event.data.data();
const user = event.params.userUid;
const getDeviceUser = admin.database().ref(`/users/${notification.to}/`).once('value');
// Get the follower profile.
const getProfilePromise = admin.auth().getUser(notification.sender);
return Promise.all([getDeviceUser, getProfilePromise]).then(results => {
const tokensSnapshot = results[0];
const liker = results[1];
// Check if there are any device tokens.
if (!tokensSnapshot.hasChildren()) {
return console.log('There are no notification tokens to send to.');
}
//console.log('There are', tokensSnapshot.numChildren(), 'tokens to send notifications to.');
console.log('Fetched follower profile', liker);
// Notification details.
const payload = {
notification : {
title : 'You have a new like!',
body : `${liker.displayName} just liked your photo.`,
badge: '1',
sound: 'default'
}
};
// Listing all tokens.
var tokens = admin.firestore.ref(`/users/${notification.to}/`).get('fcm');
// Send notifications to all tokens.
admin.messaging().sendToDevice(tokens.data(), payload);
return admin.messaging().sendToDevice(tokens, payload).then(response => {
// For each message check if there was an error.
const tokensToRemove = [];
response.results.forEach((result, index) => {
const error = result.error;
if (error) {
console.error('Failure sending notification to', tokens[index], error);
// Cleanup the tokens who are not registered anymore.
if (error.code === 'messaging/invalid-registration-token' ||
error.code === 'messaging/registration-token-not-registered') {
tokensToRemove.push(tokensSnapshot.update({
fcm: FieldValue.delete()
}));
}
}
});
return Promise.all(tokensToRemove);
});
});
});
Hope this will help. This is my code after 2 days of trying to learn how to convert from realtime database to firestore. It is based on a firebase project: https://github.com/MahmoudAlyuDeen/FirebaseIM
let functions = require('firebase-functions');
let admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotificationToFirestone = functions.firestore.document('/notifications/{pushId}')
.onCreate(event => {
const pushId = event.data.id;
const message = event.data.data();
const senderUid = message.from;
const receiverUid = message.to;
const db = admin.firestore();
if (senderUid === receiverUid) {
console.log('pushId: '+ pushId);
return db.collection('notifications').doc(pushId).delete();;
} else {
const ref = db.collection('users').doc(receiverUid);
const query = new Promise(
function (resolve, reject) {
ref.get()
.then(doc => {
if (!doc.exists) {
console.log('No such document!');
reject(new Error('No such document!'));
} else {
console.log('Document data:', doc.data().instanceId);
resolve(doc.data().instanceId);
}
})
.catch(err => {
console.log('Error getting document', err);
reject(err);
});
});
const getSenderUidPromise = admin.auth().getUser(senderUid);
return Promise.all([query, getSenderUidPromise]).then(results => {
//console.log('instanceId = Result[0]: ' + results[0]);
//console.log('sender = Result[1]: ' + results[1]);
const instanceId = results[0];
const sender = results[1];
//console.log('notifying ' + receiverUid + ' about ' + message.body + ' from ' + senderUid);
//console.log('instanceId este' + instanceId);
const payload = {
notification: {
title: sender.displayName,
body: message.body,
icon: sender.photoURL
}
};
admin.messaging().sendToDevice(instanceId, payload)
.then(function (response) {
console.log("Message sent: ", response);
})
.catch(function (error) {
console.log("Error sending message: ", error);
});
});
}
});
I would like to use websockets to send updates from the server to the clients.
I know I can use Server Sent Events but Internet Explorer doesn't have great compatibility with it so I prefer to use websocket.
The TotalJs WebSocket allow me to use it like a client?
I'm trying to do this: (TotalJs Websocket Example)
exports.install = function(framework) {
framework.route('/');
framework.route('/send/', send_message);
framework.websocket('/', socket_homepage, ['json']);
};
function send_message() {
var controller = this;
var socket = new WebSocket('ws://127.0.0.1:8000/');
socket.onopen = function() {
socket.send(encodeURIComponent(JSON.stringify({ message: "send_message" })));
};
socket.close();
socket = null;
}
function socket_homepage() {
var controller = this;
controller.on('open', function(client) {
console.log('Connect / Online:', controller.online);
client.send({ message: 'Hello {0}'.format(client.id) });
controller.send({ message: 'Connect new user: {0}\nOnline: {1}'.format(client.id, controller.online) }, [], [client.id]);
});
controller.on('close', function(client) {
console.log('Disconnect / Online:', controller.online);
controller.send({ message: 'Disconnect user: {0}\nOnline: {1}'.format(client.id, controller.online) });
});
controller.on('message', function(client, message) {
console.log(message);
if (typeof(message.username) !== 'undefined') {
var old = client.id;
client.id = message.username;
controller.send({ message: 'rename: ' + old + ', new: ' + client.id });
return;
}
// send to all without this client
message.message = client.id + ': ' + message.message;
console.log(message);
controller.send(message);
});
}
When someone connect to http://127.0.0.1/send all clients connected to the server will receive a message.
Node.js doesn't have native WebSocket support so the send_message() function does not work. I would like to use TotalJs Websocket support but I don't know how to use it like a client.
Thats it.
Thank you very much.
I know this is the not best way but I used a global variable to resolve.
exports.install = function(framework) {
framework.route('/');
framework.route('/send/', send_message);
framework.websocket('/', socket_homepage, ['json']);
};
function send_message() {
if (websocket == null) return;
websocket.send({ message: "Hello World!" });
}
var websocket = null;
function socket_homepage() {
//var controller = this;
websocket = this;
websocket.on('open', function(client) {
console.log('Connect / Online:', websocket.online);
client.send({ message: 'Hello {0}'.format(client.id) });
websocket.send({ message: 'Connect new user: {0}\nOnline: {1}'.format(client.id, websocket.online) }, [], [client.id]);
});
websocket.on('close', function(client) {
console.log('Disconnect / Online:', websocket.online);
websocket.send({ message: 'Disconnect user: {0}\nOnline: {1}'.format(client.id, websocket.online) });
});
websocket.on('message', function(client, message) {
console.log(message);
if (typeof(message.username) !== 'undefined') {
var old = client.id;
client.id = message.username;
websocket.send({ message: 'rename: ' + old + ', new: ' + client.id });
return;
}
// send to all without this client
message.message = client.id + ': ' + message.message;
console.log(message);
websocket.send(message);
});
}