index.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. 'use strict';
  2. process.env.NODE_CONFIG_DIR = `${__dirname}/config`;
  3. const async = require('async');
  4. const fs = require('fs');
  5. //const Discord = require("discord.js");
  6. //const client = new Discord.Client();
  7. const db = require('./logic/db');
  8. const app = require('./logic/app');
  9. const mail = require('./logic/mail');
  10. const api = require('./logic/api');
  11. const io = require('./logic/io');
  12. const stations = require('./logic/stations');
  13. const songs = require('./logic/songs');
  14. const playlists = require('./logic/playlists');
  15. const cache = require('./logic/cache');
  16. const discord = require('./logic/discord');
  17. const notifications = require('./logic/notifications');
  18. const punishments = require('./logic/punishments');
  19. const logger = require('./logic/logger');
  20. const tasks = require('./logic/tasks');
  21. const config = require('config');
  22. let currentComponent;
  23. let initializedComponents = [];
  24. let lockdownB = false;
  25. process.on('uncaughtException', err => {
  26. if (lockdownB || err.code === 'ECONNREFUSED' || err.code === 'UNCERTAIN_STATE') return;
  27. console.log(`UNCAUGHT EXCEPTION: ${err.stack}`);
  28. });
  29. const getError = (err) => {
  30. let error = 'An error occurred.';
  31. if (typeof err === "string") error = err;
  32. else if (err.message) {
  33. if (err.message !== 'Validation failed') error = err.message;
  34. else error = err.errors[Object.keys(err.errors)].message;
  35. }
  36. return error;
  37. };
  38. function lockdown() {
  39. if (lockdownB) return;
  40. lockdownB = true;
  41. initializedComponents.forEach((component) => {
  42. component._lockdown();
  43. });
  44. console.log("Backend locked down.");
  45. }
  46. function errorCb(message, err, component) {
  47. err = getError(err);
  48. lockdown();
  49. discord.sendAdminAlertMessage(message, "#FF0000", message, true, [{name: "Error:", value: err, inline: false}, {name: "Component:", value: component, inline: true}]); //TODO Maybe due to lockdown this won't work, and what if the Discord module was the one that failed?
  50. }
  51. function moduleStartFunction() {
  52. logger.info("MODULE_START", `Starting to initialize component '${currentComponent}'`);
  53. }
  54. async.waterfall([
  55. // setup our Discord module
  56. (next) => {
  57. currentComponent = 'Discord';
  58. moduleStartFunction();
  59. discord.init(config.get('apis.discord').token, config.get('apis.discord').loggingChannel, errorCb, () => {
  60. next();
  61. });
  62. },
  63. // setup our Redis cache
  64. (next) => {
  65. currentComponent = 'Cache';
  66. moduleStartFunction();
  67. cache.init(config.get('redis').url, config.get('redis').password, errorCb, () => {
  68. next();
  69. });
  70. },
  71. // setup our MongoDB database
  72. (next) => {
  73. initializedComponents.push(cache);
  74. currentComponent = 'DB';
  75. moduleStartFunction();
  76. db.init(config.get("mongo").url, errorCb, next);
  77. },
  78. // setup the express server
  79. (next) => {
  80. initializedComponents.push(db);
  81. currentComponent = 'App';
  82. moduleStartFunction();
  83. app.init(next);
  84. },
  85. // setup the mail
  86. (next) => {
  87. initializedComponents.push(app);
  88. currentComponent = 'Mail';
  89. moduleStartFunction();
  90. mail.init(next);
  91. },
  92. // setup the socket.io server (all client / server communication is done over this)
  93. (next) => {
  94. initializedComponents.push(mail);
  95. currentComponent = 'IO';
  96. moduleStartFunction();
  97. io.init(next);
  98. },
  99. // setup the punishment system
  100. (next) => {
  101. initializedComponents.push(io);
  102. currentComponent = 'Punishments';
  103. moduleStartFunction();
  104. punishments.init(next);
  105. },
  106. // setup the notifications
  107. (next) => {
  108. initializedComponents.push(punishments);
  109. currentComponent = 'Notifications';
  110. moduleStartFunction();
  111. notifications.init(config.get('redis').url, config.get('redis').password, errorCb, next);
  112. },
  113. // setup the stations
  114. (next) => {
  115. initializedComponents.push(notifications);
  116. currentComponent = 'Stations';
  117. moduleStartFunction();
  118. stations.init(next)
  119. },
  120. // setup the songs
  121. (next) => {
  122. initializedComponents.push(stations);
  123. currentComponent = 'Songs';
  124. moduleStartFunction();
  125. songs.init(next)
  126. },
  127. // setup the playlists
  128. (next) => {
  129. initializedComponents.push(songs);
  130. currentComponent = 'Playlists';
  131. moduleStartFunction();
  132. playlists.init(next)
  133. },
  134. // setup the API
  135. (next) => {
  136. initializedComponents.push(playlists);
  137. currentComponent = 'API';
  138. moduleStartFunction();
  139. api.init(next)
  140. },
  141. // setup the logger
  142. (next) => {
  143. initializedComponents.push(api);
  144. currentComponent = 'Logger';
  145. moduleStartFunction();
  146. logger.init(next)
  147. },
  148. // setup the tasks system
  149. (next) => {
  150. initializedComponents.push(logger);
  151. currentComponent = 'Tasks';
  152. moduleStartFunction();
  153. tasks.init(next)
  154. },
  155. // setup the frontend for local setups
  156. (next) => {
  157. initializedComponents.push(tasks);
  158. currentComponent = 'Windows';
  159. moduleStartFunction();
  160. if (!config.get("isDocker") && !(config.get("mode") === "development" || config.get("mode") === "dev")) {
  161. const express = require('express');
  162. const app = express();
  163. app.listen(config.get("frontendPort"));
  164. const rootDir = __dirname.substr(0, __dirname.lastIndexOf("backend")) + "frontend/dist/build";
  165. app.use(express.static(rootDir, {
  166. setHeaders: function(res, path) {
  167. if (path.indexOf('.html') !== -1) res.setHeader('Cache-Control', 'public, max-age=0');
  168. else res.setHeader('Cache-Control', 'public, max-age=2628000');
  169. }
  170. }));
  171. app.get("/*", (req, res) => {
  172. res.sendFile(`${rootDir}/index.html`);
  173. });
  174. }
  175. if (lockdownB) return;
  176. next();
  177. }
  178. ], (err) => {
  179. if (err && err !== true) {
  180. lockdown();
  181. discord.sendAdminAlertMessage("An error occurred while initializing the backend server.", "#FF0000", "Startup error", true, [{name: "Error:", value: err, inline: false}, {name: "Component:", value: currentComponent, inline: true}]);
  182. console.error('An error occurred while initializing the backend server');
  183. } else {
  184. discord.sendAdminAlertMessage("The backend server started successfully.", "#00AA00", "Startup", false, []);
  185. console.info('Backend server has been successfully started');
  186. }
  187. });