coreHandler.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. 'use strict';
  2. // nodejs modules
  3. const path = require('path'),
  4. fs = require('fs'),
  5. os = require('os'),
  6. events = require('events');
  7. // npm modules
  8. const config = require('config'),
  9. request = require('request'),
  10. waterfall = require('async/waterfall'),
  11. bcrypt = require('bcrypt'),
  12. passport = require('passport');
  13. // custom modules
  14. const global = require('./global'),
  15. stations = require('./stations');
  16. var eventEmitter = new events.EventEmitter();
  17. const station = new stations.Station("edm", {
  18. playlist: [
  19. {
  20. startedAt: Date.now(),
  21. id: "dQw4w9WgXcQ",
  22. title: "Never gonna give you up",
  23. artists: ["Rick Astley"],
  24. duration: 20,
  25. skipDuration: 0,
  26. image: "https://yt3.ggpht.com/-CGlBu6kDEi8/AAAAAAAAAAI/AAAAAAAAAAA/Pi679mvyyyU/s88-c-k-no-mo-rj-c0xffffff/photo.jpg",
  27. likes: 0,
  28. dislikes: 1,
  29. genres: ["pop", "edm"]
  30. },
  31. {
  32. startedAt: Date.now(),
  33. id: "GxBSyx85Kp8",
  34. title: "Yeah!",
  35. artists: ["Usher"],
  36. duration: 20,
  37. skipDuration: 0,
  38. image: "https://yt3.ggpht.com/-CGlBu6kDEi8/AAAAAAAAAAI/AAAAAAAAAAA/Pi679mvyyyU/s88-c-k-no-mo-rj-c0xffffff/photo.jpg",
  39. likes: 0,
  40. dislikes: 1,
  41. genres: ["pop", "edm"]
  42. }
  43. ],
  44. currentSongIndex: 1,
  45. paused: false,
  46. locked: false,
  47. displayName: "EDM",
  48. description: "EDM Music"
  49. });
  50. stations.addStation(station);
  51. module.exports = {
  52. // module functions
  53. on: (name, cb) => {
  54. eventEmitter.on(name, cb);
  55. },
  56. emit: (name, data) => {
  57. eventEmitter.emit(name, data);
  58. },
  59. // core route handlers
  60. '/users/register': (username, email, password, recaptcha, cb) => {
  61. console.log(username, password);
  62. request({
  63. url: 'https://www.google.com/recaptcha/api/siteverify',
  64. method: 'POST',
  65. form: {
  66. 'secret': config.get("apis.recapthca.secret"),
  67. 'response': recaptcha
  68. }
  69. }, function (error, response, body) {
  70. if (error === null && JSON.parse(body).success === true) {
  71. body = JSON.parse(body);
  72. global.db.user.findOne({'username': username}, function (err, user) {
  73. console.log(err, user);
  74. if (err) return cb(err);
  75. if (user) return cb("username");
  76. else {
  77. global.db.user.findOne({'email.address': email}, function (err, user) {
  78. console.log(err, user);
  79. if (err) return cb(err);
  80. if (user) return cb("email");
  81. else {
  82. // TODO: Email verification code, send email
  83. bcrypt.genSalt(10, function (err, salt) {
  84. if (err) {
  85. return cb(err);
  86. } else {
  87. bcrypt.hash(password, salt, function (err, hash) {
  88. if (err) {
  89. return cb(err);
  90. } else {
  91. let newUser = new global.db.user({
  92. username: username,
  93. email: {
  94. address: email,
  95. verificationToken: global.generateRandomString("64")
  96. },
  97. services: {
  98. password: {
  99. password: hash
  100. }
  101. }
  102. });
  103. newUser.save(function (err) {
  104. if (err) throw err;
  105. return cb(null, newUser);
  106. });
  107. }
  108. });
  109. }
  110. });
  111. }
  112. });
  113. }
  114. });
  115. } else {
  116. cb("Recaptcha failed");
  117. }
  118. });
  119. },
  120. '/stations': cb => {
  121. cb(stations.getStations().map(function (result) {
  122. return {
  123. id: result.getId(),
  124. displayName: result.getDisplayName(),
  125. description: result.getDescription(),
  126. users: result.getUsers()
  127. }
  128. }));
  129. },
  130. '/station/:id/join': (stationId, socketId, cb) => {
  131. const station = stations.getStation(stationId);
  132. if (station) {
  133. var response = station.handleUserJoin(socketId);
  134. return cb(response);
  135. }
  136. else {
  137. return cb({ status: 'error', message: 'Room with that ID does not exists' });
  138. }
  139. },
  140. '/station/:id/skip': (stationId, socketId, cb) => {
  141. const station = stations.getStation(stationId);
  142. if (station) {
  143. var response = station.handleUserJoin(socketId);
  144. return cb(response);
  145. }
  146. else {
  147. return cb({ status: 'error', message: 'Room with that ID does not exists' });
  148. }
  149. },
  150. '/youtube/getVideos/:query': (query, cb) => {
  151. cb({
  152. type: "query",
  153. items: [
  154. {
  155. id: "39fk3490krf9",
  156. title: "Test Title",
  157. channel: "Test Channel",
  158. duration: 200,
  159. image: "https://i.ytimg.com/vi/lwg5yAuanPg/hqdefault.jpg?custom=true&w=196&h=110&stc=true&jpg444=true&jpgq=90&sp=68&sigh=DWOZl_nkv78qzj8WHPY1-53iQfA"
  160. },
  161. {
  162. id: "49iug05it",
  163. title: "Test Title 222",
  164. channel: "Test Channel 222",
  165. duration: 100,
  166. image: "https://i.ytimg.com/vi/QJwIsBoe3Lg/hqdefault.jpg?custom=true&w=196&h=110&stc=true&jpg444=true&jpgq=90&sp=68&sigh=8L20nlTyPf7xuIB8DTeBQFWW2Xw"
  167. }
  168. ]
  169. });
  170. },
  171. '/songs/queue/addSongs/:songs': (songs, user, cb) => {
  172. if (user !== null && user !== undefined && user.logged_in) {
  173. if (Array.isArray(songs)) {
  174. if (songs.length > 0) {
  175. let failed = 0;
  176. let success = 0;
  177. songs.forEach(function (song) {
  178. if (typeof song === "object" && song !== null) {
  179. let obj = {};
  180. obj.title = song.title;
  181. obj._id = song.id;
  182. obj.artists = [];
  183. obj.image = "test";
  184. obj.duration = 0;
  185. obj.genres = ["edm"];
  186. //TODO Get data from Wikipedia and Spotify
  187. obj.requestedBy = user._id;
  188. console.log(user._id);
  189. console.log(user);
  190. obj.requestedAt = Date.now();
  191. let queueSong = new global.db.queueSong(obj);
  192. queueSong.save(function(err) {
  193. console.log(err);
  194. if (err) failed++;
  195. else success++;
  196. });
  197. } else {
  198. failed++;
  199. }
  200. });
  201. cb({success, failed});
  202. } else {
  203. cb({err: "No songs supplied."});
  204. }
  205. } else {
  206. cb({err: "Not supplied an array."});
  207. }
  208. } else {
  209. cb({err: "Not logged in."});
  210. }
  211. },
  212. '/songs/queue/getSongs': (user, cb) => {
  213. if (user !== null && user !== undefined && user.logged_in) {
  214. global.db.queueSong.find({}, function(err, songs) {
  215. if (err) throw err;
  216. else cb({songs: songs});
  217. });
  218. } else {
  219. cb({err: "Not logged in."});
  220. }
  221. },
  222. '/songs/queue/updateSong/:id': (user, id, object, cb) => {
  223. if (user !== null && user !== undefined && user.logged_in) {
  224. global.db.queueSong.findOne({_id: id}, function(err, song) {
  225. if (err) throw err;
  226. else {
  227. if (song !== undefined && song !== null) {
  228. if (typeof object === "object" && object !== null) {
  229. delete object.requestedBy;
  230. delete object.requestedAt;
  231. global.db.queueSong.update({_id: id}, {$set: object}, function(err, song) {
  232. if (err) throw err;
  233. cb({success: true});
  234. });
  235. } else {
  236. cb({err: "Invalid data."});
  237. }
  238. } else {
  239. cb({err: "Song not found."});
  240. }
  241. }
  242. });
  243. } else {
  244. cb({err: "Not logged in."});
  245. }
  246. },
  247. /*'/stations/search/:query': (query, cb) => {
  248. const params = [
  249. 'part=snippet',
  250. `q=${encodeURIComponent(query)}`,
  251. `key=${config.get('apis.youtube.key')}`,
  252. 'type=video',
  253. 'maxResults=25'
  254. ].join('&');
  255. request(`https://www.googleapis.com/youtube/v3/search?${params}`, (err, res, body) => {
  256. if (err) {
  257. return cb({ status: 'error', message: 'Failed to make request' });
  258. }
  259. else {
  260. try {
  261. return cb({ status: 'success', body: JSON.parse(body) });
  262. }
  263. catch (e) {
  264. return cb({ status: 'error', message: 'Non JSON response' });
  265. }
  266. }
  267. });
  268. },*/
  269. '/song/:id/toggleLike': (songId, userId, cb) => {
  270. var user = global.db.user.findOne(userId);
  271. var song = global.db.song.findOne(songId);
  272. if (user !== undefined) {
  273. if (song !== undefined) {
  274. var liked = false;
  275. if (song.likes.indexOf(userId) === -1) {
  276. liked = true;
  277. // Add like
  278. } else {
  279. // Remove like
  280. }
  281. if (song.dislikes.indexOf(userId) !== -1) {
  282. // Remove dislike
  283. }
  284. // Emit to all sockets with this user that their likes/dislikes updated.
  285. // Emit to all sockets in the room that the likes/dislikes has updated
  286. cb({liked: liked, disliked: false});
  287. } else {
  288. cb({err: "Song not found."});
  289. }
  290. } else {
  291. cb({err: "User not found."});
  292. }
  293. },
  294. '/user/:id/ratings': (userId, cb) => {
  295. var user = global.db.user.findOne(userId);
  296. if (user !== undefined) {
  297. cb({likes: user.likes, dislikes: user.dislikes});
  298. } else {
  299. cb({err: "User not found."});
  300. }
  301. }
  302. };