app.js 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929
  1. History = new Mongo.Collection("history");
  2. Playlists = new Mongo.Collection("playlists");
  3. Rooms = new Mongo.Collection("rooms");
  4. Queues = new Mongo.Collection("queues");
  5. if (Meteor.isClient) {
  6. Meteor.startup(function() {
  7. reCAPTCHA.config({
  8. publickey: '6LcVxg0TAAAAAE18vBiH00UAyaJggsmLm890SjZl'
  9. });
  10. });
  11. Meteor.subscribe("queues");
  12. var hpSound = undefined;
  13. var songsArr = [];
  14. var ytArr = [];
  15. var _sound = undefined;
  16. var parts = location.href.split('/');
  17. var id = parts.pop();
  18. var type = id.toLowerCase();
  19. function getSpotifyInfo(title, cb) {
  20. $.ajax({
  21. type: "GET",
  22. url: 'https://api.spotify.com/v1/search?q=' + encodeURIComponent(title.toLowerCase()) + '&type=track',
  23. applicationType: "application/json",
  24. contentType: "json",
  25. success: function (data) {
  26. cb(data);
  27. }
  28. });
  29. }
  30. function getSpotifyArtist(data) {
  31. var temp = "";
  32. var artist;
  33. if(data.artists.length >= 2){
  34. for(var k in data.artists){
  35. temp = temp + data.artists[k].name + ", ";
  36. }
  37. } else{
  38. for(var k in data.artists){
  39. temp = temp + data.artists[k].name;
  40. }
  41. }
  42. if(temp[temp.length-2] === ","){
  43. artist = temp.substr(0,temp.length-2);
  44. } else{
  45. artist = temp;
  46. }
  47. return artist;
  48. }
  49. Template.register.events({
  50. "submit form": function(e){
  51. e.preventDefault();
  52. var username = e.target.registerUsername.value;
  53. var email = e.target.registerEmail.value;
  54. var password = e.target.registerPassword.value;
  55. var captchaData = grecaptcha.getResponse();
  56. Meteor.call("createUserMethod", {username: username, email: email, password: password}, captchaData, function(err, res) {
  57. grecaptcha.reset();
  58. if (err) {
  59. console.log(err);
  60. $(".container").after('<div class="alert alert-danger" role="alert"><strong>Oh Snap!</strong> ' + err.reason + '</div>')
  61. } else {
  62. Meteor.loginWithPassword(username, password);
  63. }
  64. });
  65. },
  66. "click #facebook-login": function(){
  67. Meteor.loginWithFacebook()
  68. },
  69. "click #github-login": function(){
  70. Meteor.loginWithGithub()
  71. },
  72. "click #login": function(){
  73. $("#register-view").hide();
  74. $("#login-view").show();
  75. }
  76. });
  77. Template.login.events({
  78. "submit form": function(e){
  79. e.preventDefault();
  80. var username = e.target.loginUsername.value;
  81. var password = e.target.loginPassword.value;
  82. Meteor.loginWithPassword(username, password);
  83. Accounts.onLoginFailure(function(){
  84. $("input").css("background-color","indianred").addClass("animated shake");
  85. $("input").on("click",function(){
  86. $("input").css({
  87. "background-color": "transparent",
  88. "width": "250px"
  89. });
  90. })
  91. });
  92. },
  93. "click #facebook-login": function(){
  94. Meteor.loginWithFacebook()
  95. },
  96. "click #github-login": function(){
  97. Meteor.loginWithGithub()
  98. },
  99. "click #register": function(){
  100. $("#login-view").hide();
  101. $("#register-view").show();
  102. }
  103. });
  104. Template.dashboard.events({
  105. "click .logout": function(e){
  106. e.preventDefault();
  107. Meteor.logout();
  108. if (hpSound !== undefined) {
  109. hpSound.stop();
  110. }
  111. },
  112. "click #croom_create": function() {
  113. Meteor.call("createRoom", $("#croom").val(), function (err, res) {
  114. if (err) {
  115. alert("Error " + err.error + ": " + err.reason);
  116. } else {
  117. window.location = "/" + $("#croom").val();
  118. }
  119. });
  120. }
  121. });
  122. Template.dashboard.helpers({
  123. rooms: function() {
  124. return Rooms.find({});
  125. }
  126. })
  127. Template.room.events({
  128. "click #add-song-button": function(e){
  129. e.preventDefault();
  130. parts = location.href.split('/');
  131. id = parts.pop();
  132. var genre = id.toLowerCase();
  133. var type = $("#type").val();
  134. id = $("#id").val();
  135. var title = $("#title").val();
  136. var artist = $("#artist").val();
  137. var songData = {type: type, id: id, title: title, artist: artist};
  138. Meteor.call("addSongToQueue", genre, songData, function(err, res) {
  139. console.log(err, res);
  140. });
  141. },
  142. "click #return": function(e){
  143. $("#add-info").hide();
  144. $("#search-info").show();
  145. },
  146. "click #search-song": function(){
  147. $("#song-results").empty();
  148. var search_type = $("#search_type").val();
  149. if (search_type === "YouTube") {
  150. $.ajax({
  151. type: "GET",
  152. url: "https://www.googleapis.com/youtube/v3/search?part=snippet&q=" + $("#song-input").val() + "&key=AIzaSyAgBdacEWrHCHVPPM4k-AFM7uXg-Q__YXY",
  153. applicationType: "application/json",
  154. contentType: "json",
  155. success: function(data){
  156. for(var i in data.items){
  157. $("#song-results").append("<p>" + data.items[i].snippet.title + "</p>");
  158. ytArr.push({title: data.items[i].snippet.title, id: data.items[i].id.videoId});
  159. }
  160. $("#song-results p").click(function(){
  161. $("#search-info").hide();
  162. $("#add-info").show();
  163. var title = $(this).text();
  164. for(var i in ytArr){
  165. if(ytArr[i].title === title){
  166. var songObj = {
  167. id: ytArr[i].id,
  168. title: ytArr[i].title,
  169. type: "youtube"
  170. };
  171. // Set title field
  172. $("#title").val(songObj.title);
  173. // Set ID field
  174. $("#artist").val("");
  175. $("#id").val(songObj.id);
  176. $("#type").val("YouTube");
  177. getSpotifyInfo(songObj.title.replace(/\[.*\]/g, ""), function(data) {
  178. if (data.tracks.items.length > 0) {
  179. $("#title").val(data.tracks.items[0].name);
  180. var artists = [];
  181. data.tracks.items[0].artists.forEach(function(artist) {
  182. artists.push(artist.name);
  183. });
  184. $("#artist").val(artists.join(", "));
  185. }
  186. // Set title field again if possible
  187. // Set artist if possible
  188. });
  189. }
  190. }
  191. })
  192. }
  193. })
  194. } else if (search_type === "SoundCloud") {
  195. SC.get('/tracks', { q: $("#song-input").val()}, function(tracks) {
  196. for(var i in tracks){
  197. $("#song-results").append("<p>" + tracks[i].title + "</p>")
  198. songsArr.push({title: tracks[i].title, id: tracks[i].id, duration: tracks[i].duration / 1000});
  199. }
  200. $("#song-results p").click(function(){
  201. $("#search-info").hide();
  202. $("#add-info").show();
  203. var title = $(this).text();
  204. for(var i in songsArr){
  205. if(songsArr[i].title === title){
  206. var id = songsArr[i].id;
  207. var duration = songsArr[i].duration;
  208. var songObj = {
  209. title: songsArr[i].title,
  210. id: id,
  211. duration: duration,
  212. type: "soundcloud"
  213. }
  214. $("#title").val(songObj.title);
  215. // Set ID field
  216. $("#id").val(songObj.id);
  217. $("#type").val("SoundCloud");
  218. getSpotifyInfo(songObj.title.replace(/\[.*\]/g, ""), function(data) {
  219. if (data.tracks.items.length > 0) {
  220. $("#title").val(data.tracks.items[0].name);
  221. var artists = [];
  222. data.tracks.items[0].artists.forEach(function(artist) {
  223. artists.push(artist.name);
  224. });
  225. $("#artist").val(artists.join(", "));
  226. }
  227. // Set title field again if possible
  228. // Set artist if possible
  229. });
  230. }
  231. }
  232. })
  233. });
  234. }
  235. },
  236. "click #add-songs": function(){
  237. $("#add-songs-modal").show();
  238. },
  239. "click #close-modal": function(){
  240. $("#search-info").show();
  241. $("#add-info").hide();
  242. }
  243. });
  244. Template.room.helpers({
  245. type: function() {
  246. var parts = location.href.split('/');
  247. var id = parts.pop();
  248. return id.toUpperCase();
  249. },
  250. title: function(){
  251. return Session.get("title");
  252. },
  253. artist: function(){
  254. return Session.get("artist");
  255. },
  256. title_next: function(){
  257. return Session.get("title_next");
  258. },
  259. artist_next: function(){
  260. return Session.get("artist_next");
  261. },
  262. title_after: function(){
  263. return Session.get("title_after");
  264. },
  265. artist_after: function(){
  266. return Session.get("artist_after");
  267. },
  268. loaded: function() {
  269. return Session.get("loaded");
  270. }
  271. });
  272. Template.admin.helpers({
  273. queues: function() {
  274. return Queues.find({});
  275. }
  276. });
  277. var yt_player = undefined;
  278. var _sound = undefined;
  279. Template.admin.events({
  280. "click .preview-button": function(e){
  281. Session.set("song", this);
  282. },
  283. "click #add-song-button": function(e){
  284. var genre = $(e.toElement).data("genre") || $(e.toElement).parent().data("genre");
  285. Meteor.call("addSongToPlaylist", genre, this);
  286. },
  287. "click #deny-song-button": function(e){
  288. var genre = $(e.toElement).data("genre") || $(e.toElement).parent().data("genre");
  289. Meteor.call("removeSongFromQueue", genre, this.id);
  290. },
  291. "click #play": function() {
  292. $("#play").attr("disabled", true);
  293. $("#stop").attr("disabled", false);
  294. var song = Session.get("song");
  295. var id = song.id;
  296. var type = song.type;
  297. if (type === "YouTube") {
  298. if (yt_player === undefined) {
  299. yt_player = new YT.Player("previewPlayer", {
  300. height: 540,
  301. width: 568,
  302. videoId: id,
  303. playerVars: {autoplay: 1, controls: 0, iv_load_policy: 3},
  304. events: {
  305. 'onReady': function(event) {
  306. console.log("WOOH! Does it work?");
  307. event.target.playVideo();
  308. }
  309. }
  310. });
  311. } else {
  312. yt_player.loadVideoById(id);
  313. }
  314. $("#previewPlayer").show();
  315. } else if (type === "SoundCloud") {
  316. SC.stream("/tracks/" + song.id, function(sound) {
  317. _sound = sound;
  318. sound._player._volume = 0.3;
  319. sound.play();
  320. });
  321. }
  322. },
  323. "click #stop": function() {
  324. $("#play").attr("disabled", false);
  325. $("#stop").attr("disabled", true);
  326. if (yt_player !== undefined) {
  327. yt_player.stopVideo();
  328. }
  329. if (_sound !== undefined) {
  330. _sound.stop();
  331. }
  332. }
  333. });
  334. Template.admin.onCreated(function() {
  335. var tag = document.createElement("script");
  336. tag.src = "https://www.youtube.com/iframe_api";
  337. var firstScriptTag = document.getElementsByTagName('script')[0];
  338. firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  339. });
  340. Template.admin.onRendered(function() {
  341. $("#previewModal").on("hidden.bs.modal", function() {
  342. if (yt_player !== undefined) {
  343. $("#play").attr("disabled", false);
  344. $("#stop").attr("disabled", true);
  345. $("#previewPlayer").hide();
  346. yt_player.loadVideoById("", 0);
  347. yt_player.seekTo(0);
  348. yt_player.stopVideo();
  349. }
  350. if (_sound !== undefined) {
  351. _sound.stop();
  352. $("#play").attr("disabled", false);
  353. $("#stop").attr("disabled", true);
  354. }
  355. });
  356. });
  357. Template.playlist.helpers({
  358. playlist_songs: function() {
  359. var data = Playlists.find({type: type}).fetch();
  360. if (data !== undefined && data.length > 0) {
  361. return data[0].songs;
  362. } else {
  363. return [];
  364. }
  365. }
  366. });
  367. Meteor.subscribe("rooms");
  368. Template.room.onCreated(function () {
  369. var tag = document.createElement("script");
  370. tag.src = "https://www.youtube.com/iframe_api";
  371. var firstScriptTag = document.getElementsByTagName('script')[0];
  372. firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  373. var currentSong = undefined;
  374. var nextSong = undefined;
  375. var afterSong = undefined;
  376. var _sound = undefined;
  377. var yt_player = undefined;
  378. var size = 0;
  379. var artistStr;
  380. var temp = "";
  381. var currentArt;
  382. function getTimeElapsed() {
  383. if (currentSong !== undefined) {
  384. return Date.now() - currentSong.started;
  385. }
  386. return 0;
  387. }
  388. function getSongInfo(query, artistName, platform){
  389. var search = query;
  390. var titles = [];
  391. getSpotifyInfo(query, function(data) {
  392. for(var i in data){
  393. for(var j in data[i].items){
  394. if(search.indexOf(data[i].items[j].name) !== -1 && artistName.indexOf(data[i].items[j].artists[0].name) !== -1){
  395. var info = data[i].items[j];
  396. Session.set("title", data[i].items[j].name);
  397. if(platform === "youtube"){
  398. Session.set("duration", data[i].items[j].duration_ms / 1000)
  399. }
  400. var artist = getSpotifyArtist(data[i].items[j]);
  401. Session.set("artist", artist);
  402. $("#song-img").attr("src", data[i].items[j].album.images[1].url);
  403. return true;
  404. }
  405. }
  406. //---------------------------------------------------------------//
  407. }
  408. });
  409. }
  410. function getNextSongInfo(query, artistName, platform){
  411. var search = query;
  412. var titles = [];
  413. getSpotifyInfo(query, function(data) {
  414. for(var i in data){
  415. for(var j in data[i].items){
  416. if(search.indexOf(data[i].items[j].name) !== -1 && artistName.indexOf(data[i].items[j].artists[0].name) !== -1){
  417. var info = data[i].items[j];
  418. Session.set("title_next", data[i].items[j].name);
  419. var artist = getSpotifyArtist(data[i].items[j]);
  420. Session.set("artist_next", artist);
  421. $("#song-img-next").attr("src", data[i].items[j].album.images[1].url);
  422. return true;
  423. }
  424. }
  425. //---------------------------------------------------------------//
  426. }
  427. });
  428. }
  429. function getAfterSongInfo(query, artistName, platform){
  430. var search = query;
  431. var titles = [];
  432. getSpotifyInfo(query, function(data) {
  433. for(var i in data){
  434. for(var j in data[i].items){
  435. if(search.indexOf(data[i].items[j].name) !== -1 && artistName.indexOf(data[i].items[j].artists[0].name) !== -1){
  436. var info = data[i].items[j];
  437. Session.set("title_after", data[i].items[j].name);
  438. var artist = getSpotifyArtist(data[i].items[j]);
  439. Session.set("artist_after", artist);
  440. $("#song-img-after").attr("src", data[i].items[j].album.images[1].url);
  441. return true;
  442. }
  443. }
  444. //---------------------------------------------------------------//
  445. }
  446. });
  447. }
  448. function resizeSeekerbar() {
  449. $("#seeker-bar").width(((getTimeElapsed() / 1000) / Session.get("duration") * 100) + "%");
  450. }
  451. function startSong() {
  452. if (currentSong !== undefined) {
  453. if (_sound !== undefined) _sound.stop();
  454. if (yt_player !== undefined && yt_player.stopVideo !== undefined) yt_player.stopVideo();
  455. if (currentSong.song.type === "soundcloud") {
  456. $("#player").attr("src", "")
  457. getSongInfo(currentSong.song.title, currentSong.song.artist, "soundcloud");
  458. SC.stream("/tracks/" + currentSong.song.id + "#t=20s", function(sound){
  459. _sound = sound;
  460. sound._player._volume = 0.3;
  461. sound.play();
  462. var interval = setInterval(function() {
  463. if (sound.getState() === "playing") {
  464. sound.seek(getTimeElapsed());
  465. window.clearInterval(interval);
  466. }
  467. }, 200);
  468. // Session.set("title", currentSong.song.title || "Title");
  469. // Session.set("artist", currentSong.song.artist || "Artist");
  470. Session.set("duration", currentSong.song.duration);
  471. resizeSeekerbar();
  472. });
  473. } else {
  474. if (yt_player === undefined) {
  475. yt_player = new YT.Player("player", {
  476. height: 540,
  477. width: 960,
  478. videoId: currentSong.song.id,
  479. events: {
  480. 'onReady': function(event) {
  481. event.target.seekTo(getTimeElapsed() / 1000);
  482. event.target.playVideo();
  483. resizeSeekerbar();
  484. },
  485. 'onStateChange': function(event){
  486. if (event.data == YT.PlayerState.PAUSED) {
  487. event.target.seekTo(getTimeElapsed() / 1000);
  488. event.target.playVideo();
  489. }
  490. }
  491. }
  492. });
  493. } else {
  494. yt_player.loadVideoById(currentSong.song.id);
  495. }
  496. // Session.set("title", currentSong.song.title || "Title");
  497. // Session.set("artist", currentSong.song.artist || "Artist");
  498. getSongInfo(currentSong.song.title, currentSong.song.artist, "youtube");
  499. //Session.set("duration", currentSong.song.duration);
  500. }
  501. }
  502. }
  503. Meteor.subscribe("history");
  504. Meteor.subscribe("playlists");
  505. Session.set("loaded", false);
  506. Meteor.subscribe("rooms", function() {
  507. var parts = location.href.split('/');
  508. var id = parts.pop();
  509. var type = id.toLowerCase();
  510. if (Rooms.find({type: type}).count() !== 1) {
  511. window.location = "/";
  512. } else {
  513. Session.set("loaded", true);
  514. Meteor.setInterval(function () {
  515. var data = undefined;
  516. var dataCursorH = History.find({type: type});
  517. var dataCursorP = Playlists.find({type: type});
  518. dataCursorH.forEach(function (doc) {
  519. if (data === undefined) {
  520. data = doc;
  521. }
  522. });
  523. if (data !== undefined && data.history.length > size) {
  524. currentSong = data.history[data.history.length - 1];
  525. var songs = dataCursorP.fetch()[0].songs;
  526. songs.forEach(function(song, index) {
  527. if (currentSong.song.title === song.title) {
  528. if (index + 1 < songs.length) {
  529. // INDEX+1
  530. nextSong = songs[index + 1];
  531. } else {
  532. // 0
  533. nextSong = songs[0];
  534. }
  535. getNextSongInfo(nextSong.title, nextSong.artist, nextSong.type);
  536. if (index + 2 < songs.length) {
  537. afterSong = songs[index + 2];
  538. } else if (songs.length === index + 1 && songs.length > 1 ) {
  539. afterSong = songs[1];
  540. } else {
  541. afterSong = songs[0];
  542. }
  543. getAfterSongInfo(afterSong.title, afterSong.artist, afterSong.type);
  544. }
  545. });
  546. size = data.history.length;
  547. startSong();
  548. }
  549. }, 1000);
  550. Meteor.setInterval(function () {
  551. resizeSeekerbar();
  552. }, 50);
  553. }
  554. });
  555. });
  556. }
  557. if (Meteor.isServer) {
  558. Meteor.startup(function() {
  559. reCAPTCHA.config({
  560. privatekey: '6LcVxg0TAAAAAI2fgIEEWHFxwNXeVIs8mzq5cfRM'
  561. });
  562. });
  563. Meteor.users.deny({update: function () { return true; }});
  564. Meteor.users.deny({insert: function () { return true; }});
  565. Meteor.users.deny({remove: function () { return true; }});
  566. function getSongDuration(query){
  567. var duration;
  568. var search = query;
  569. query = query.toLowerCase().split(" ").join("%20");
  570. var res = Meteor.http.get('https://api.spotify.com/v1/search?q=' + query + '&type=track');
  571. for(var i in res.data){
  572. for(var j in res.data[i].items){
  573. if(search.indexOf(res.data[i].items[j].name) !== -1){
  574. duration = res.data[i].items[j].duration_ms / 1000;
  575. return duration;
  576. }
  577. }
  578. }
  579. }
  580. function getSongAlbumArt(query){
  581. var albumart;
  582. var search = query;
  583. query = query.toLowerCase().split(" ").join("%20");
  584. var res = Meteor.http.get('https://api.spotify.com/v1/search?q=' + query + '&type=track');
  585. for(var i in res.data){
  586. for(var j in res.data[i].items){
  587. if(search.indexOf(res.data[i].items[j].name) !== -1){
  588. albumart = res.data[i].items[j].album.images[1].url
  589. return albumart;
  590. }
  591. }
  592. }
  593. }
  594. //var room_types = ["edm", "nightcore"];
  595. var songsArr = [];
  596. function getSongsByType(type) {
  597. if (type === "edm") {
  598. return [
  599. {id: "aE2GCa-_nyU", title: "Radioactive - Lindsey Stirling and Pentatonix", duration: getSongDuration("Radioactive - Lindsey Stirling and Pentatonix"), albumart: getSongAlbumArt("Radioactive - Lindsey Stirling and Pentatonix"), artist: "Lindsey Stirling, Pentatonix", type: "youtube"},
  600. {id: "aHjpOzsQ9YI", title: "Crystallize", artist: "Lindsey Stirling", duration: getSongDuration("Crystallize"), albumart: getSongAlbumArt("Crystallize"), type: "youtube"}
  601. ];
  602. } else if (type === "nightcore") {
  603. return [{id: "f7RKOP87tt4", title: "Monster (DotEXE Remix)", duration: getSongDuration("Monster (DotEXE Remix)"), albumart: getSongAlbumArt("Monster (DotEXE Remix)"), artist: "Meg & Dia", type: "youtube"}];
  604. } else {
  605. return [{id: "dQw4w9WgXcQ", title: "Never Gonna Give You Up", duration: getSongDuration("Never Gonna Give You Up"), albumart: getSongAlbumArt("Never Gonna Give You Up"), artist: "Rick Astley", type: "youtube"}];
  606. }
  607. }
  608. Rooms.find({}).fetch().forEach(function(room) {
  609. var type = room.type;
  610. if (Playlists.find({type: type}).count() === 0) {
  611. if (type === "edm") {
  612. Playlists.insert({type: type, songs: getSongsByType(type)});
  613. } else if (type === "nightcore") {
  614. Playlists.insert({type: type, songs: getSongsByType(type)});
  615. } else {
  616. Playlists.insert({type: type, songs: getSongsByType(type)});
  617. }
  618. }
  619. if (History.find({type: type}).count() === 0) {
  620. History.insert({type: type, history: []});
  621. }
  622. if (Playlists.find({type: type}).fetch()[0].songs.length === 0) {
  623. // Add a global video to Playlist so it can proceed
  624. } else {
  625. var startedAt = Date.now();
  626. var songs = Playlists.find({type: type}).fetch()[0].songs;
  627. var currentSong = 0;
  628. addToHistory(songs[currentSong], startedAt);
  629. function addToHistory(song, startedAt) {
  630. History.update({type: type}, {$push: {history: {song: song, started: startedAt}}});
  631. }
  632. function skipSong() {
  633. songs = Playlists.find({type: type}).fetch()[0].songs;
  634. if (currentSong < (songs.length - 1)) {
  635. currentSong++;
  636. } else currentSong = 0;
  637. songTimer();
  638. addToHistory(songs[currentSong], startedAt);
  639. }
  640. function songTimer() {
  641. startedAt = Date.now();
  642. Meteor.setTimeout(function() {
  643. skipSong();
  644. }, songs[currentSong].duration * 1000);
  645. }
  646. songTimer();
  647. }
  648. });
  649. Accounts.onCreateUser(function(options, user) {
  650. if (options.profile) {
  651. user.profile = options.profile;
  652. user.profile.rank = "default";
  653. }
  654. return user;
  655. });
  656. ServiceConfiguration.configurations.remove({
  657. service: "facebook"
  658. });
  659. ServiceConfiguration.configurations.insert({
  660. service: "facebook",
  661. appId: "1496014310695890",
  662. secret: "9a039f254a08a1488c08bb0737dbd2a6"
  663. });
  664. ServiceConfiguration.configurations.remove({
  665. service: "github"
  666. });
  667. ServiceConfiguration.configurations.insert({
  668. service: "github",
  669. clientId: "dcecd720f47c0e4001f7",
  670. secret: "375939d001ef1a0ca67c11dbf8fb9aeaa551e01b"
  671. });
  672. Meteor.publish("history", function() {
  673. return History.find({})
  674. });
  675. Meteor.publish("playlists", function() {
  676. return Playlists.find({})
  677. });
  678. Meteor.publish("rooms", function() {
  679. return Rooms.find({});
  680. });
  681. Meteor.publish("queues", function() {
  682. return Queues.find({});
  683. });
  684. Meteor.publish("isAdmin", function() {
  685. return Meteor.users.find({_id: this.userId, "profile.rank": "admin"});
  686. });
  687. Meteor.methods({
  688. createUserMethod: function(formData, captchaData) {
  689. var verifyCaptchaResponse = reCAPTCHA.verifyCaptcha(this.connection.clientAddress, captchaData);
  690. if (!verifyCaptchaResponse.success) {
  691. console.log('reCAPTCHA check failed!', verifyCaptchaResponse);
  692. throw new Meteor.Error(422, 'reCAPTCHA Failed: ' + verifyCaptchaResponse.error);
  693. } else {
  694. console.log('reCAPTCHA verification passed!');
  695. Accounts.createUser({
  696. username: formData.username,
  697. email: formData.email,
  698. password: formData.password
  699. });
  700. }
  701. return true;
  702. },
  703. addSongToQueue: function(type, songData) {
  704. type = type.toLowerCase();
  705. if (Rooms.find({type: type}).count() === 1) {
  706. if (Queues.find({type: type}).count() === 0) {
  707. Queues.insert({type: type, songs: []});
  708. }
  709. if (songData !== undefined && Object.keys(songData).length === 4 && songData.type !== undefined && songData.title !== undefined && songData.title !== undefined && songData.artist !== undefined) {
  710. songData.duration = getSongDuration(songData.title);
  711. Queues.update({type: type}, {$push: {songs: {id: songData.id, title: songData.title, artist: songData.artist, duration: songData.duration, type: songData.type}}});
  712. return true;
  713. } else {
  714. throw new Meteor.error(403, "Invalid data.");
  715. }
  716. } else {
  717. throw new Meteor.error(403, "Invalid genre.");
  718. }
  719. },
  720. removeSongFromQueue: function(type, songId) {
  721. type = type.toLowerCase();
  722. Queues.update({type: type}, {$pull: {songs: {id: songId}}});
  723. },
  724. addSongToPlaylist: function(type, songData) {
  725. type = type.toLowerCase();
  726. if (Rooms.find({type: type}).count() === 1) {
  727. if (Playlists.find({type: type}).count() === 0) {
  728. Playlists.insert({type: type, songs: []});
  729. }
  730. if (songData !== undefined && Object.keys(songData).length === 5 && songData.type !== undefined && songData.title !== undefined && songData.title !== undefined && songData.artist !== undefined && songData.duration !== undefined) {
  731. Playlists.update({type: type}, {$push: {songs: {id: songData.id, title: songData.title, artist: songData.artist, duration: songData.duration, type: songData.type}}});
  732. Queues.update({type: type}, {$pull: {songs: {id: songData.id}}});
  733. return true;
  734. } else {
  735. throw new Meteor.error(403, "Invalid data.");
  736. }
  737. } else {
  738. throw new Meteor.error(403, "Invalid genre.");
  739. }
  740. },
  741. createRoom: function(type) {
  742. if (Rooms.find({type: type}).count() === 0) {
  743. Rooms.insert({type: type}, function(err) {
  744. if (err) {
  745. throw err;
  746. } else {
  747. if (Playlists.find({type: type}).count() === 1) {
  748. if (History.find({type: type}).count() === 0) {
  749. History.insert({type: type, history: []}, function(err3) {
  750. if (err3) {
  751. throw err3;
  752. } else {
  753. startStation();
  754. return true;
  755. }
  756. });
  757. } else {
  758. startStation();
  759. return true;
  760. }
  761. } else {
  762. Playlists.insert({type: type, songs: getSongsByType(type)}, function (err2) {
  763. if (err2) {
  764. throw err2;
  765. } else {
  766. if (History.find({type: type}).count() === 0) {
  767. History.insert({type: type, history: []}, function(err3) {
  768. if (err3) {
  769. throw err3;
  770. } else {
  771. startStation();
  772. return true;
  773. }
  774. });
  775. } else {
  776. startStation();
  777. return true;
  778. }
  779. }
  780. });
  781. }
  782. }
  783. });
  784. } else {
  785. throw "Room already exists";
  786. }
  787. function startStation() {
  788. var startedAt = Date.now();
  789. var songs = Playlists.find({type: type}).fetch()[0].songs;
  790. var currentSong = 0;
  791. addToHistory(songs[currentSong], startedAt);
  792. function addToHistory(song, startedAt) {
  793. History.update({type: type}, {$push: {history: {song: song, started: startedAt}}});
  794. }
  795. function skipSong() {
  796. songs = Playlists.find({type: type}).fetch()[0].songs;
  797. if (currentSong < (songs.length - 1)) {
  798. currentSong++;
  799. } else currentSong = 0;
  800. songTimer();
  801. addToHistory(songs[currentSong], startedAt);
  802. }
  803. function songTimer() {
  804. startedAt = Date.now();
  805. Meteor.setTimeout(function() {
  806. skipSong();
  807. }, songs[currentSong].duration * 1000);
  808. }
  809. songTimer();
  810. }
  811. }
  812. });
  813. }
  814. /*Router.waitOn(function() {
  815. Meteor.subscribe("isAdmin", Meteor.userId());
  816. });*/
  817. /*Router.onBeforeAction(function() {
  818. /*Meteor.autorun(function () {
  819. if (admin.ready()) {
  820. this.next();
  821. }
  822. });*/
  823. /*this.next();
  824. });*/
  825. Router.route("/", {
  826. template: "home"
  827. });
  828. Router.route("/terms", {
  829. template: "terms"
  830. });
  831. Router.route("/privacy", {
  832. template: "privacy"
  833. });
  834. Router.route("/admin", {
  835. waitOn: function() {
  836. return Meteor.subscribe("isAdmin", Meteor.userId());
  837. },
  838. action: function() {
  839. var user = Meteor.users.find({}).fetch();
  840. if (user[0] !== undefined && user[0].profile !== undefined && user[0].profile.rank === "admin") {
  841. this.render("admin");
  842. } else {
  843. this.redirect("/");
  844. }
  845. }
  846. });
  847. Router.route("/:type", {
  848. template: "room"
  849. });