app.js 44 KB

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