queueSongs.js 6.3 KB

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