coreHandler.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  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 timer;
  53. this.skipSong = function() {
  54. if (playlist.length > 0) {
  55. if (timer !== undefined) {
  56. timer.pause();
  57. }
  58. if (currentSongIndex+1 < playlist.length) {
  59. currentSongIndex++;
  60. } else {
  61. currentSongIndex = 0;
  62. }
  63. skipVotes = 0;
  64. currentSong = playlist[currentSongIndex];
  65. timer = new Timer(function() {
  66. console.log("Skip!");
  67. self.skipSong();
  68. }, currentSong.duration, paused);
  69. //io.emit("skipSong " + id, currentSong);
  70. }
  71. };
  72. this.toggleVoteSkip = function(userId) {
  73. if (skipVotes.indexOf(userId) === -1) {
  74. skipVotes.push(userId);
  75. } else {
  76. skipVotes = skipVotes.splice(skipVotes.indexOf(userId), 1);
  77. }
  78. //TODO Calculate if enough people voted to skip
  79. //TODO Emit
  80. };
  81. this.retrievePlaylist = function() {
  82. //TODO Use Rethink to get the Playlist for this room
  83. };
  84. this.pause = function() {
  85. if (!paused) {
  86. paused = true;
  87. timer.pause();
  88. }
  89. //TODO Emit
  90. };
  91. this.unpause = function() {
  92. if (paused) {
  93. paused = false;
  94. timer.resume();
  95. }
  96. //TODO Emit
  97. };
  98. this.isPaused = function() {
  99. return paused;
  100. };
  101. this.getCurrentSong = function() {
  102. return currentSong;
  103. };
  104. this.lock = function() {
  105. if (!locked) {
  106. locked = true;
  107. }
  108. //TODO Emit
  109. };
  110. this.unlock = function() {
  111. if (locked) {
  112. locked = false;
  113. }
  114. //TODO Emit
  115. };
  116. this.isLocked = function() {
  117. return locked;
  118. };
  119. this.skipSong();
  120. }
  121. function Timer(callback, delay, paused) {
  122. var timerId, start, remaining = delay;
  123. var timeWhenPaused = 0;
  124. var timePaused = Date.now();
  125. this.pause = function () {
  126. clearTimeout(timerId);
  127. remaining -= Date.now() - start;
  128. timePaused = Date.now();
  129. };
  130. this.resume = function () {
  131. start = Date.now();
  132. clearTimeout(timerId);
  133. timerId = setTimeout(callback, remaining);
  134. timeWhenPaused += Date.now() - timePaused;
  135. };
  136. this.resetTimeWhenPaused = function() {
  137. timeWhenPaused = 0;
  138. };
  139. this.timeWhenPaused = function () {
  140. return timeWhenPaused;
  141. };
  142. if (paused === false) {
  143. this.resume();
  144. }
  145. }
  146. module.exports = {
  147. setup: function (dbConn) {
  148. dbConnection = dbConn;
  149. },
  150. disconnect: function () {
  151. },
  152. login: function (user, cb) {
  153. if (!user.username || !user.password) {
  154. return cb({ status: 'error', message: 'Invalid login request' });
  155. }
  156. r.table('users').filter({
  157. username: user.username,
  158. password: crypto.createHash('md5').update(user.password).digest("hex")
  159. }).run(rc, (err, cursor) => {
  160. if (err) {
  161. return cb({ status: 'failure', message: 'Error while fetching the user' });
  162. }
  163. else {
  164. cursor.toArray((err, result) => {
  165. if (err) {
  166. return cb({ status: 'failure', message: 'Error while fetching the user' });
  167. }
  168. else {
  169. return cb({ status: 'success', user: result });
  170. }
  171. });
  172. }
  173. });
  174. },
  175. register: function (user, cb) {
  176. if (!user.email || !user.username || !user.password) {
  177. return cb({ status: 'error', message: 'Invalid register request' });
  178. }
  179. // TODO: Implement register
  180. },
  181. rooms: function (cb) {
  182. r.table('rooms').run(rc, (err, cursor) => {
  183. if (err) {
  184. return cb({ status: 'failure', message: 'Error while fetching the rooms' });
  185. }
  186. else {
  187. cursor.toArray((err, result) => {
  188. if (err) {
  189. return cb({ status: 'failure', message: 'Error while fetching the rooms' });
  190. }
  191. else {
  192. return cb(result);
  193. }
  194. });
  195. }
  196. });
  197. },
  198. room: function (id, cb) {
  199. if (socket.custom.user == null) {
  200. return cb({ status: 'error', message: "You can't join a room until you've logged in" });
  201. }
  202. r.table('rooms').get(id).run(rc, (err, result) => {
  203. if (err) {
  204. return cb({ status: 'error', message: 'Room with that id does not exist' });
  205. }
  206. else {
  207. socket.custom.roomId = id;
  208. var userInfo = {
  209. username: socket.custom.user.username
  210. };
  211. var otherUsersInfo = [];
  212. // tell all the users in this room that someone is joining it
  213. io.sockets.clients().forEach((otherSocket) => {
  214. if (otherSocket != socket && otherSocket.custom.roomId == id) {
  215. otherUsersInfo.push({ username: otherSocket.custom.user.username });
  216. otherSocket.emit('room', { status: 'joining', user: userInfo });
  217. }
  218. });
  219. return cb({
  220. status: 'joined',
  221. data: {
  222. room: result,
  223. users: otherUsersInfo
  224. }
  225. });
  226. }
  227. });
  228. },
  229. search: function (query, cb) {
  230. request('https://www.googleapis.com/youtube/v3/search?' + [
  231. 'part=snippet', `q=${encodeURIComponent(query)}`, `key=${config.get('apis.youtube.key')}`, 'type=video', 'maxResults=25'
  232. ].join('&'), (err, res, body) => {
  233. if (err) {
  234. socket.emit('search', { status: 'error', message: 'Failed to make request' });
  235. }
  236. else {
  237. try {
  238. socket.emit('search', { status: 'success', body: JSON.parse(body) });
  239. }
  240. catch (e) {
  241. socket.emit('search', { status: 'error', message: 'Non JSON response' });
  242. }
  243. }
  244. });
  245. }
  246. };