playlists.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. 'use strict';
  2. const db = require('../db');
  3. const io = require('../io');
  4. const cache = require('../cache');
  5. const utils = require('../utils');
  6. const hooks = require('./hooks');
  7. const async = require('async');
  8. const playlists = require('../playlists');
  9. let lib = {
  10. indexForUser: (session, createdBy, cb) => {
  11. db.models.playlist.find({ createdBy }, (err, playlists) => {
  12. if (err) throw err;
  13. cb({
  14. status: 'success',
  15. data: playlists
  16. });
  17. });
  18. },
  19. create: (session, data, cb) => {
  20. async.waterfall([
  21. (next) => {
  22. return (data) ? next() : cb({ 'status': 'failure', 'message': 'Invalid data' });
  23. },
  24. // check the cache for the playlist
  25. (next) => cache.hget('playlists', data._id, next),
  26. // if the cached version exist
  27. (playlist, next) => {
  28. if (playlist) return next({ 'status': 'failure', 'message': 'A playlist with that id already exists' });
  29. db.models.playlist.findOne({ _id: data._id }, next);
  30. },
  31. (playlist, next) => {
  32. if (playlist) return next({ 'status': 'failure', 'message': 'A playlist with that id already exists' });
  33. const { _id, displayName, songs, createdBy } = data;
  34. db.models.playlist.create({
  35. _id,
  36. displayName,
  37. songs,
  38. createdBy,
  39. createdAt: Date.now()
  40. }, next);
  41. }
  42. ], (err, playlist) => {
  43. if (err) return cb({ 'status': 'failure', 'message': 'Something went wrong'});
  44. cache.pub('playlist.create', data._id);
  45. return cb({ 'status': 'success', 'message': 'Successfully created playlist' });
  46. });
  47. },
  48. getPlaylist: (session, id, cb) => {
  49. playlists.getPlaylist(id, (err, playlist) => {
  50. if (err == null) return cb({
  51. status: 'success',
  52. data: playlist
  53. });
  54. });
  55. },
  56. update: (session, _id, playlist, cb) => {
  57. db.models.playlist.findOneAndUpdate({ _id }, playlist, { upsert: true }, (err, data) => {
  58. if (err) throw err;
  59. return cb({ status: 'success', message: 'Playlist has been successfully updated', data });
  60. });
  61. },
  62. addSongToPlaylist: (session, songId, playlistId, cb) => {
  63. async.waterfall([
  64. (next) => {
  65. utils.getSongFromYouTube(songId, (song) => {
  66. song.artists = [];
  67. song.genres = [];
  68. song.skipDuration = 0;
  69. song.thumbnail = 'empty';
  70. song.explicit = false;
  71. song.requestedBy = 'temp';
  72. song.requestedAt = Date.now();
  73. next(null, song);
  74. });
  75. },
  76. (newSong, next) => {
  77. utils.getSongFromSpotify(newSong, (song) => {
  78. next(null, song);
  79. });
  80. },
  81. (newSong, next) => {
  82. db.models.playlist.findOne({ _id: playlistId }, (err, playlist) => {
  83. if (err) throw err;
  84. playlist.songs.push(newSong);
  85. playlist.save(err => {
  86. if (err) {
  87. console.error(err);
  88. return next('Failed to add song to playlist');
  89. }
  90. cache.hset('playlists', playlistId, playlist);
  91. next(null, playlist);
  92. });
  93. });
  94. }
  95. ],
  96. (err, playlist) => {
  97. if (err) return cb({ status: 'error', message: err });
  98. else return cb({ status: 'success', message: 'Song has been successfully added to the playlist', data: playlist.songs });
  99. });
  100. },
  101. addSetToPlaylist: (session, url, playlistId, cb) => {
  102. async.waterfall([
  103. (next) => {
  104. utils.getPlaylistFromYouTube(url, songs => {
  105. next(null, songs);
  106. });
  107. },
  108. (songs, next) => {
  109. for (let s = 0; s < songs.length; s++) {
  110. lib.addSongToPlaylist(session, songs[s].contentDetails.videoId, playlistId, (res) => {});
  111. }
  112. next(null);
  113. },
  114. (next) => {
  115. db.models.playlist.findOne({ _id: playlistId }, (err, playlist) => {
  116. if (err) throw err;
  117. next(null, playlist);
  118. });
  119. }
  120. ],
  121. (err, playlist) => {
  122. if (err) return cb({ status: 'error', message: err });
  123. else return cb({ status: 'success', message: 'Playlist has been successfully added', data: playlist.songs });
  124. });
  125. },
  126. removeSongFromPlaylist: (session, songId, playlistId, cb) => {
  127. db.models.playlist.findOne({ _id: playlistId }, (err, playlist) => {
  128. if (err) throw err;
  129. for (let z = 0; z < playlist.songs.length; z++) {
  130. if (playlist.songs[z]._id == songId) playlist.songs.shift(playlist.songs[z]);
  131. }
  132. playlist.save(err => {
  133. if (err) {
  134. console.error(err);
  135. return next('Failed to remove song to playlist');
  136. }
  137. cache.hset('playlists', playlistId, playlist);
  138. return cb({ status: 'success', message: 'Song has been successfully removed from playlist', data: playlist.songs });
  139. });
  140. });
  141. },
  142. updateDisplayName: (session, _id, displayName, cb) => {
  143. db.models.playlist.findOneAndUpdate({ _id }, { displayName }, { upsert: true }, (err, res) => {
  144. if (err) throw err;
  145. cache.hset('playlists', _id, res);
  146. return cb({ status: 'success', message: 'Playlist has been successfully updated' });
  147. });
  148. },
  149. updatePlaylistId: (session, oldId, newId, cb) => {
  150. db.models.playlist.findOne({ _id: oldId }).exec((err, doc) => {
  151. if (err) throw err;
  152. doc._id = newId;
  153. let newPlaylist = new db.models.playlist(doc);
  154. newPlaylist.isNew = true;
  155. newPlaylist.save(err => {
  156. if (err) console.error(err);
  157. });
  158. db.models.playlist.remove({ _id: oldId });
  159. cache.hdel('playlists', oldId, () => {
  160. cache.hset('playlists', newId, doc);
  161. return cb({ status: 'success', data: doc });
  162. });
  163. });
  164. },
  165. promoteSong: (session, playlistId, fromIndex, cb) => {
  166. db.models.playlist.findOne({ _id: playlistId }, (err, playlist) => {
  167. if (err) throw err;
  168. let song = playlist.songs[fromIndex];
  169. playlist.songs.splice(fromIndex, 1);
  170. playlist.songs.splice((fromIndex + 1), 0, song);
  171. playlist.save(err => {
  172. if (err) {
  173. console.error(err);
  174. return next('Failed to promote song');
  175. }
  176. cache.hset('playlists', playlistId, playlist);
  177. return cb({ status: 'success', data: playlist.songs });
  178. });
  179. });
  180. },
  181. demoteSong: (session, playlistId, fromIndex, cb) => {
  182. db.models.playlist.findOne({ _id: playlistId }, (err, playlist) => {
  183. if (err) throw err;
  184. let song = playlist.songs[fromIndex];
  185. playlist.songs.splice(fromIndex, 1);
  186. playlist.songs.splice((fromIndex - 1), 0, song);
  187. playlist.save(err => {
  188. if (err) {
  189. console.error(err);
  190. return next('Failed to demote song');
  191. }
  192. cache.hset('playlists', playlistId, playlist);
  193. return cb({ status: 'success', data: playlist.songs });
  194. });
  195. });
  196. },
  197. remove: (session, _id, cb) => {
  198. db.models.playlist.remove({ _id }).exec(err => {
  199. if (err) throw err;
  200. cache.hdel('playlists', _id, () => {
  201. return cb({ status: 'success', message: 'Playlist successfully removed' });
  202. });
  203. });
  204. }
  205. };
  206. module.exports = lib;