queueSongs.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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. err = utils.getError(err);
  39. logger.error("QUEUE_INDEX", `Indexing queuesongs failed. "${err}"`);
  40. return cb({status: 'failure', message: err});
  41. } else {
  42. module.exports.getSet(session, 1, result => {
  43. logger.success("QUEUE_INDEX", `Indexing queuesongs successful.`);
  44. return cb({
  45. songs: result,
  46. maxLength: songs.length
  47. });
  48. });
  49. }
  50. });
  51. }),
  52. getSet: hooks.adminRequired((session, set, cb) => {
  53. db.models.queueSong.find({}).limit(50 * set).exec((err, songs) => {
  54. if (err) throw err;
  55. cb(songs.splice(Math.max(songs.length - 50, 0)));
  56. });
  57. }),
  58. /**
  59. * Updates a queuesong
  60. *
  61. * @param {Object} session - the session object automatically added by socket.io
  62. * @param {String} songId - the id of the queuesong that gets updated
  63. * @param {Object} updatedSong - the object of the updated queueSong
  64. * @param {Function} cb - gets called with the result
  65. * @param {String} userId - the userId automatically added by hooks
  66. */
  67. update: hooks.adminRequired((session, songId, updatedSong, cb, userId) => {
  68. async.waterfall([
  69. (next) => {
  70. db.models.queueSong.findOne({ _id: songId }, next);
  71. },
  72. (song, next) => {
  73. if(!song) return next('Song not found');
  74. let updated = false;
  75. let $set = {};
  76. for (let prop in updatedSong) if (updatedSong[prop] !== song[prop]) $set[prop] = updatedSong[prop]; updated = true;
  77. if (!updated) return next('No properties changed');
  78. db.models.queueSong.update({ _id: songId }, {$set}, next);
  79. }
  80. ], (err) => {
  81. if (err) {
  82. err = utils.getError(err);
  83. logger.error("QUEUE_UPDATE", `Updating queuesong "${songId}" failed for user ${userId}. "${err}"`);
  84. return cb({status: 'failure', message: err});
  85. }
  86. cache.pub('queue.update', songId);
  87. logger.success("QUEUE_UPDATE", `User "${userId}" successfully update queuesong "${songId}".`);
  88. return cb({status: 'success', message: 'Successfully updated song.'});
  89. });
  90. }),
  91. /**
  92. * Removes a queuesong
  93. *
  94. * @param {Object} session - the session object automatically added by socket.io
  95. * @param {String} songId - the id of the queuesong that gets removed
  96. * @param {Function} cb - gets called with the result
  97. * @param {String} userId - the userId automatically added by hooks
  98. */
  99. remove: hooks.adminRequired((session, songId, cb, userId) => {
  100. async.waterfall([
  101. (next) => {
  102. db.models.queueSong.remove({ _id: songId }, next);
  103. }
  104. ], (err) => {
  105. if (err) {
  106. err = utils.getError(err);
  107. logger.error("QUEUE_REMOVE", `Removing queuesong "${songId}" failed for user ${userId}. "${err}"`);
  108. return cb({status: 'failure', message: err});
  109. }
  110. cache.pub('queue.removedSong', songId);
  111. logger.success("QUEUE_REMOVE", `User "${userId}" successfully removed queuesong "${songId}".`);
  112. return cb({status: 'success', message: 'Successfully updated song.'});
  113. });
  114. }),
  115. /**
  116. * Creates a queuesong
  117. *
  118. * @param {Object} session - the session object automatically added by socket.io
  119. * @param {String} songId - the id of the song that gets added
  120. * @param {Function} cb - gets called with the result
  121. * @param {String} userId - the userId automatically added by hooks
  122. */
  123. add: hooks.loginRequired((session, songId, cb, userId) => {
  124. let requestedAt = Date.now();
  125. async.waterfall([
  126. (next) => {
  127. db.models.queueSong.findOne({_id: songId}, next);
  128. },
  129. (song, next) => {
  130. if (song) return next('This song is already in the queue.');
  131. db.models.song.findOne({_id: songId}, next);
  132. },
  133. // Get YouTube data from id
  134. (song, next) => {
  135. if (song) return next('This song has already been added.');
  136. //TODO Add err object as first param of callback
  137. utils.getSongFromYouTube(songId, (song) => {
  138. song.artists = [];
  139. song.genres = [];
  140. song.skipDuration = 0;
  141. song.thumbnail = 'empty';
  142. song.explicit = false;
  143. song.requestedBy = userId;
  144. song.requestedAt = requestedAt;
  145. next(null, song);
  146. });
  147. },
  148. (newSong, next) => {
  149. //TODO Add err object as first param of callback
  150. utils.getSongFromSpotify(newSong, (song) => {
  151. next(null, song);
  152. });
  153. },
  154. (newSong, next) => {
  155. const song = new db.models.queueSong(newSong);
  156. song.save(err => {
  157. if (err) return next(err);
  158. next(null, newSong);
  159. });
  160. },
  161. (newSong, next) => {
  162. db.models.user.findOne({ _id: userId }, (err, user) => {
  163. if (err) next(err, newSong);
  164. else {
  165. user.statistics.songsRequested = user.statistics.songsRequested + 1;
  166. user.save(err => {
  167. if (err) return next(err, newSong);
  168. else next(null, newSong);
  169. });
  170. }
  171. });
  172. }
  173. ], (err, newSong) => {
  174. if (err) {
  175. err = utils.getError(err);
  176. logger.error("QUEUE_ADD", `Adding queuesong "${songId}" failed for user ${userId}. "${err}"`);
  177. return cb({status: 'failure', message: err});
  178. }
  179. cache.pub('queue.newSong', newSong._id);
  180. logger.success("QUEUE_ADD", `User "${userId}" successfully added queuesong "${songId}".`);
  181. return cb({ status: 'success', message: 'Successfully added that song to the queue' });
  182. });
  183. })
  184. };