app.js 42 KB

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