index.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. "use strict";
  2. var fs = require('fs');
  3. var os = require('os');
  4. var proc = require('child_process');
  5. var app = require('express')();
  6. var server = require('http').Server(app);
  7. var io = require('socket.io')(server);
  8. var playLists = {};
  9. var currentPlayer;
  10. var currentSong;
  11. // Save played songs and randomly play them when we run out
  12. var playedSongs = [];
  13. var options = {};
  14. process.argv.slice(2).forEach(function (value) {
  15. if (value.indexOf("--") === 0) {
  16. value = value.split("=")
  17. options[value[0].slice(2)] = value[1];
  18. };
  19. });
  20. try {
  21. fs.mkdirSync('downloads');
  22. } catch (e) {
  23. if (e.code !== 'EEXIST') {
  24. throw e;
  25. }
  26. }
  27. var sendCurrentSong = function () {
  28. console.log("Sending song");
  29. io.sockets.emit('newSong', {url: currentSong});
  30. };
  31. var nextSong = function () {
  32. if (Object.keys(playLists).length === 0) {
  33. console.log("No songs possible. Nothing has been added yet.");
  34. return;
  35. }
  36. if (playLists[currentPlayer] && playLists[currentPlayer].length >= 1) {
  37. playedSongs.push(playLists[currentPlayer].shift());
  38. }
  39. var tries = 0;
  40. var currentIndex;
  41. while (tries < Object.keys(playLists).length) {
  42. currentIndex = Object.keys(playLists).indexOf(currentPlayer);
  43. if (currentIndex === -1 || Object.keys(playLists).length === currentIndex + 1) {
  44. currentIndex = 0;
  45. } else {
  46. currentIndex += 1;
  47. }
  48. currentPlayer = Object.keys(playLists)[currentIndex];
  49. if (playLists[currentPlayer] && playLists[currentPlayer].length >= 1) {
  50. currentSong = playLists[currentPlayer][0];
  51. sendCurrentSong();
  52. return;
  53. }
  54. tries += 1;
  55. }
  56. console.log("No songs in queue");
  57. if (playedSongs.length > 0) {
  58. console.log("Grabbing random song from backlog");
  59. currentSong = playedSongs[Math.floor(Math.random() * playedSongs.length)];
  60. sendCurrentSong();
  61. return;
  62. }
  63. };
  64. io.on('connection', function (socket) {
  65. console.log("New connection");
  66. if (currentSong) {
  67. sendCurrentSong();
  68. } else {
  69. nextSong(false);
  70. }
  71. socket.on('songEnd', function () {
  72. console.log("Song ended");
  73. nextSong(true);
  74. });
  75. });
  76. app.get('/', function (ignore, res) {
  77. res.sendFile(__dirname + '/index.html');
  78. });
  79. app.get('/currentFile', function (ignore, res) {
  80. var filename = currentSong.split('/').join('_')
  81. fs.lstat('downloads/' + filename + '.ogg', function (err) {
  82. if (err && err.code === 'ENOENT') {
  83. console.log(currentSong + " cannot be sent: " + err + ". Skipping.");
  84. var index = playedSongs.indexOf(currentSong);
  85. // Remove song from previous playlist if it exists
  86. if (index != -1) {
  87. playedSongs.splice(index, 1);
  88. }
  89. nextSong(true);
  90. } else {
  91. res.sendFile(__dirname + '/downloads/' + currentSong.split('/').join('_') + '.ogg');
  92. }
  93. });
  94. });
  95. app.get('/play', function (req, res) {
  96. if (options.playpassword !== undefined) {
  97. if (req.query.pass === undefined) {
  98. res.send('Password required. Please add ?pass= followed by the password to the end of this URL.');
  99. return;
  100. }
  101. if (req.query.pass !== options.playpassword) {
  102. res.send('Incorrect password.');
  103. return;
  104. }
  105. }
  106. res.sendFile(__dirname + '/play.html');
  107. });
  108. app.get('/add', function (req, res) {
  109. if (!req.query.url) {
  110. res.send('Cannot add empty URL');
  111. return;
  112. }
  113. var user = req.connection.remoteAddress;
  114. if (playLists[user] === undefined) {
  115. playLists[user] = [];
  116. }
  117. var filename = req.query.url.split('/').join('_');
  118. var addDone = function () {
  119. console.log("Adding of %s completed", req.query.url);
  120. if (!currentSong) {
  121. console.log("Nothing playing. Forcing next song");
  122. nextSong(false);
  123. }
  124. };
  125. fs.lstat('downloads/' + filename + '.ogg', function (err) {
  126. if (err && err.code === 'ENOENT') {
  127. console.log("%s doesn't exist, will download", req.query.url);
  128. var command = proc.spawn('./youtube-dl', [req.query.url, '--extract-audio', '--audio-format=vorbis', '-o', 'downloads/' + req.query.url.split('/').join('_') + '.ogg']);
  129. command.on('exit', function (code) {
  130. if (code !== 0) {
  131. res.send("Failed to add " + req.query.url + ": Error code " + code);
  132. console.log("Failed to add %s: Error code %s", req.query.url, code);
  133. return;
  134. }
  135. res.send("Link downloaded and added.");
  136. playLists[user].push(req.query.url);
  137. addDone();
  138. });
  139. } else {
  140. res.send("Link queued from cache.");
  141. console.log("File in cache");
  142. playLists[user].push(req.query.url);
  143. addDone();
  144. }
  145. });
  146. });
  147. server.listen(3000, function () {
  148. var networkInterfaces = os.networkInterfaces();
  149. Object.keys(networkInterfaces).forEach(function (networkInterface) {
  150. networkInterface = networkInterfaces[networkInterface];
  151. Object.keys(networkInterface).forEach(function (interfaceEntry) {
  152. console.log('PlayByTurn listening at http://%s:3000', networkInterface[interfaceEntry].address);
  153. });
  154. });
  155. });