stations.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. 'use strict';
  2. const async = require('async');
  3. const request = require('request');
  4. const db = require('../db');
  5. const cache = require('../cache');
  6. const utils = require('../utils');
  7. module.exports = {
  8. index: (session, cb) => {
  9. cb(cache.getAllRows('stations'));
  10. },
  11. join: (session, stationId, cb) => {
  12. async.waterfall([
  13. // first check the cache for the station
  14. (next) => next(null, cache.findRow('stations', 'id', stationId)),
  15. // if the cached version exist use it, otherwise check the DB for it
  16. (station, next) => {
  17. if (station) return next(true, station);
  18. db.models.station.find({ id: stationId }, next);
  19. },
  20. // add the station from the DB to the cache, adding the temporary data
  21. (station, next) => {
  22. cache.addRow('stations', Object.assign(station, {
  23. skips: 0,
  24. userCount: 0,
  25. currentSongIndex: 0,
  26. paused: false
  27. }));
  28. next(null, station);
  29. }
  30. ], (err, station) => {
  31. if (err && err !== true) {
  32. return cb({ status: 'error', message: 'An error occurred while joining the station' });
  33. }
  34. if (station) {
  35. if (session) session.stationId = stationId;
  36. station.userCount++;
  37. cb({ status: 'success', userCount: station.userCount });
  38. }
  39. else {
  40. cb({ status: 'failure', message: `That station doesn't exist` });
  41. }
  42. });
  43. },
  44. skip: (session, cb) => {
  45. if (!session) return cb({ status: 'failure', message: 'You must be logged in to skip a song!' });
  46. async.waterfall([
  47. // first check the cache for the station
  48. (next) => next(null, cache.findRow('stations', 'id', session.stationId)),
  49. // if the cached version exist use it, otherwise check the DB for it
  50. (station, next) => {
  51. if (station) return next(true, station);
  52. db.models.station.find({ id: session.stationId }, next);
  53. },
  54. // add the station from the DB to the cache, adding the temporary data
  55. (station, next) => {
  56. cache.addRow('stations', Object.assign(station, {
  57. skips: 0,
  58. userCount: 0,
  59. currentSongIndex: 0,
  60. paused: false
  61. }));
  62. next(null, station);
  63. }
  64. ], (err, station) => {
  65. if (err && err !== true) {
  66. return cb({ status: 'error', message: 'An error occurred while skipping the station' });
  67. }
  68. if (station) {
  69. station.skips++;
  70. if (station.skips > Math.floor(station.userCount / 2)) {
  71. // TODO: skip to the next song if the skips is higher then half the total users
  72. }
  73. cb({ status: 'success', skips: station.skips });
  74. }
  75. else {
  76. cb({ status: 'failure', message: `That station doesn't exist` });
  77. }
  78. });
  79. },
  80. // leaves the users current station
  81. // returns the count of users that are still in that station
  82. leave: (session, cb) => {
  83. // if they're not logged in, we don't need to do anything below
  84. if (!session) return cb({ status: 'success' });
  85. async.waterfall([
  86. // first check the cache for the station
  87. (next) => next(null, cache.findRow('stations', 'id', session.stationId)),
  88. // if the cached version exist use it, otherwise check the DB for it
  89. (station, next) => {
  90. if (station) return next(true, station);
  91. db.models.station.find({ id: session.stationId }, next);
  92. },
  93. // add the station from the DB to the cache, adding the temporary data
  94. (station, next) => {
  95. cache.addRow('stations', Object.assign(station, {
  96. skips: 0,
  97. userCount: 0,
  98. currentSongIndex: 0,
  99. paused: false
  100. }));
  101. next(null, station);
  102. }
  103. ], (err, station) => {
  104. if (err && err !== true) {
  105. return cb({ status: 'error', message: 'An error occurred while leaving the station' });
  106. }
  107. session.stationId = null;
  108. if (station) {
  109. station.userCount--;
  110. cb({ status: 'success', userCount: station.userCount });
  111. }
  112. else {
  113. cb({ status: 'failure', message: `That station doesn't exist` });
  114. }
  115. });
  116. },
  117. addSong: (session, station, song, cb) => {
  118. // if (!session.logged_in) return cb({ status: 'failure', message: 'You must be logged in to add a song' });
  119. const params = [
  120. 'part=snippet,contentDetails,statistics,status',
  121. `id=${encodeURIComponent(song.id)}`,
  122. `key=${config.get('apis.youtube.key')}`
  123. ].join('&');
  124. request(`https://www.googleapis.com/youtube/v3/videos?${params}`, (err, res, body) => {
  125. if (err) {
  126. console.error(err);
  127. return cb({ status: 'error', message: 'Failed to find song from youtube' });
  128. }
  129. const newSong = new db.models.song({
  130. id: json.items[0].id,
  131. title: json.items[0].snippet.title,
  132. duration: utils.convertTime(json.items[0].contentDetails.duration),
  133. thumbnail: json.items[0].snippet.thumbnails.high.url
  134. });
  135. // save the song to the database
  136. newSong.save(err => {
  137. if (err) {
  138. console.error(err);
  139. return cb({ status: 'error', message: 'Failed to save song from youtube to the database' });
  140. }
  141. stations.getStation(station).playlist.push(newSong);
  142. cb({ status: 'success', data: stations.getStation(station.playlist) });
  143. });
  144. });
  145. }
  146. };