coreHandler.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. 'use strict';
  2. // nodejs modules
  3. const path = require('path'),
  4. fs = require('fs'),
  5. os = require('os');
  6. // npm modules
  7. const config = require('config'),
  8. request = require('request'),
  9. waterfall = require('async/waterfall').
  10. r = require('rethinkdb');
  11. // custom modules
  12. const utils = require('./utils');
  13. var dbConnection = null;
  14. // station stuff
  15. var stations = [];
  16. //TODO Find better name for this (createStation will be to add a station to the db)
  17. function makeStation(id) {
  18. if (!getStation(id)) {
  19. var station = new Station(id);
  20. stations.push(station);
  21. return station;
  22. } else {
  23. return false;
  24. }
  25. }
  26. function getStation(id) {
  27. stations.forEach(function(station) {
  28. this.station = station;
  29. });
  30. return this.station;
  31. }
  32. function Station(id) {
  33. //TODO Add startedAt and timePaused
  34. var self = this;
  35. var playlist = [
  36. {
  37. mid: "3498fd83",
  38. duration: 20000,
  39. title: "Test1"
  40. },
  41. {
  42. mid: "3498fd83434",
  43. duration: 10000,
  44. title: "Test2"
  45. }
  46. ];//TODO Get this from RethinkDB
  47. var currentSong = playlist[0];
  48. var currentSongIndex = 0;//TODO Get this from RethinkDB
  49. var paused = true;//TODO Get this from RethinkDB
  50. var locked = false;//TODO Get this from RethinkDB
  51. var skipVotes = [];
  52. var users = [];
  53. var timer;
  54. var displayName;//TODO Get this from RethinkDB
  55. var description;//TODO Get this from RethinkDB
  56. this.skipSong = function() {
  57. if (playlist.length > 0) {
  58. if (timer !== undefined) {
  59. timer.pause();
  60. }
  61. if (currentSongIndex+1 < playlist.length) {
  62. currentSongIndex++;
  63. } else {
  64. currentSongIndex = 0;
  65. }
  66. skipVotes = 0;
  67. currentSong = playlist[currentSongIndex];
  68. timer = new Timer(function() {
  69. console.log("Skip!");
  70. self.skipSong();
  71. }, currentSong.duration, paused);
  72. //io.emit("skipSong " + id, currentSong);
  73. }
  74. };
  75. this.toggleVoteSkip = function(userId) {
  76. if (skipVotes.indexOf(userId) === -1) {
  77. skipVotes.push(userId);
  78. } else {
  79. skipVotes = skipVotes.splice(skipVotes.indexOf(userId), 1);
  80. }
  81. //TODO Calculate if enough people voted to skip
  82. //TODO Emit
  83. };
  84. this.retrievePlaylist = function() {
  85. //TODO Use Rethink to get the Playlist for this room
  86. };
  87. this.pause = function() {
  88. if (!paused) {
  89. paused = true;
  90. timer.pause();
  91. }
  92. //TODO Emit
  93. };
  94. this.unpause = function() {
  95. if (paused) {
  96. paused = false;
  97. timer.resume();
  98. }
  99. //TODO Emit
  100. };
  101. this.isPaused = function() {
  102. return paused;
  103. };
  104. this.getCurrentSong = function() {
  105. return currentSong;
  106. };
  107. this.lock = function() {
  108. if (!locked) {
  109. locked = true;
  110. }
  111. //TODO Emit
  112. };
  113. this.unlock = function() {
  114. if (locked) {
  115. locked = false;
  116. }
  117. //TODO Emit
  118. };
  119. this.isLocked = function() {
  120. return locked;
  121. };
  122. this.updateDisplayName = function(newDisplayName) {
  123. //TODO Update RethinkDB
  124. displayName = newDisplayName;
  125. };
  126. this.updateDescription = function(newDescription) {
  127. //TODO Update RethinkDB
  128. description = newDescription;
  129. };
  130. this.getId = function() {
  131. return id;
  132. };
  133. this.getDisplayName = function() {
  134. return displayName;
  135. };
  136. this.getDescription = function() {
  137. return description;
  138. };
  139. this.addUser = function(user) {
  140. users.add(user);
  141. };
  142. this.removeUser = function(user) {
  143. users.splice(users.indexOf(user), 1);
  144. };
  145. this.getUsers = function() {
  146. return users;
  147. };
  148. this.skipSong();
  149. }
  150. function Timer(callback, delay, paused) {
  151. var timerId, start, remaining = delay;
  152. var timeWhenPaused = 0;
  153. var timePaused = Date.now();
  154. this.pause = function () {
  155. clearTimeout(timerId);
  156. remaining -= Date.now() - start;
  157. timePaused = Date.now();
  158. };
  159. this.resume = function () {
  160. start = Date.now();
  161. clearTimeout(timerId);
  162. timerId = setTimeout(callback, remaining);
  163. timeWhenPaused += Date.now() - timePaused;
  164. };
  165. this.resetTimeWhenPaused = function() {
  166. timeWhenPaused = 0;
  167. };
  168. this.timeWhenPaused = function () {
  169. return timeWhenPaused;
  170. };
  171. if (paused === false) {
  172. this.resume();
  173. }
  174. }
  175. module.exports = {
  176. setup: function (dbConn) {
  177. dbConnection = dbConn;
  178. },
  179. disconnect: function () {
  180. },
  181. login: function (user, cb) {
  182. if (!user.username || !user.password) {
  183. return cb({ status: 'error', message: 'Invalid login request' });
  184. }
  185. r.table('users').filter({
  186. username: user.username,
  187. password: crypto.createHash('md5').update(user.password).digest("hex")
  188. }).run(rc, (err, cursor) => {
  189. if (err) {
  190. return cb({ status: 'failure', message: 'Error while fetching the user' });
  191. }
  192. else {
  193. cursor.toArray((err, result) => {
  194. if (err) {
  195. return cb({ status: 'failure', message: 'Error while fetching the user' });
  196. }
  197. else {
  198. return cb({ status: 'success', user: result });
  199. }
  200. });
  201. }
  202. });
  203. },
  204. register: function (user, cb) {
  205. if (!user.email || !user.username || !user.password) {
  206. return cb({ status: 'error', message: 'Invalid register request' });
  207. }
  208. // TODO: Implement register
  209. },
  210. rooms: function (cb) {
  211. var _rooms = stations.map(function(result) {
  212. return {
  213. id: result.getId(),
  214. displayName: result.getDisplayName(),
  215. description: result.getDescription(),
  216. users: result.getUsers()
  217. }
  218. });
  219. cb(_rooms);
  220. },
  221. handleRoomJoin: function (id, cb) {
  222. var room = getStation(id);
  223. socket.custom.roomId = id;
  224. var userInfo = {
  225. username: socket.custom.user.username
  226. };
  227. // tell all the users in this room that someone is joining it
  228. io.sockets.clients().forEach(function (otherSocket) {
  229. if (otherSocket != socket && otherSocket.custom.roomId === id) {
  230. otherSocket.emit('roomUserJoin', { user: userInfo });
  231. }
  232. });
  233. return cb({
  234. status: 'joined',
  235. data: {
  236. room: room
  237. }
  238. });
  239. },
  240. search: function (query, cb) {
  241. request('https://www.googleapis.com/youtube/v3/search?' + [
  242. 'part=snippet', `q=${encodeURIComponent(query)}`, `key=${config.get('apis.youtube.key')}`, 'type=video', 'maxResults=25'
  243. ].join('&'), (err, res, body) => {
  244. if (err) {
  245. socket.emit('search', { status: 'error', message: 'Failed to make request' });
  246. }
  247. else {
  248. try {
  249. socket.emit('search', { status: 'success', body: JSON.parse(body) });
  250. }
  251. catch (e) {
  252. socket.emit('search', { status: 'error', message: 'Non JSON response' });
  253. }
  254. }
  255. });
  256. }
  257. };