/
index.js
executable file
·162 lines (144 loc) · 4.57 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
var WebSocketServer = require("ws").Server;
var http = require("http");
var express = require("express");
var request = require("request");
var app = express();
var port = process.env.PORT || 5000;
// Last.fm API constants
var baseURL = 'http://ws.audioscrobbler.com/2.0/?';
var apiKey = 'api_key=3d386c221b36c1442b384aa1d853bc8c';
var format = 'format=json';
var method = 'method=user.getRecentTracks';
var limit = 'limit=1';
// Serve static files from
app.use(express.static(__dirname + "/app"));
app.use(express.static(__dirname + "/app/styles"));
app.use('/bower_components', express.static(__dirname + '/bower_components'));
app.use(express.static(__dirname + "/app/scripts"));
app.use(express.static(__dirname + "/app/fonts"));
app.use(express.static(__dirname + "/app/images"));
// Create server and tell which port to listen to
var server = http.createServer(app);
server.listen(port);
console.log("http server listening on %d", port);
// Plugin for handling multiple socket connections
var wss = new WebSocketServer({server: server, perMessageDeflate: false});
console.log("websocket server created");
// Information of all users who are connected
var usersAPI = {
// Sample element looks like this
// {'user': Guapo15, 'location': {'lat': 40, 'lng': 80}, 'song': {{last.fm response}}}
users: [],
// Add new user to users and broadcast
addNewUser: function(user, location) {
var exists = this.checkExistenceOf(user);
if (exists == -1) {
var query = buildQuery(user);
request.get(query, {}, function(err, res, body) {
var userInfo = {'user': user, 'location': location, 'song': body};
usersAPI.users.push(userInfo);
console.log('Added user.')
console.log(usersAPI.users);
wss.broadcast(JSON.stringify(userInfo));
});
}
else {
this.updateUserLocation(user, location, exists);
}
},
// Deprecated
addUser: function(info) {
this.users.push(info);
console.log('Added user.')
console.log(info);
},
// Get user's current song and broadcast
updateUser: function(user) {
var query = buildQuery(user.user);
request.get(query, {}, function(err, res, body) {
user.song = body;
console.log('Updated user.')
wss.broadcast(JSON.stringify(user));
});
},
updateUserLocation: function(user, location, index) {
console.log('yo');
this.users[index].location = location;
wss.broadcast(JSON.stringify(user));
},
// Potential race condition.
// I'm just being lazy and don't want to do two O(n) calls
checkExistenceOf: function(user) {
for (var i = this.users.length - 1; i >= 0; i--) {
if (this.users[i].user == user) { return i; }
}
return -1;
},
// Used earlier for testing, but still useful so it's hanging around
reset: function() {
this.users.length = 0;
}
};
console.log(usersAPI);
// Return the Last.fm query for this given user
function buildQuery(user) {
var url = baseURL;
url += apiKey + '&';
url += format + '&';
url += method + '&';
url += limit + '&';
url += 'user=' + user;
return url;
}
// For those just connecting, show every connection prior
wss.showCurrentConnections = function showCurrentConnections(ws) {
var connections = usersAPI.users;
console.log(connections);
for (var index=0; index<connections.length; index++) {
ws.send(connections[index]);
}
}
// Transmit data to every client
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
client.send(data);
});
};
// The 'upon connection' logic
wss.on("connection", function(ws) {
console.log("websocket connection open");
// Show existing connections upon connection
wss.showCurrentConnections(ws);
// Every 60 seconds, get users' current song
setInterval(function() {
for (var index=0; index<usersAPI.users.length; index++) {
var user = usersAPI.users[index];
console.log(user);
usersAPI.updateUser(user);
}
}, 60000);
ws.on("close", function() {
console.log("websocket connection close");
});
// When the server gets a message from a client
// Makes the call to Last.fm
ws.on('message', function incoming(message, flags) {
console.log('received: %s', message);
// message is JSON
// get the user from message and call Last.fm
var parsed = JSON.parse(message);
var user = parsed.user;
var location = parsed.location;
usersAPI.addNewUser(user, location);
});
});
/*(function(){
console.log('yo');
// For ever connected user, update self
for (var index=0; index<usersAPI.users.length; index++) {
var user = usersAPI.users[index];
console.log(user);
usersAPI.updateUser(user);
}
setTimeout(arguments.callee, 60000); // every minute and a half or 90 seconds
})();*/