index.js 6.0 KB

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