queueSongs.js 5.6 KB

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