index.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. const MusicBot = require ( './musicbot.js' );
  2. const Config = require ( './config.json' );
  3. const logger = require ( './logger.js' );
  4. const https = require ( 'https' );
  5. const fs = require ( 'fs' );
  6. const url = require ( 'url' );
  7. const path = require ( 'path' );
  8. const crypto = require ( 'crypto' );
  9. const Cookies = require ( 'cookies' );
  10. logger.initialize ( );
  11. const mimeTypes =
  12. {
  13. 'js': 'application/javascript',
  14. 'json': 'application/json',
  15. 'ogg': 'application/ogg',
  16. 'mp3': 'audio/mpeg',
  17. 'wav': 'audio/x-wav',
  18. 'gif': 'image/gif',
  19. 'jpg': 'image/jpeg',
  20. 'jpeg': 'image/jpeg',
  21. 'png': 'image/png',
  22. 'css': 'text/css',
  23. 'html': 'text/html',
  24. 'xml': 'text/xml',
  25. 'txt': 'text/plain'
  26. };
  27. const options =
  28. {
  29. key: fs.readFileSync ( Config.https.key ),
  30. cert: fs.readFileSync ( Config.https.cert )
  31. };
  32. let requestHandlers = { };
  33. function renderTemplate ( template, request, response, data )
  34. {
  35. let filepath = './templates/' + template + '.html';
  36. if ( fs.existsSync ( filepath ) )
  37. {
  38. let buffer = fs.readFileSync ( filepath ).toString ( );
  39. for ( let key in data )
  40. buffer = buffer.replace ( new RegExp ( '{{' + key + '}}', 'g' ), data [key] );
  41. response.write ( buffer );
  42. }
  43. }
  44. function redirectRequest ( request, response, url )
  45. {
  46. response.writeHead ( 302, {
  47. 'Location': url
  48. } );
  49. response.end ( );
  50. }
  51. function registerRequestHandler ( path, handler )
  52. {
  53. if ( typeof path !== "string" ) return false;
  54. if ( typeof handler !== "function" ) return false;
  55. if ( !requestHandlers [path] )
  56. {
  57. logger.log ( '[Info/WebServer] Registered request handler for ' + path );
  58. requestHandlers [path] = handler;
  59. return true;
  60. }
  61. return false;
  62. }
  63. function getRequestData ( request )
  64. {
  65. let requestData = { };
  66. let urlObject = url.parse ( request.url, true );
  67. requestData.path = urlObject.pathname;
  68. requestData.query = urlObject.query;
  69. requestData.ip = request.connection.remoteAddress;
  70. return requestData;
  71. }
  72. function getMimeType ( filepath )
  73. {
  74. let defaultMimeType = 'application/octet-stream';
  75. let extension = path.extname ( filepath ).substring ( 1, this.length );
  76. if ( mimeTypes [extension] ) return mimeTypes [extension];
  77. else return defaultMimeType;
  78. }
  79. function createDefaultResponse ( request, response, requestData )
  80. {
  81. let fullPath = './frontend' + requestData.path;
  82. fullPath = fullPath.replace( /\.\.\//g, '' );
  83. if ( fs.existsSync ( fullPath ) && fs.lstatSync ( fullPath ).isDirectory ( ) )
  84. fullPath = fullPath + 'index.html';
  85. if ( fs.existsSync ( fullPath ) )
  86. {
  87. let mimeType = getMimeType ( fullPath );
  88. let stat = fs.statSync ( fullPath );
  89. response.writeHead ( 200,
  90. {
  91. 'Content-Type': mimeType,
  92. 'Content-Length': stat.size
  93. } );
  94. let readStream = fs.createReadStream ( fullPath )
  95. readStream.pipe ( response );
  96. }
  97. else
  98. {
  99. logger.log ( '[Info/WebServer] Outgoing Rsponse 404. File: ' + fullPath );
  100. // display error page
  101. response.writeHead ( 404, { 'Content-Type': 'text/html' } );
  102. response.write ( '<h1>Not Found</h1>' );
  103. response.end ( );
  104. }
  105. }
  106. let sessions = { };
  107. function terminateSession ( sessionID )
  108. {
  109. logger.log ( '[Info/WebServer] Terminating session ' + sessionID );
  110. delete sessions [sessionID];
  111. }
  112. function renewSession ( sessionID, cookies )
  113. {
  114. logger.log ( '[Info/WebServer] Renewing session ' + sessionID );
  115. clearTimeout ( sessions [sessionID].timeout );
  116. sessions [sessionID].timeout = setTimeout ( function ( ) { terminateSession ( sessionID ); }, Config.session_duration );
  117. sessions [sessionID].expires = Date.now ( ) + Config.session_duration;
  118. cookies.set ( 'session_id', sessionID, { expires: new Date ( sessions [sessionID].expires ) } );
  119. }
  120. function getRequestSession ( request, requestData, cookies )
  121. {
  122. let sessionID = cookies.get ( 'session_id' );
  123. if ( sessionID )
  124. {
  125. if ( sessions [sessionID] )
  126. {
  127. renewSession ( sessionID, cookies );
  128. return sessions [sessionID];
  129. }
  130. }
  131. sessionID = crypto.randomBytes ( 12 ).toString ( 'base64' );
  132. let newSession = { };
  133. newSession.id = sessionID;
  134. newSession.started = Date.now ( );
  135. newSession.expires = newSession.started + Config.session_duration;
  136. newSession.timeout = setTimeout ( function ( ) { terminateSession ( sessionID ); }, Config.session_duration );
  137. newSession.variables = { };
  138. cookies.set ( 'session_id', sessionID, { expires: new Date ( newSession.expires ) } );
  139. sessions [sessionID] = newSession;
  140. logger.log ( '[Info/WebServer] Starting new session ' + sessionID );
  141. return sessions [sessionID];
  142. }
  143. const server = https.createServer ( options, function ( request, response )
  144. {
  145. let requestData = getRequestData ( request );
  146. let cookies = Cookies ( request, response );
  147. let session = getRequestSession ( request, response, cookies );
  148. logger.log ( '[Info/WebServer] Incomming Request ' + requestData.path + ' from ' + requestData.ip );
  149. if ( requestHandlers [requestData.path] )
  150. {
  151. try
  152. {
  153. requestHandlers [requestData.path] ( request, response, requestData, cookies, session );
  154. }
  155. catch ( error )
  156. {
  157. logger.log ( '[Info/WebServer] Outgoing Rsponse 500' );
  158. logger.error ( error );
  159. // display error page
  160. response.writeHead ( 500, { 'Content-Type': 'text/html' } );
  161. response.write ( '<h1>Internal Server Error</h1>' );
  162. response.end ( );
  163. }
  164. }
  165. else
  166. {
  167. createDefaultResponse ( request, response, requestData );
  168. }
  169. } );
  170. module.exports.registerRequestHandler = registerRequestHandler;
  171. module.exports.redirect = redirectRequest;
  172. module.exports.renderTemplate = renderTemplate;
  173. require ( './handlers.js' );
  174. function runMusicBot ( )
  175. {
  176. try
  177. {
  178. MusicBot.run ( );
  179. }
  180. catch ( error )
  181. {
  182. logger.error ( error );
  183. setTimeout ( function ( ) { runMusicBot ( ); }, 500 );
  184. }
  185. }
  186. server.listen ( 3000 );
  187. runMusicBot ( );