index.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. const fs = require('fs');
  2. const https = require('https');
  3. const seedrandom = require('seedrandom');
  4. const express = require('express');
  5. const app = express();
  6. const options = {
  7. key: fs.readFileSync("ssl/private.key"),
  8. cert: fs.readFileSync("ssl/certificate.crt"),
  9. ca: [fs.readFileSync('ssl/ca_bundle.crt')]
  10. };
  11. const server = https.createServer(options, app);
  12. const io = require('socket.io')(server);
  13. const PORT = 443;
  14. const admins = {
  15. 'André': 'passwort'
  16. }
  17. var users = [];
  18. var bannedIps = [];
  19. fs.readFile("config/ban.json", "utf8", (err, data) => {
  20. if (!err) {
  21. bannedIps = JSON.parse(data);
  22. }
  23. })
  24. const randomColors = [
  25. '#c42020',
  26. '#de801e',
  27. '#f6c60b',
  28. '#19ce19',
  29. '#129696',
  30. '#2c53e3',
  31. '#6f23e3',
  32. '#883f88',
  33. ];
  34. const HISTORY_SIZE = 50;
  35. var history = [];
  36. app.use(express.static(__dirname + '/www'));
  37. app.use('/node_modules', express.static(__dirname + '/node_modules'));
  38. app.get('/img/ava/:username', (req, res) => {
  39. var file = '';
  40. if (fs.existsSync(__dirname + '/www/img/ava/' + req.params.username + '.png')) {
  41. file = __dirname + '/www/img/ava/' + req.params.username + '.png';
  42. } else {
  43. const files = fs.readdirSync(__dirname + '/www/img/ava/random/');
  44. const seededRandom = seedrandom(req.params.username)();
  45. const randomFile = files[Math.floor(seededRandom * files.length)];
  46. file = __dirname + '/www/img/ava/random/' + randomFile;
  47. }
  48. res.sendFile(file);
  49. });
  50. io.on('connection', (socket) => {
  51. const ip = socket.handshake.address;
  52. log('- New user joined the server:', ip);
  53. for (const bannedItem of bannedIps) {
  54. if (bannedItem.ip == ip) {
  55. log('- User blacklisted, kicking:', ip)
  56. socket.emit('serverKick');
  57. socket.disconnect();
  58. break;
  59. }
  60. }
  61. socket.emit('serverHandshake');
  62. const user = {ip: ip, socket: socket};
  63. users.push(user);
  64. socket.on('login', (username, password) => {
  65. if (!username) {
  66. socket.emit('usernameInvalid');
  67. return;
  68. }
  69. for (let user of users) {
  70. if (user.name == username) {
  71. socket.emit('usernameTaken');
  72. return;
  73. }
  74. }
  75. if (admins && admins[username]) {
  76. if (!password) {
  77. log('- Attempted login as admin without password.', username, '(' + ip + ')');
  78. socket.emit('passwordRequired');
  79. return;
  80. } else if (admins[username] != password) {
  81. log('- Attempted login as admin with wrong password.', username, '(' + ip + ')');
  82. socket.emit('passwordWrong');
  83. return;
  84. }
  85. log('- Admin "' + username + '" login successful');
  86. user.admin = true;
  87. socket.on('requestKick', (userToBeKicked) => {
  88. log('- Admin "' + username + '" requested kick of User "' + userToBeKicked.name + '"');
  89. kickUser(userToBeKicked);
  90. });
  91. socket.on('requestLiftBan', (ip) => {
  92. log('- Admin "' + username + '" requested to lift ban for ip "' + ip + '"');
  93. liftBan(ip);
  94. });
  95. }
  96. log('- New user logged in:', username, '(' + ip + ')');
  97. user.name = username;
  98. user.color = getRandomColor(username);
  99. socket.emit('serverLogin', getCleanUser(user), history);
  100. io.emit('userJoined', username);
  101. updateUsers();
  102. updateBanned();
  103. socket.on('disconnect', () => {
  104. log('- User joined the server:', ip);
  105. users = users.filter((listUser) => listUser !== user);
  106. io.emit('userLeft', username);
  107. updateUsers();
  108. });
  109. socket.on('message', (msg) => {
  110. if (msg) {
  111. log(user.name + ':', msg, '(' + user.ip + ')');
  112. if (history.length >= HISTORY_SIZE) {
  113. history = history.slice(1);
  114. }
  115. history.push({msg: msg, user: getCleanUser(user), timestamp: Date.now()});
  116. io.emit('message', msg, getCleanUser(user), Date.now());
  117. }
  118. });
  119. });
  120. });
  121. function updateUsers() {
  122. io.emit('usersUpdated', users.filter((user) => user.name != null).map(getCleanUser));
  123. }
  124. function getCleanUser(user) {
  125. return {
  126. name: user.name,
  127. admin: user.admin,
  128. color: user.color
  129. }
  130. }
  131. function kickUser(user) {
  132. let ip;
  133. for (const exUser of users) {
  134. if (exUser.name == user.name) {
  135. ip = exUser.ip;
  136. break;
  137. }
  138. }
  139. bannedIps.push({ip: ip, user: user});
  140. updateBanned();
  141. for (const exUser of users) {
  142. if (exUser.ip == ip) {
  143. exUser.socket.emit('serverKick');
  144. exUser.socket.disconnect();
  145. }
  146. }
  147. }
  148. function liftBan(ip) {
  149. bannedIps = bannedIps.filter((listItem) => listItem.ip != ip);
  150. updateBanned();
  151. }
  152. function updateBanned() {
  153. fs.writeFile('config/ban.json', JSON.stringify(bannedIps), (e) => {
  154. });
  155. io.emit('bannedUpdated', bannedIps);
  156. }
  157. function getRandomColor(seed) {
  158. return randomColors[Math.floor(seedrandom(seed)() * randomColors.length)];
  159. }
  160. function log(...inputs) {
  161. var output = '[' + new Date().toISOString().substr(0, 19).replace('T', ', ') + '] ';
  162. for (const i of inputs) {
  163. output += i + ' ';
  164. }
  165. console.log(output);
  166. fs.appendFile('log.txt', '' + output + '\n', (e) => {
  167. });
  168. }
  169. server.listen(PORT, () => {
  170. log('- Server up and running at port ' + PORT);
  171. });