send message with sockets - angularjs

I just need to have a user send private message to another user.
I have a service in angular with methods:
onSend:function(data) {
socket.emit('notification:save', {
message:'fromClient'
});
console.log("emittted")
},
onReceive:function(){
socket.on('notification:save',function(message){
console.log("recieved notif on mesage send")
})
console.log("recieved")
}
controller:
if(Auth.isLoggedIn()){
socket.onReceive();
}
$scope.sendMessage = function () {
socket.onSend($scope.message.newMessage);
$scope.message.newMessage = '';
};
It emits the event when I call $scope.sendMessage function but never is able to listen to the event i.e onReceive is never triggered.
How do I make this adapt to send to a particular client?
I need to listen and emit event both at front end. Just a notification so nothing that I need to store in db. Do I still have to include server side in this part of emit and on for events.

Here is a simple example of a private message server using socket.io. this uses nodejs and express on the server side, jquery on the client and socketio on both. the client.html is for demonstration only. in angular you would supply the username before connection to the socket.io server. in client.html you will need to enter it in the username field then click connect on both clients before sending messages. to test you can use 2 different browsers (ie. firefox for 1 client, chrome for another) make sure the user name is different on each client otherwise you will be sending messages to yourself.
server.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var _ = require('lodash');
var clients = {};
app.get('/', function(req, res){
res.send('<h1>Message Server</h1>');
});
io.on('connection', function(socket){
// store the socket with the username if a reply event was emitted
socket.on('reply.username', function(username) {
console.log('Got Username reply', username);
clients[username] = socket;
});
// handle direct messages
socket.on('msg.private', function(obj) {
console.log('routing private message');
if (obj.to && clients[obj.to]) {
console.log('delivering to', obj.to);
clients[obj.to].emit('msg.private', obj.message);
}
});
// emit a request to the client to send its username back
socket.emit('send.username');
});
//start the server
http.listen(3000, function() {
console.log('Started server');
});
client.html
<html>
<head>
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
</head>
<body>
<script>
var socket;
function connectIO() {
socket = io.connect('http://localhost:3000/');
socket.on('send.username', function() {
console.log('Server requested username');
socket.emit('reply.username', $('#username').val());
});
// recieve a message
socket.on('msg.private', function(msg) {
$('#chat').html(msg);
});
}
// send the pm
function sendPM() {
socket.emit('msg.private', {
to: $('#to').val(),
message: $('#msg').val()
});
$('#message').val('');
}
</script>
<form>
<textarea id="chat" rows="10" cols="10"></textarea><br>
Username: <input type="text" id="username"><br>
To: <input type="text" id="to"><br>
Message: <input type="text" id="msg"><br>
<span onclick="sendPM()">Send</span><br>
<span onclick="connectIO()">Connect</span>
</form>
</body>
</html>

Related

Integrating Stripe JS with MEAN Stack Application

I'm trying to integrate stripe in my MEAN stack application. It's not communicating with Stripe to receive the token. I'm not sure why.
I have stripe source code sourced in my index.html page for my angular application.
It is not communicating with Stripe to receive the token, that console.log never fills, So I know it's not communicating with Stripe for some reason, but the same source code communicates with Stripe in a standalone application. I also believe it is failing when sending server side. I'm trying to send this request from port 3000 to port 8082.
Then I have the below script in another HTML page in my app for stripe:
Stripe.setPublishableKey('pk_test_******************');
var $btn = $('#submit');
$btn.on('click', function() {
$btn.prop('disabled', true);
$btn.button('progress');
var cardNum = $('#card-num').val();
var cardExp = $('#card-exp').val().split('/');
var cardCVC = $('#card-cvc').val();
// First submit the card information to Stripe to get back a token
console.log("starting stripe token");
Stripe.card.createToken({
number: cardNum,
exp_month: cardExp[0],
exp_year: cardExp[1],
cvc: cardCVC
}, function(status, response) {
var $form = $('#form');
var token = response.id;
console.log(response.id);
// Save the token into a hidden input field
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
// Now submit the form to our server so it can make the charge against the token
$.post("http://localhost:8082/charge", $form.get(0), function(res) {
console.log("response from charge: " + res);
});
// All done!
$btn.addClass('btn-success').removeClass('btn-primary');
$btn.button('success');
setTimeout(function() {
$('#checkout').modal('hide');
}, 250);
});
return false;
});
I see the console.log response of starting stripe token but it doesn't actually communicate with stripe.
Then here is my server side code:
app.post('/charge', function(req, res) {
// Connect to the db
MongoClient.connect("mongodb://localhost:27017/meanAuth", function(err, db) {
if(!err) {
console.log("We are connected");
}
});
var stripeToken = req.body.stripeToken;
var amount = 1000;
stripe.charges.create({
card: stripeToken,
currency: 'usd',
amount: amount
},
function(err, charge) {
if (err) {
res.send(500, err);
} else {
res.send(204);
}
});
});
My reason for doing this is I'm trying to send user information in my request to the server side code so the server can update a value in my Mongo database.
I need help! Thanks in advance

socket.io - can't send messages to a spesific room in a socket

I am trying use socket.io + angular to create a chat room web application.
I have a specific text box in which the user enter the name of the room he wants to connect. then, I am trying to connect this user into that specific room and send all of his messages to this room.
however, when I am trying to send a string into the chat, the request is being handle on the server side (the console log output is printed from the server) but not on the controller socket.on('chat_message', function(data) ...) method does not print it console log.
what am I doing wrong?
the code is below. there is more code that I don't think is required (angular related stuff).
Thanks in advance
view
<form ng-submit="submit()">
<input autocomplete="off" ng-model="insertedText" type="text" />
<button type="button" ng-click="submit()">
Send
</button>
</form>
controller
mymodule.controller("cntrlChat", ['$scope', 'myService',
function($scope, myService){
var socket = io();
$scope.messages = [];
$scope.room= myService.get();
socket.emit('room', $scope.room);
$scope.submit=function(){
socket.emit('chat_message',{ room: $scope.room, msg: $scope.user+": "+$scope.insertedText });
$scope.insertedText='';
return false;
}
socket.on('chat_message', function(data){
console.log('room-->'+data.room+' msg---->'+data.msg );
$scope.$apply(function() {
$scope.messages.push(data.msg);
});
});
}]);
server
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.use(express.static(__dirname + '/'));
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
io.emit('chat_message', "welcome");
socket.on('room', function(room) {
socket.join(room);
});
socket.on('chat_message', function(data){
console.log("room---->"+data.room, "msg---->"+data.msg);
io.sockets.in(data.room).emit('chat message',data.msg);
});
socket.on('disconnect', function(){
io.emit('chat message', "Bye");
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
You are emitting chat message from the server and waiting for chat_message on the client. Look carefully, one has an underscore the other a space.
It might just be a typo error.
Avoid spaces and special characters in message labels.
the error is here
io.sockets.in(data.room).emit('chat message',data.msg);
it should be
io.sockets.in(data.room).emit('chat_message',data.msg);

private chat using socket.id on socket.io

i am fresher at nodejs and socket.io. i am trying to made a chat application using nodejs, socket.io and angularjs in express framework. i am lacking basic idea how chat is performed privately.up to this stage my code works chatting in a group of connected users. here is my server code
var server = require('http').Server(app);
var io = require('socket.io')(server);
var socket = require('./routes/socket.js');
server.listen(8000);
console.log('server listening on port:8000');
io.on('connection',socket);
and my main socket file consit code like:
module.exports = function(socket){
console.log('connected'+' '+'socketId :'+socket.id);
//console.log(req.session.id);
var users =[];
socket.emit(socket.id);
socket.on('username',function(data){
users.push({id:socket.id,message:data.username});
socket.emit('username', users)
})
socket.on('typing',function(data){
//socket.emit('typing',{message:"helo angular"});
socket.broadcast.emit('typing',{message:data.message});
});
socket.on('typing-stop',function(data){
//socket.emit('typing',{message:"helo angular"});
debugger;
socket.broadcast.emit('typing-stop',{message:data.message});
});
socket.on('new-user',function(data){
socket.emit('new-user',data);
socket.broadcast.emit('new-user',data);
})
socket.on('message',function(data){
users.push({message:data.message});
socket.emit('message',{id:socket.id,message:data.message});
socket.broadcast.emit('message',{id:socket.id,message:data.message});// emit the message to every one connected in server
})
socket.on('disconnect',function(){
console.log('user disconnected');
socket.broadcast.emit('disconnected',{'message':'user left the chat room'});
});
}
i am abe to load all the users who get logged in my app.
all i want is to click to the available and start private messaging, till now chat is public everyone connected in server can see message.
my angularjs controller code goes like:
function orgController(notifyService, chatSocket, $state,$http) {
chatSocket.connect();
var vm = this;
vm.sendMessage = sendMessage;
vm.messages = [];
vm.users = [];
var id = $state.params.id;
$http.get('/users/' + id).then(function(result) {
console.log(result.data);
vm.userData = result.data;
chatSocket.emit('new-user', { 'username': result.data.details.firstName + ' ' + result.data.details.lastName });
});
chatSocket.on('new-user',function(data){
vm.users.push(data);
})
function sendMessage(msg) {
//console.log(msg);
if (msg != null && msg != '') {
chatSocket.emit('message', { message: msg });
vm.msg = '';
} else {
vm.msg = '';
}
}
chatSocket.on('message', function(data) {
//debugger;
console.log(data);
vm.messages.push(data);
});
}
NOTE: i have included angular-socket.io modules and inject its dependency in a service called chatSocket which only return socketFactory.
now i want to click in a user from logged in userlist and start communication. how can i do it from (socket.id). which socket generates or from session id? anyone has better way of doing such. any suggestion and response are highly appreciated.
Basically what you need to do is emit an event to a specific socket like this.
io.to(socket.id).emit('privateMessage', {message: <message goes here>});
then on the client side
socket.on('privateMessage', function(data){
var message = data.message;
//do stuff, display message etc...
});

Using Socket.io, Angular, JWT Authenitication data not available till after user authenticated refresh

I am using Angular and Socket.io, socket-jwt for authentication the sockets, and angular-socket-io on the front end.
When the page loads, the client attempts to connect to the socket.io server. It is denied because their is no token established for the client.
When a socket connection is established I am decoding the token on the server and then I want to emit data to the client including the socket.id where I will update the model and view.
After a user authenticates, it is not until the page is refreshed that the socket.io data is available and then emits to the client.
How do I go about establishing the socket.io connection after the user has logged in and making the data available?
I have tried calling my socket factory, using socket.connect() and io.connect() inside the login controller after a user logs in.
socket factory
app.factory('socket', function ($window, socketFactory) {
var token = $window.localStorage.yourTokenKey;
var myIoSocket = 'http://localhost:8080';
var socket = io.connect(myIoSocket, {'query' : 'token=' + token});
return socket;
});
login function in login controller
$scope.login = function() {
AuthService.login($scope.user)
.then(function(msg) {
socket.connect();
$state.go('home');
}, function() {
console.log('Login Failed');
});
};
server code
var socketIo = require('socket.io');
var io = socketIo.listen(server);
io.use(socketioJwt.authorize({
secret: config.secret,
handshake: true
}));
io.on("connection", function(socket) {
var token = socket.handshake.query.token;
var decoded = jwt.decode(token);
var user = {
name: decoded._doc.name,
userId: decoded._doc._id,
socketId: socket.id
};
socket.emit(‘other event’, user);
});

MEAN.JS Contact Form

Trying to create a contact form and feedback form for my website. Here is my route and controller I'm using however I need to understand what's going on with my routes and how to capture the input fields from the form implement this inside MEAN.JS:
route.js:
app.route('/mail').get(mail.createmail);
app/controller.js:
exports.createmail = function(req, res) {
var mailOpts, smtpTrans;
// create reusable transporter object using SMTP transport
var transporter = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: 'administrator#radleaf.com',
pass: '34Girls34*goo'
}
});
// NB! No need to recreate the transporter object. You can use
// the same transporter object for all e-mails
// setup e-mail data with unicode symbols
var mailOptions = {
from: 'Fred Foo ✔ <foo#blurdybloop.com>', // sender address
to: 'ty#radleaf.com', // list of receivers
subject: 'Hello ✔', // Subject line
text: 'Hello world ✔', // plaintext body
html: '<b>Hello world ✔</b>' // html body
};
// send mail with defined transport object
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
console.log(error);
} else {
console.log('Message sent: ' + info.response);
}
});
};
Not sure how this work with the HTML with the view:
<form action="mail">...</form>
If I understand the question correctly, you're asking how you can gather data which is input into a form, send that data to expressJS, and then use that data to send an outbound email.
If so, then here is your flow:
Step 1: Create a form in a view and map it to an AngularJS controller
<form name="contactForm" data-ng-submit="sendMail()">
Name: <input type="text" data-ng-model="contact_name">
Message: <input type="text" data-ng-model="contact_msg">
<button type="submit">
</form>
Step 2: In your AngularJS controller, use a $http request to send your data to your Express Route
$scope.sendMail = function() {
// Simple POST request example (passing data) :
$http.post('/mail', {name: contact_name, msg: contact_msg}).
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
}
Step 3: Use your ExpressJS Route as an API to call your ExpressJS Controller.
(It looks like you've got this bit covered)
app.route('/mail').get(mail.createmail);
Step 4: Receive and do something with the data passed through the $http POST
exports.createmail = function(req, res) {
var data = req.body;
Now you can use the data, like this
var mailOptions = {
from: data.name, // sender name
text: data.msg, // plaintext body
};
MeanJS 0.4.0 also has a working example of NodeMailer which might help: https://github.com/meanjs/mean/tree/0.4.0
With angularJS, you can remove the action attribute, and just use angularJS ngSubmit directive, and call a function in your controller which would now visit the endpoint with $http.get.

Resources