· 6 years ago · Nov 11, 2019, 09:50 PM
1// Modules
2const express = require('express');
3const http = require('http');
4const socketIO = require('socket.io');
5const path = require('path');
6const cookieParser = require('cookie-parser');
7const session = require('express-session');
8const passport = require('passport');
9const socketSession = require('express-socket.io-session')
10const totp = require('notp').totp;
11const base32 = require('thirty-two');
12const CustomStrategy = require('passport-custom');
13const opAuth = require('opskins-oauth'); // OPSkins auth
14const ExpressTrade = require('expresstrade'); // ExpressTrade
15const crypto = require('crypto');
16const app = express();
17const server = http.createServer(app);
18let io = socketIO(server);
19
20// MySQL
21const mysql = require(path.join(__dirname,'server/mysql.js'));
22
23// Config File
24const config = require(path.join(__dirname, 'server/config.js'));
25
26// API Posts
27const api = require(path.join(__dirname, 'server/routes/api.js'));
28
29// Create new expresstrade instance
30const ET = new ExpressTrade({
31 apikey: config.opskinsApiKey,
32 twofactorsecret: config.opskinsSecret,
33 pollInterval: config.opskinsPollInterval * 1000
34});
35
36// Serialize and deserialize users into the session
37passport.serializeUser((user, done) => {
38 done(null, user);
39});
40
41passport.deserializeUser((obj, done) => {
42 done(null, obj);
43});
44
45
46
47// Middleware
48let sessionMiddleware = session({
49 key: 'session_id'
50 , secret: 'Hirsw0w'
51 , resave: false
52 , saveUninitialized: true
53 , cookie: {
54 maxAge: 1000 * 60 * 60 * 24 * 365
55 }
56});
57app.use(cookieParser());
58app.use(sessionMiddleware);
59
60app.use(passport.initialize());
61app.use(passport.session());
62io.use(socketSession(sessionMiddleware));
63app.use(express.static(path.join(__dirname, 'dist/vgoballoon')));
64app.use('/api', api);
65
66// Sockets
67
68// chat Messages id64 | avatar | Username | message
69let chatMessages = [];
70
71// Online Users ( by id64 : socket | passport )
72let users = [];
73
74const Status = {
75 WAITING:0,
76 TIMER:1,
77 END:2
78};
79
80let balloons = {
81 status: Status.WAITING,
82 gameId: 0,
83 precentage: 0.0,
84 gameHash: 'hash',
85 gameTimer: 15,
86 players: []
87}
88
89function balloonHandler() {
90 switch(balloons.status) {
91 case Status.WAITING: {
92 if(balloons.players.length > 0) {
93 balloons.status = Status.TIMER;
94 balloons.gameTimer = 3;
95 sendBalloonsData();
96 }
97 break;
98 }
99 case Status.TIMER: {
100 if(balloons.gameTimer > 0) balloons.gameTimer--;
101 else {
102 balloons.status = Status.END;
103 balloons.gameTimer = 10;
104 }
105 sendBalloonsData();
106 break;
107 }
108 case Status.END: {
109 if(balloons.gameTimer > 0) balloons.gameTimer--;
110 else {
111 for(let p in balloons.players) {
112 if(100.0 / balloons.players[p].chance > balloons.precentage) {
113 let socketuser = User(balloons.players[p].id64).user;
114 socketuser.balance += (balloons.players[p].bet * balloons.players[p].chance * 0.95);
115 mysql.updateUser(socketuser);
116 sendUserInformation(User(balloons.players[p].id64).socket, socketuser);
117 }
118 };
119 newBalloonRound();
120 sendBalloonsData();
121 }
122 }
123 }
124}
125
126function newBalloonRound() {
127 balloons.status = Status.WAITING;
128 let secret = randomSecret();
129 balloons.gameHash = crypto.createHash('md5').update(secret + '-' + balloons.precentage).digest('hex');
130 balloons.precentage = Math.random()*100.0;
131 balloons.gameTimer = 15;
132 balloons.players = [];
133 mysql.newGame({precentage:balloons.precentage,hash:balloons.gameHash,secret:secret}, (err,res) => {
134 if(err)
135 throw err;
136 else {
137 balloons.gameId = res.insertId;
138 }
139 });
140}
141
142function randomSecret() {
143 return Math.random().toString(36).substring(7);
144}
145
146io.on('connect', (socket) => {
147 let socketuser;
148 console.log("connection");
149
150 // If user is logged in, assign the user object to 'socketuser'
151 if (socket.handshake.session.passport && socket.handshake.session.passport.user)
152 socketuser = socket.handshake.session.passport.user;
153
154 socket.emit('loadMessages', JSON.stringify(chatMessages));
155 if(socketuser == null)
156 return;
157
158 mysql.getUserData(socketuser.id64, (err,result) => {
159 if(err)
160 throw err;
161 else {
162 socketuser.balance = result[0].balance;
163 sendUserInformation(socket ,socketuser);
164 }
165 });
166
167 for(let u in users) {
168 if(users[u] == null)
169 continue;
170
171 if(users[u].user.id64 == socketuser.id64)
172 users[u] = null;
173 }
174
175 users.push({user: socketuser, socket: socket});
176
177 socket.on('newMessage', (data) => {
178 let message = JSON.parse(data);
179 if(chatMessages.push({id64: socketuser.id64, avatar: socketuser.avatar, username: socketuser.username,message: message.message}) == 20) // change to 11
180 chatMessages.splice(0,1);
181
182 io.emit('newMessage',data);
183 });
184
185 socket.on('placeBalloonBet', (data) => {
186 let bet = JSON.parse(data);
187 if (balloons.status == Status.END)
188 return socket.emit('errorMsg', JSON.stringify({message: 'Round is over, bets cannot be placed at the moment.'}));
189 else if (didPlayerBet(socketuser.id64))
190 return socket.emit('errorMsg', JSON.stringify({message: 'You can place only 1 bet per round.'}));
191 else if (bet.amount < 0.1 || bet.amount > 2000)
192 return socket.emit('errorMsg', JSON.stringify({message: 'Minimum bet amount is 0.1CR and Maximum is 2,000CR'}));
193 else if (bet.chance < 1.10 || bet.chance > 10.0)
194 return socket.emit('errorMsg', JSON.stringify({message: 'Minimum chance is 1.1X and Maxmimum is 10.0X'}));
195 else if(bet.amount > socketuser.balance)
196 return socket.emit('errorMsg', JSON.stringify({message: 'You have insufficient funds!'}));
197
198 socketuser.balance -= bet.amount;
199 mysql.updateUser({username: socketuser.username, balance: socketuser.balance, id64: socketuser.id64});
200 sendUserInformation(socket, socketuser);
201 mysql.newBet({
202 username: socketuser.username,
203 id64: socketuser.id64,
204 chance: bet.chance,
205 bet: bet.amount,
206 gameid: balloons.gameId
207 });
208 balloons.players.push( {
209 id64: socketuser.id64,
210 avatar: socketuser.avatar,
211 username: socketuser.username,
212 chance: bet.chance,
213 bet: bet.amount
214 });
215 sendBalloonsData();
216 });
217});
218
219function User(id64) {
220 for(let u in users) {
221 if(users[u] == null)
222 continue;
223
224 if(users[u].user.id64 == id64)
225 return users[u];
226 }
227 return {user: null, socket: null};
228}
229
230function didPlayerBet(id64) {
231 for(let p in balloons.players) {
232 if(balloons.players[p].id64 == id64) {
233 return true;
234 }
235 }
236
237 return false;
238}
239
240function sendUserInformation(socket, socketuser) {
241 socket.emit('UserLoggedIn', JSON.stringify({id: socketuser.id, id64: socketuser.id64, username: socketuser.username, avatar: socketuser.avatar, balance: socketuser.balance}));
242}
243
244function sendBalloonsData() {
245 let tempPrecent = balloons.precentage;
246 let data = balloons;
247 delete data.precentage;
248 if(data.status == Status.END) {
249 for(let p in data.players) {
250 if(100.0 / data.players[p].chance > tempPrecent) data.players[p].win = 1;
251 else data.players[p].win = 0;
252 };
253 }
254 io.emit('balloonsData', JSON.stringify(data));
255 data.precentage = tempPrecent;
256}
257
258//OPSkins Authentication
259let OpskinsAuth = new opAuth.init({
260 name: config.loginName,
261 returnURL: config.returnUrl,
262 apiKey: config.opskinsApiKey,
263 scopes: 'identity',
264 mobile: true
265});
266
267passport.use('custom', new CustomStrategy(function (req, done) {
268 OpskinsAuth.authenticate(req, (err, user) => {
269 if (err) {
270 done(err);
271 } else {
272 mysql.userLogin(user);
273 mysql.getUserData(user.id64, (err,result) => {
274 if(err)
275 throw err;
276 else {
277 user.balance = result[0].balance;
278 done(null, user);
279 }
280 });
281 }
282 });
283}));
284
285function onAuthorizeSuccess(data, accept) {
286 accept();
287}
288
289function onAuthorizeFail(data, message, error, accept) {
290 accept(null, !error);
291}
292
293
294app.get('/auth/opskins', function (req, res) {
295 res.redirect(OpskinsAuth.getFetchUrl());
296});
297
298app.get('/auth/opskins/authenticate', passport.authenticate('custom', {
299 failureRedirect: '/'
300}), function (req, res) {
301 res.redirect('/');
302});
303
304app.get('/logout', (req, res) => {
305 req.logout();
306 res.redirect('/');
307});
308
309
310// Set Angular Direction to everything else
311app.get('*', (req, res) => {
312 res.sendFile(path.join(__dirname, 'dist/vgoballoon/index.html'));
313});
314
315// Port
316const port = process.env.PORT || 4600;
317
318// Start Server
319server.listen(port, () => {
320 console.log(`Server started on port ${port}`);
321 newBalloonRound();
322 setInterval(balloonHandler, 1000);
323});