queueSongs.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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({ songId }, next);
  57. },
  58. (song, next) => {
  59. let updated = false;
  60. let $set = {};
  61. for (let prop in updatedSong) if (updatedSong[prop] !== song[prop]) $set[prop] = updatedSong[prop]; updated = true;
  62. if (!updated) return next('No properties changed');
  63. db.models.queueSong.update({ _id: songId }, {$set}, next);
  64. }
  65. ], (err) => {
  66. if (err) {
  67. let error = 'An error occurred.';
  68. if (typeof err === "string") error = err;
  69. else if (err.message) error = err.message;
  70. logger.log("QUEUE_UPDATE", "ERROR", `Updating queuesong "${songId}" failed for user ${userId}. "${err.message}"`);
  71. return cb({status: 'failure', message: error});
  72. }
  73. cache.pub('queue.updatedSong', songId);
  74. logger.log("QUEUE_UPDATE", "SUCCESS", `User "${userId}" successfully update queuesong "${songId}".`);
  75. return cb({status: 'success', message: 'Successfully updated song.'});
  76. });
  77. }),
  78. /**
  79. * Removes a queuesong
  80. *
  81. * @param {Object} session - the session object automatically added by socket.io
  82. * @param {String} songId - the id of the queuesong that gets removed
  83. * @param {Function} cb - gets called with the result
  84. * @param {String} userId - the userId automatically added by hooks
  85. */
  86. remove: hooks.adminRequired((session, songId, cb, userId) => {
  87. async.waterfall([
  88. (next) => {
  89. db.models.queueSong.remove({ _id: songId }, next);
  90. }
  91. ], (err) => {
  92. if (err) {
  93. let error = 'An error occurred.';
  94. if (typeof err === "string") error = err;
  95. else if (err.message) error = err.message;
  96. logger.log("QUEUE_REMOVE", "ERROR", `Removing queuesong "${songId}" failed for user ${userId}. "${err.message}"`);
  97. return cb({status: 'failure', message: error});
  98. }
  99. cache.pub('queue.removedSong', songId);
  100. logger.log("QUEUE_REMOVE", "SUCCESS", `User "${userId}" successfully removed queuesong "${songId}".`);
  101. return cb({status: 'success', message: 'Successfully updated song.'});
  102. });
  103. }),
  104. /**
  105. * Creates a queuesong
  106. *
  107. * @param {Object} session - the session object automatically added by socket.io
  108. * @param {String} songId - the id of the song that gets added
  109. * @param {Function} cb - gets called with the result
  110. * @param {String} userId - the userId automatically added by hooks
  111. */
  112. add: hooks.loginRequired((session, songId, cb, userId) => {
  113. let requestedAt = Date.now();
  114. async.waterfall([
  115. (next) => {
  116. db.models.queueSong.findOne({_id: songId}, next);
  117. },
  118. (song, next) => {
  119. if (song) return next('This song is already in the queue.');
  120. db.models.song.findOne({_id: songId}, next);
  121. },
  122. // Get YouTube data from id
  123. (song, next) => {
  124. if (song) return next('This song has already been added.');
  125. //TODO Add err object as first param of callback
  126. utils.getSongFromYouTube(songId, (song) => {
  127. song.artists = [];
  128. song.genres = [];
  129. song.skipDuration = 0;
  130. song.thumbnail = 'empty';
  131. song.explicit = false;
  132. song.requestedBy = userId;
  133. song.requestedAt = requestedAt;
  134. next(null, song);
  135. });
  136. },
  137. (newSong, next) => {
  138. //TODO Add err object as first param of callback
  139. utils.getSongFromSpotify(newSong, (song) => {
  140. next(null, song);
  141. });
  142. },
  143. (newSong, next) => {
  144. const song = new db.models.queueSong(newSong);
  145. song.save(err => {
  146. if (err) return next(err);
  147. next(null, newSong);
  148. });
  149. }
  150. ], (err, newSong) => {
  151. if (err) {
  152. let error = 'An error occurred.';
  153. if (typeof err === "string") error = err;
  154. else if (err.message) error = err.message;
  155. return cb({status: 'failure', message: error});
  156. }
  157. cache.pub('queue.newSong', newSong._id);
  158. return cb({ status: 'success', message: 'Successfully added that song to the queue' });
  159. });
  160. })
  161. };