-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
160 lines (137 loc) · 4.85 KB
/
server.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
// Define the packages and requirements for the application to work.
const twitter = require('twitter'),
express = require('express'),
app = express(),
http = require('http'),
server = http.createServer(app),
io = require('socket.io').listen(server),
CONFIG = require('./config.json');
// Configure a twitter client
const twit = new twitter({
consumer_key: CONFIG.consumer_key,
consumer_secret: CONFIG.consumer_secret,
access_token_key: CONFIG.access_token_key,
access_token_secret: CONFIG.access_token_secret
});
// Configure the local (but global) variables to use between socket events and the twitter stream
const local = {
memory: [],
output: null,
inputString: 'hi',
update: false
}
// Validation function to see if the inputString has been changed
function checkInput() {
if(local.update) {
local.update = false;
return true;
}
return false
}
// Initiate the server and call the socket connection
function initServer() {
// Listen to the proccess.env.PORT or the configurated port
server.listen(process.env.PORT || CONFIG.port);
console.log(`Server is listening on port ${CONFIG.port}, or the local Heroku port`)
// Publish the public folder as a static folder to the client
app.use(express.static(__dirname + '/public'));
// Call the socket connection
initSockets()
}
// Initiate the socket connection
function initSockets() {
// As soon as socket-io finds a new client, connect with it.
io.sockets.on('connection', socket => {
// Check if there are saved images in the sidebar, and send them to the new client if there are.
if(local.memory.length) {
socket.emit('update list', local.memory);
}
// Next up are all socket related events
// When 'update string' is received. Set the new inputString and change the update value to 'true'
socket.on('update string', string => {
local.inputString = string;
local.update = true;
});
// The client is ready to receive a new image, so we send the latest one saved from the stream, if not null
socket.on('request new image', () => {
// Check to see if there is any data at all, otherwise void
if(local.output !== null) {
socket.emit('twitter-stream', {'src': local.output});
}
})
// User wishes to save an image (click)
socket.on('save image', src => {
// Push the image src url to our local memory
local.memory.push(src)
// Check if the maximum number of images has been surpassed
if(local.memory.length > 15) {
// Remove the first entry from the array if so
local.memory.shift();
}
// Emit to update the list on the local client, broadcast to update for every other client
socket.emit('update list', local.memory);
socket.broadcast.emit('update list', local.memory);
});
// Handle error event
socket.on('error', error => {
console.log('error' + error)
});
// Handle disconnect event
socket.on('disconnect', () => {
console.log('A user disconnected')
});
// As soon as we've set up all events, send the 'connected' event to the client to complete the handshake
socket.emit('we have established a connection!');
});
}
// Initiate the Twitter stream
function initStream() {
// Hook into the stream API with a custom query and a low filter level (can be none or medium as well)
twit.stream('statuses/filter', {'track': local.inputString, 'filter_level':'low'}, stream => {
// Save the last entry for sanitation purposes
let last = null;
// As soon as there is new data, handle it
stream.on('data', data => {
// Validate if the user object is accesible (locked chars give an error)
if(data.user){
// Validate if the user profile image exists
if (data.user.profile_image_url !== null) {
// Apply the check if the image is the same one as last entry (duplicate streaming results)
if(data.user.profile_image_url !== last) {
// Update the last known image URL
last = data.user.profile_image_url;
// Update our output for the socket connection to use
local.output = data.user.profile_image_url;
}
}
}
// Handle error event
stream.on('error', error => {
return console.log(error);
});
// Handle limit event
stream.on('limit', limitMessage => {
return console.log(limitMessage);
});
// Handle warning event
stream.on('warning', warning => {
return console.log(warning);
});
// Handle disconnect event
stream.on('disconnect', disconnectMessage => {
return console.log(disconnectMessage);
});
// Check to see if the inputString has changed, every time there is new data
if(checkInput()) {
// If so, destroy the stream
stream.destroy();
// And re-init the stream with the new query
initStream();
console.log(`Restarted stream with query: ${local.inputString}`)
}
});
});
}
// Start the socket connection and Twitter stream
initServer();
initStream();