queueSongs.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. 'use strict';
  2. const db = require('../db');
  3. const utils = require('../utils');
  4. const logger = require('../logger');
  5. const notifications = require('../notifications');
  6. const cache = require('../cache');
  7. const async = require('async');
  8. const config = require('config');
  9. const request = require('request');
  10. const hooks = require('./hooks');
  11. cache.sub('queue.newSong', songId => {
  12. db.models.queueSong.findOne({_id: songId}, (err, song) => {
  13. utils.emitToRoom('admin.queue', 'event:admin.queueSong.added', song);
  14. });
  15. });
  16. cache.sub('queue.removedSong', songId => {
  17. utils.emitToRoom('admin.queue', 'event:admin.queueSong.removed', songId);
  18. });
  19. cache.sub('queue.updatedSong', songId => {
  20. //TODO Retrieve new Song object
  21. utils.emitToRoom('admin.queue', 'event:queueSong.updated', { songId });
  22. });
  23. module.exports = {
  24. /**
  25. * Gets all queuesongs
  26. *
  27. * @param {Object} session - the session object automatically added by socket.io
  28. * @param {Function} cb - gets called with the result
  29. */
  30. index: hooks.adminRequired((session, cb) => {
  31. async.waterfall([
  32. (next) => {
  33. db.models.queueSong.find({}, next);
  34. }
  35. ], (err, songs) => {
  36. if (err) {
  37. logger.log("QUEUE_INDEX", "ERROR", `Indexing queuesongs failed. "${err.message}"`);
  38. return cb({status: 'failure', message: 'Something went wrong.'});
  39. }
  40. logger.log("QUEUE_INDEX", "SUCCESS", `Indexing queuesongs successful.`);
  41. return cb(songs);
  42. });
  43. }),
  44. /**
  45. * Updates a queuesong
  46. *
  47. * @param {Object} session - the session object automatically added by socket.io
  48. * @param {String} songId - the id of the queuesong that gets updated
  49. * @param {Object} updatedSong - the object of the updated queueSong
  50. * @param {Function} cb - gets called with the result
  51. * @param {String} userId - the userId automatically added by hooks
  52. */
  53. update: hooks.adminRequired((session, songId, updatedSong, cb, userId) => {
  54. async.waterfall([
  55. (next) => {
  56. db.models.queueSong.findOne({ _id: songId }, next);
  57. },
  58. (song, next) => {
  59. if(!song) return next('Song not found');
  60. let updated = false;
  61. let $set = {};
  62. for (let prop in updatedSong) if (updatedSong[prop] !== song[prop]) $set[prop] = updatedSong[prop]; updated = true;
  63. if (!updated) return next('No properties changed');
  64. db.models.queueSong.update({ _id: songId }, {$set}, next);
  65. }
  66. ], (err) => {
  67. if (err) {
  68. let error = 'An error occurred.';
  69. if (typeof err === "string") error = err;
  70. else if (err.message) error = err.message;
  71. logger.log("QUEUE_UPDATE", "ERROR", `Updating queuesong "${songId}" failed for user ${userId}. "${err.message}"`);
  72. return cb({status: 'failure', message: error});
  73. }
  74. cache.pub('queue.updatedSong', songId);
  75. logger.log("QUEUE_UPDATE", "SUCCESS", `User "${userId}" successfully update queuesong "${songId}".`);
  76. return cb({status: 'success', message: 'Successfully updated song.'});
  77. });
  78. }),
  79. /**
  80. * Removes a queuesong
  81. *
  82. * @param {Object} session - the session object automatically added by socket.io
  83. * @param {String} songId - the id of the queuesong that gets removed
  84. * @param {Function} cb - gets called with the result
  85. * @param {String} userId - the userId automatically added by hooks
  86. */
  87. remove: hooks.adminRequired((session, songId, cb, userId) => {
  88. async.waterfall([
  89. (next) => {
  90. db.models.queueSong.remove({ _id: songId }, next);
  91. }
  92. ], (err) => {
  93. if (err) {
  94. let error = 'An error occurred.';
  95. if (typeof err === "string") error = err;
  96. else if (err.message) error = err.message;
  97. logger.log("QUEUE_REMOVE", "ERROR", `Removing queuesong "${songId}" failed for user ${userId}. "${err.message}"`);
  98. return cb({status: 'failure', message: error});
  99. }
  100. cache.pub('queue.removedSong', songId);
  101. logger.log("QUEUE_REMOVE", "SUCCESS", `User "${userId}" successfully removed queuesong "${songId}".`);
  102. return cb({status: 'success', message: 'Successfully updated song.'});
  103. });
  104. }),
  105. /**
  106. * Creates a queuesong
  107. *
  108. * @param {Object} session - the session object automatically added by socket.io
  109. * @param {String} songId - the id of the song that gets added
  110. * @param {Function} cb - gets called with the result
  111. * @param {String} userId - the userId automatically added by hooks
  112. */
  113. add: hooks.loginRequired((session, songId, cb, userId) => {
  114. let requestedAt = Date.now();
  115. async.waterfall([
  116. (next) => {
  117. db.models.queueSong.findOne({_id: songId}, next);
  118. },
  119. (song, next) => {
  120. if (song) return next('This song is already in the queue.');
  121. db.models.song.findOne({_id: songId}, next);
  122. },
  123. // Get YouTube data from id
  124. (song, next) => {
  125. if (song) return next('This song has already been added.');
  126. //TODO Add err object as first param of callback
  127. utils.getSongFromYouTube(songId, (song) => {
  128. song.artists = [];
  129. song.genres = [];
  130. song.skipDuration = 0;
  131. song.thumbnail = 'empty';
  132. song.explicit = false;
  133. song.requestedBy = userId;
  134. song.requestedAt = requestedAt;
  135. next(null, song);
  136. });
  137. },
  138. (newSong, next) => {
  139. //TODO Add err object as first param of callback
  140. utils.getSongFromSpotify(newSong, (song) => {
  141. next(null, song);
  142. });
  143. },
  144. (newSong, next) => {
  145. const song = new db.models.queueSong(newSong);
  146. song.save(err => {
  147. if (err) return next(err);
  148. next(null, newSong);
  149. });
  150. }
  151. ], (err, newSong) => {
  152. if (err) {
  153. let error = 'An error occurred.';
  154. if (typeof err === "string") error = err;
  155. else if (err.message) error = err.message;
  156. return cb({status: 'failure', message: error});
  157. }
  158. cache.pub('queue.newSong', newSong._id);
  159. return cb({ status: 'success', message: 'Successfully added that song to the queue' });
  160. });
  161. })
  162. };