client.js 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246
  1. Meteor.startup(function() {
  2. reCAPTCHA.config({
  3. publickey: '6LcVxg0TAAAAAE18vBiH00UAyaJggsmLm890SjZl'
  4. });
  5. });
  6. Meteor.subscribe("queues");
  7. Meteor.subscribe("reports");
  8. Meteor.subscribe("chat");
  9. Meteor.subscribe("playlists");
  10. Meteor.subscribe("alerts");
  11. var minterval;
  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. var resizeSeekerbarInterval;
  20. var station_c = undefined;
  21. var songMID;
  22. UI.registerHelper("formatTime", function(seconds) {
  23. var d = moment.duration(parseInt(seconds), 'seconds');
  24. return d.minutes() + ":" + ("0" + d.seconds()).slice(-2);
  25. });
  26. /*UI.registerHelper("formatTimeFromNow", function(time) {
  27. var d = moment(time);
  28. return d.fromNow();
  29. });*/
  30. function getSpotifyInfo(title, cb, artist) {
  31. var q = "";
  32. q = title;
  33. if (artist !== undefined) {
  34. q += " artist:" + artist;
  35. }
  36. $.ajax({
  37. type: "GET",
  38. url: 'https://api.spotify.com/v1/search?q=' + encodeURIComponent(q) + '&type=track',
  39. applicationType: "application/json",
  40. contentType: "json",
  41. success: function (data) {
  42. cb(data);
  43. }
  44. });
  45. }
  46. Template.profile.helpers({
  47. "username": function() {
  48. return Session.get("username");
  49. },
  50. "first_joined": function() {
  51. return moment(Session.get("first_joined")).format("DD/MM/YYYY HH:mm:ss");
  52. },
  53. "rank": function() {
  54. return Session.get("rank");
  55. },
  56. loaded: function() {
  57. return Session.get("loaded");
  58. },
  59. likedSongs: function(){
  60. var user = Meteor.user();
  61. var likedArr = [];
  62. user.profile.liked.forEach(function(id){
  63. Rooms.find().forEach(function(room){
  64. Playlists.find({type: room.type}).forEach(function(pl){
  65. for(var i in pl.songs){
  66. if(pl.songs[i].mid === id){
  67. likedArr.push({title: pl.songs[i].title, artist: pl.songs[i].artist});
  68. }
  69. }
  70. });
  71. })
  72. })
  73. return likedArr;
  74. }
  75. });
  76. Template.profile.onCreated(function() {
  77. var parts = Router.current().url.split('/');
  78. var username = parts.pop();
  79. Session.set("loaded", false);
  80. Meteor.subscribe("userProfiles", function() {
  81. if (Meteor.users.find({"profile.usernameL": username.toLowerCase()}).count() === 0) {
  82. window.location = "/";
  83. } else {
  84. var data = Meteor.users.findOne({"profile.usernameL": username.toLowerCase()});
  85. Session.set("username", data.profile.username);
  86. Session.set("first_joined", data.createdAt);
  87. Session.set("rank", data.profile.rank);
  88. Session.set("loaded", true);
  89. }
  90. });
  91. });
  92. 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}}};
  93. Handlebars.registerHelper('active', function(path) {
  94. return curPath() == path ? 'active' : '';
  95. });
  96. Template.header.helpers({
  97. currentUser: function() {
  98. return Meteor.user();
  99. },
  100. isAdmin: function() {
  101. if (Meteor.user() && Meteor.user().profile) {
  102. return Meteor.user().profile.rank === "admin";
  103. } else {
  104. return false;
  105. }
  106. }
  107. });
  108. Template.header.events({
  109. "click .logout": function(e){
  110. e.preventDefault();
  111. Meteor.logout();
  112. if (hpSound !== undefined) {
  113. hpSound.stop();
  114. }
  115. }
  116. });
  117. Template.register.events({
  118. "submit form": function(e){
  119. e.preventDefault();
  120. var username = e.target.registerUsername.value;
  121. var email = e.target.registerEmail.value;
  122. var password = e.target.registerPassword.value;
  123. var captchaData = grecaptcha.getResponse();
  124. Meteor.call("createUserMethod", {username: username, email: email, password: password}, captchaData, function(err, res) {
  125. grecaptcha.reset();
  126. if (err) {
  127. console.log(err);
  128. var errAlert = $('<div class="alert alert-danger" role="alert"><strong>Oh Snap!</strong> ' + err.reason + '</div>');
  129. $("#login").after(errAlert);
  130. errAlert.fadeOut(20000, function() {
  131. errAlert.remove();
  132. });
  133. } else {
  134. Meteor.loginWithPassword(username, password);
  135. Accounts.onLogin(function(){
  136. window.location.href = "/";
  137. })
  138. }
  139. });
  140. },
  141. "click #github-login": function(){
  142. Meteor.loginWithGithub({loginStyle: "redirect"});
  143. }
  144. });
  145. Template.login.events({
  146. "submit form": function(e){
  147. e.preventDefault();
  148. var username = e.target.loginUsername.value;
  149. var password = e.target.loginPassword.value;
  150. Meteor.loginWithPassword(username, password);
  151. Accounts.onLogin(function(){
  152. window.location.href = "/";
  153. })
  154. Accounts.onLoginFailure(function(){
  155. $("#login-form input").css("background-color","indianred");
  156. $("#login-form input").on("click",function(){
  157. $("#login-form input").css({
  158. "-webkit-appearance": "none",
  159. " -moz-appearance": "none",
  160. " appearance": "none",
  161. "outline": "0",
  162. "border": "1px solid rgba(255, 255, 255, 0.4)",
  163. "background-color": "rgba(255, 255, 255, 0.2)",
  164. "width": "304px",
  165. "border-radius": "3px",
  166. "padding": "10px 15px",
  167. "margin": "0 auto 10px auto",
  168. "display": "block",
  169. "text-align": "center",
  170. "font-size": "18px",
  171. "color": "white",
  172. "-webkit-transition-duration": "0.25s",
  173. " transition-duration": "0.25s",
  174. "font-weight": "300"
  175. });
  176. $("#login-form input:focus").css({
  177. "width": "354px",
  178. "color": "white"
  179. })
  180. $("#login-form input").on("blur", function(){
  181. $(this).css("width", "304px");
  182. })
  183. })
  184. });
  185. },
  186. "click #github-login": function(){
  187. Meteor.loginWithGithub({loginStyle: "redirect"});
  188. }
  189. });
  190. Template.dashboard.helpers({
  191. rooms: function() {
  192. return Rooms.find({});
  193. },
  194. currentSong: function() {
  195. var type = this.type;
  196. var room = Rooms.findOne({type: type});
  197. if (room !== undefined) {
  198. return room.currentSong;
  199. } else {
  200. return {};
  201. }
  202. }
  203. });
  204. Template.dashboard.onCreated(function() {
  205. if (_sound !== undefined) _sound.stop();
  206. if (minterval !== undefined) {
  207. Meteor.clearInterval(minterval);
  208. }
  209. if (resizeSeekerbarInterval !== undefined) {
  210. Meteor.clearInterval(resizeSeekerbarInterval);
  211. resizeSeekerbarInterval = undefined;
  212. }
  213. if (station_c !== undefined) {
  214. station_c.stop();
  215. }
  216. Session.set("type", undefined);
  217. });
  218. Template.room.events({
  219. "click #sync": function() {
  220. if (Session.get("currentSong") !== undefined) {
  221. var room = Rooms.findOne({type: Session.get("type")});
  222. if (room !== undefined) {
  223. var timeIn = Date.now() - Session.get("currentSong").started - room.timePaused;
  224. console.log(timeIn);
  225. var skipDuration = Number(Session.get("currentSong").skipDuration) | 0;
  226. if (yt_player !== undefined) {
  227. yt_player.seekTo(skipDuration + timeIn / 1000);
  228. }
  229. else if (_sound !== undefined) {
  230. _sound.seekTo(skipDuration * 1000 + timeIn);
  231. }
  232. }
  233. }
  234. },
  235. "click #side-panel": function(e) {
  236. Meteor.setTimeout(function() {
  237. var elem = document.getElementById('chat');
  238. elem.scrollTop = elem.scrollHeight;;
  239. }, 1);
  240. },
  241. "click #submit": function() {
  242. Meteor.call("sendMessage", Session.get("type"), $("#chat-input").val(), function(err, res) {
  243. console.log(err, res);
  244. if (res) {
  245. $("#chat-input").val("");
  246. }
  247. });
  248. },
  249. "keyup #chat-input": function(e) {
  250. if (e.type == "keyup" && e.which == 13) {
  251. e.preventDefault();
  252. Meteor.call("sendMessage", Session.get("type"), $("#chat-input").val(), function(err, res) {
  253. console.log(err, res);
  254. if (res) {
  255. $("#chat-input").val("");
  256. }
  257. });
  258. }
  259. },
  260. "click #like": function(e) {
  261. Meteor.call("likeSong", Session.get("currentSong").mid);
  262. },
  263. "click #dislike": function(e) {
  264. Meteor.call("dislikeSong", Session.get("currentSong").mid);
  265. },
  266. "click #vote-skip": function(){
  267. Meteor.call("voteSkip", type, function(err, res) {
  268. $("#vote-skip").attr("disabled", true);
  269. });
  270. songMID = Session.get("currentSong").mid;
  271. },
  272. "click #report-prev": function(e) {
  273. if (Session.get("previousSong") !== undefined) {
  274. Session.set("reportPrevious", true);
  275. $("#report-prev").prop("disabled", true);
  276. $("#report-curr").prop("disabled", false);
  277. }
  278. },
  279. "click #report-curr": function(e) {
  280. Session.set("reportPrevious", false);
  281. $("#report-prev").prop("disabled", false);
  282. $("#report-curr").prop("disabled", true);
  283. },
  284. "click #report-modal": function() {
  285. Session.set("currentSongR", Session.get("currentSong"));
  286. Session.set("previousSongR", Session.get("previousSong"));
  287. },
  288. "click #add-song-button": function(e){
  289. e.preventDefault();
  290. parts = location.href.split('/');
  291. var roomType = parts.pop();
  292. var genre = id.toLowerCase();
  293. var type = $("#type").val();
  294. id = $("#id").val();
  295. var title = $("#title").val();
  296. var artist = $("#artist").val();
  297. var img = $("#img").val();
  298. var songData = {type: type, id: id, title: title, artist: artist, img: img};
  299. if(Playlists.find({type: roomType, "songs.title": songData.title}, {songs: {$elemMatch: {title: songData.title}}}).count() !== 0) {
  300. $(".landing").prepend("<div class='alert alert-danger alert-dismissible' role='alert' style='margin-bottom: 0'><button type='button' class='close' data-dismiss='alert' aria-label='Close'><span aria-hidden='true'><i class='fa fa-times'></i></span></button><strong>Song not added.</strong> This song is already is in the playlist.</div>");
  301. } else{
  302. Meteor.call("addSongToQueue", genre, songData, function(err, res) {
  303. console.log(err, res);
  304. });
  305. }
  306. $("#close-modal-a").click();
  307. },
  308. "click #toggle-video": function(e){
  309. e.preventDefault();
  310. if (Session.get("mediaHidden")) {
  311. $("#media-container").removeClass("hidden");
  312. $("#toggle-video").text("Hide video");
  313. Session.set("mediaHidden", false);
  314. } else {
  315. $("#media-container").addClass("hidden");
  316. $("#toggle-video").text("Show video");
  317. Session.set("mediaHidden", true);
  318. }
  319. },
  320. "click #return": function(e){
  321. $("#add-info").hide();
  322. $("#search-info").show();
  323. },
  324. "click #search-song": function(){
  325. $("#song-results").empty();
  326. var search_type = $("#search_type").val();
  327. if (search_type === "YouTube") {
  328. $.ajax({
  329. type: "GET",
  330. url: "https://www.googleapis.com/youtube/v3/search?part=snippet&q=" + $("#song-input").val() + "&key=AIzaSyAgBdacEWrHCHVPPM4k-AFM7uXg-Q__YXY",
  331. applicationType: "application/json",
  332. contentType: "json",
  333. success: function(data){
  334. for(var i in data.items){
  335. $("#song-results").append("<p>" + data.items[i].snippet.title + "</p>");
  336. ytArr.push({title: data.items[i].snippet.title, id: data.items[i].id.videoId});
  337. }
  338. $("#song-results p").click(function(){
  339. $("#search-info").hide();
  340. $("#add-info").show();
  341. var title = $(this).text();
  342. for(var i in ytArr){
  343. if(ytArr[i].title === title){
  344. var songObj = {
  345. id: ytArr[i].id,
  346. title: ytArr[i].title,
  347. type: "youtube"
  348. };
  349. $("#title").val(songObj.title);
  350. $("#artist").val("");
  351. $("#id").val(songObj.id);
  352. $("#type").val("YouTube");
  353. getSpotifyInfo(songObj.title.replace(/\[.*\]/g, ""), function(data) {
  354. if (data.tracks.items.length > 0) {
  355. $("#title").val(data.tracks.items[0].name);
  356. var artists = [];
  357. $("#img").val(data.tracks.items[0].album.images[1].url);
  358. data.tracks.items[0].artists.forEach(function(artist) {
  359. artists.push(artist.name);
  360. });
  361. $("#artist").val(artists.join(", "));
  362. }
  363. });
  364. }
  365. }
  366. })
  367. }
  368. })
  369. } else if (search_type === "SoundCloud") {
  370. SC.get('/tracks', { q: $("#song-input").val()}, function(tracks) {
  371. for(var i in tracks){
  372. $("#song-results").append("<p>" + tracks[i].title + "</p>")
  373. songsArr.push({title: tracks[i].title, id: tracks[i].id, duration: tracks[i].duration / 1000});
  374. }
  375. $("#song-results p").click(function(){
  376. $("#search-info").hide();
  377. $("#add-info").show();
  378. var title = $(this).text();
  379. for(var i in songsArr){
  380. if(songsArr[i].title === title){
  381. var id = songsArr[i].id;
  382. var duration = songsArr[i].duration;
  383. var songObj = {
  384. title: songsArr[i].title,
  385. id: id,
  386. duration: duration,
  387. type: "soundcloud"
  388. }
  389. $("#title").val(songObj.title);
  390. // Set ID field
  391. $("#id").val(songObj.id);
  392. $("#type").val("SoundCloud");
  393. getSpotifyInfo(songObj.title.replace(/\[.*\]/g, ""), function(data) {
  394. if (data.tracks.items.length > 0) {
  395. $("#title").val(data.tracks.items[0].name);
  396. var artists = [];
  397. data.tracks.items[0].artists.forEach(function(artist) {
  398. artists.push(artist.name);
  399. });
  400. $("#artist").val(artists.join(", "));
  401. }
  402. // Set title field again if possible
  403. // Set artist if possible
  404. });
  405. }
  406. }
  407. })
  408. });
  409. }
  410. },
  411. "click #close-modal-a": function(){
  412. $("#search-info").show();
  413. $("#add-info").hide();
  414. },
  415. "click #volume-icon": function(){
  416. var volume = 0;
  417. var slider = $("#volume-slider").slider();
  418. $("#volume-icon").removeClass("fa-volume-down").addClass("fa-volume-off")
  419. if (yt_player !== undefined) {
  420. yt_player.setVolume(volume);
  421. localStorage.setItem("volume", volume);
  422. $("#volume-slider").slider("setValue", volume);
  423. } else if (_sound !== undefined) {
  424. _sound.setVolume(volume);
  425. localStorage.setItem("volume", volume);
  426. $("#volume-slider").slider("setValue", volume);
  427. }
  428. },
  429. "click #play": function() {
  430. Meteor.call("resumeRoom", type);
  431. },
  432. "click #pause": function() {
  433. Meteor.call("pauseRoom", type);
  434. },
  435. "click #skip": function() {
  436. Meteor.call("skipSong", type);
  437. },
  438. "click #shuffle": function() {
  439. Meteor.call("shufflePlaylist", type);
  440. },
  441. "change input": function(e) {
  442. if (e.target && e.target.id) {
  443. var partsOfId = e.target.id.split("-");
  444. partsOfId[1] = partsOfId[1].charAt(0).toUpperCase() + partsOfId[1].slice(1);
  445. var camelCase = partsOfId.join("");
  446. Session.set(camelCase, e.target.checked);
  447. }
  448. },
  449. "click #report-song-button": function() {
  450. var report = {};
  451. report.reportSongB = $("#report-song").is(":checked");
  452. report.reportTitleB = $("#report-title").is(":checked");
  453. report.reportAuthorB = $("#report-author").is(":checked");
  454. report.reportDurationB = $("#report-duration").is(":checked");
  455. report.reportAudioB = $("#report-audio").is(":checked");
  456. report.reportAlbumartB = $("#report-albumart").is(":checked");
  457. report.reportOtherB = $("#report-other").is(":checked");
  458. if (report.reportSongB) {
  459. report.reportSong = {};
  460. report.reportSong.notPlayingB = $("#report-song-not-playing").is(":checked");
  461. report.reportSong.doesNotExistB = $("#report-song-does-not-exist").is(":checked");
  462. report.reportSong.otherB = $("#report-song-other").is(":checked");
  463. if (report.reportSong.otherB) {
  464. report.reportSong.other = $("#report-song-other-ta").val();
  465. }
  466. }
  467. if (report.reportTitleB) {
  468. report.reportTitle = {};
  469. report.reportTitle.incorrectB = $("#report-title-incorrect").is(":checked");
  470. report.reportTitle.inappropriateB = $("#report-title-inappropriate").is(":checked");
  471. report.reportTitle.otherB = $("#report-title-other").is(":checked");
  472. if (report.reportTitle.otherB) {
  473. report.reportTitle.other = $("#report-title-other-ta").val();
  474. }
  475. }
  476. if (report.reportAuthorB) {
  477. report.reportAuthor = {};
  478. report.reportAuthor.incorrectB = $("#report-author-incorrect").is(":checked");
  479. report.reportAuthor.inappropriateB = $("#report-author-inappropriate").is(":checked");
  480. report.reportAuthor.otherB = $("#report-author-other").is(":checked");
  481. if (report.reportAuthor.otherB) {
  482. report.reportAuthor.other = $("#report-author-other-ta").val();
  483. }
  484. }
  485. if (report.reportDurationB) {
  486. report.reportDuration = {};
  487. report.reportDuration.longB = $("#report-duration-incorrect").is(":checked");
  488. report.reportDuration.shortB = $("#report-duration-inappropriate").is(":checked");
  489. report.reportDuration.otherB = $("#report-duration-other").is(":checked");
  490. if (report.reportDuration.otherB) {
  491. report.reportDuration.other = $("#report-duration-other-ta").val();
  492. }
  493. }
  494. if (report.reportAudioB) {
  495. report.reportAudio = {};
  496. report.reportAudio.inappropriate = $("#report-audio-inappropriate").is(":checked");
  497. report.reportAudio.notPlayingB = $("#report-audio-incorrect").is(":checked");
  498. report.reportAudio.otherB = $("#report-audio-other").is(":checked");
  499. if (report.reportAudio.otherB) {
  500. report.reportAudio.other = $("#report-audio-other-ta").val();
  501. }
  502. }
  503. if (report.reportAlbumartB) {
  504. report.reportAlbumart = {};
  505. report.reportAlbumart.incorrectB = $("#report-albumart-incorrect").is(":checked");
  506. report.reportAlbumart.inappropriateB = $("#report-albumart-inappropriate").is(":checked");
  507. report.reportAlbumart.notShowingB = $("#report-albumart-inappropriate").is(":checked");
  508. report.reportAlbumart.otherB = $("#report-albumart-other").is(":checked");
  509. if (report.reportAlbumart.otherB) {
  510. report.reportAlbumart.other = $("#report-albumart-other-ta").val();
  511. }
  512. }
  513. if (report.reportOtherB) {
  514. report.other = $("#report-other-ta").val();
  515. }
  516. Meteor.call("submitReport", report, Session.get("id"), function() {
  517. $("#close-modal-r").click();
  518. });
  519. }
  520. });
  521. Template.room.onRendered(function() {
  522. $(document).ready(function() {
  523. function makeSlider(){
  524. var slider = $("#volume-slider").slider();
  525. var volume = localStorage.getItem("volume") || 20;
  526. $("#volume-slider").slider("setValue", volume);
  527. if (slider.length === 0) {
  528. Meteor.setTimeout(function() {
  529. makeSlider();
  530. }, 500);
  531. } else {
  532. slider.on("slide", function(val) {
  533. if (val.value === 0) {
  534. $("#volume-icon").removeClass("fa-volume-down").addClass("fa-volume-off")
  535. } else {
  536. $("#volume-icon").removeClass("fa-volume-off").addClass("fa-volume-down")
  537. }
  538. if (yt_player !== undefined) {
  539. yt_player.setVolume(val.value);
  540. localStorage.setItem("volume", val.value);
  541. } else if (_sound !== undefined) {
  542. //_sound
  543. var volume = val.value / 100;
  544. _sound.setVolume(volume);
  545. localStorage.setItem("volume", val.value);
  546. }
  547. });
  548. }
  549. }
  550. makeSlider();
  551. });
  552. });
  553. Template.alerts.helpers({
  554. alerts: function() {
  555. return Alerts.find({active: true});
  556. }
  557. });
  558. Template.room.helpers({
  559. chat: function() {
  560. Meteor.setTimeout(function() {
  561. var elem = document.getElementById('chat');
  562. if (elem !== undefined && elem !== null) {
  563. elem.scrollTop = elem.scrollHeight;
  564. }
  565. }, 100);
  566. return Chat.find({type: Session.get("type")}, {sort: {time: -1}, limit: 50 }).fetch().reverse();
  567. },
  568. likes: function() {
  569. var playlist = Playlists.findOne({type: Session.get("type")});
  570. var likes = 0;
  571. playlist.songs.forEach(function(song) {
  572. if (Session.get("currentSong") && song.mid === Session.get("currentSong").mid) {
  573. likes = song.likes;
  574. return;
  575. }
  576. });
  577. return likes;
  578. },
  579. dislikes: function() {
  580. var playlist = Playlists.findOne({type: Session.get("type")});
  581. var dislikes = 0;
  582. playlist.songs.forEach(function(song) {
  583. if (Session.get("currentSong") && song.mid === Session.get("currentSong").mid) {
  584. dislikes = song.dislikes;
  585. return;
  586. }
  587. });
  588. return dislikes;
  589. },
  590. liked: function() {
  591. if (Meteor.userId()) {
  592. var currentSong = Session.get("currentSong");
  593. if (currentSong && Meteor.user().profile.liked.indexOf(currentSong.mid) !== -1) {
  594. return "active";
  595. } else {
  596. return "";
  597. }
  598. } else {
  599. "";
  600. }
  601. },
  602. disliked: function() {
  603. if (Meteor.userId()) {
  604. var currentSong = Session.get("currentSong");
  605. if (currentSong && Meteor.user().profile.disliked.indexOf(currentSong.mid) !== -1) {
  606. return "active";
  607. } else {
  608. return "";
  609. }
  610. } else {
  611. "";
  612. }
  613. },
  614. type: function() {
  615. var parts = location.href.split('/');
  616. var id = parts.pop().toLowerCase();
  617. return Rooms.findOne({type: id}).display;
  618. },
  619. users: function() {
  620. var parts = location.href.split('/');
  621. var id = parts.pop().toLowerCase();
  622. return Rooms.findOne({type: id}).users;
  623. },
  624. title: function(){
  625. return Session.get("title");
  626. },
  627. artist: function(){
  628. return Session.get("artist");
  629. },
  630. loaded: function() {
  631. return Session.get("loaded");
  632. },
  633. isAdmin: function() {
  634. if (Meteor.user() && Meteor.user().profile) {
  635. return Meteor.user().profile.rank === "admin";
  636. } else {
  637. return false;
  638. }
  639. },
  640. paused: function() {
  641. return Session.get("state") === "paused";
  642. },
  643. report: function() {
  644. return Session.get("reportObj");
  645. },
  646. reportSong: function() {
  647. return Session.get("reportSong");
  648. },
  649. reportTitle: function() {
  650. return Session.get("reportTitle");
  651. },
  652. reportAuthor: function() {
  653. return Session.get("reportAuthor");
  654. },
  655. reportDuration: function() {
  656. return Session.get("reportDuration");
  657. },
  658. reportAudio: function() {
  659. return Session.get("reportAudio");
  660. },
  661. reportAlbumart: function() {
  662. return Session.get("reportAlbumart");
  663. },
  664. reportOther: function() {
  665. return Session.get("reportOther");
  666. },
  667. currentSong: function() {
  668. return Session.get("currentSong");
  669. },
  670. previousSong: function() {
  671. return Session.get("previousSong");
  672. },
  673. currentSongR: function() {
  674. return Session.get("currentSongR");
  675. },
  676. previousSongR: function() {
  677. return Session.get("previousSongR");
  678. },
  679. reportingSong: function() {
  680. if (Session.get("reportPrevious")) {
  681. return Session.get("previousSongR");
  682. } else {
  683. return Session.get("currentSongR");
  684. }
  685. },
  686. votes: function(){
  687. return Rooms.findOne({type: Session.get("type")}).votes;
  688. }
  689. });
  690. var allAlertSub = undefined;
  691. Template.alertsDashboard.onCreated(function() {
  692. if (allAlertSub === undefined) {
  693. allAlertSub = Meteor.subscribe("allAlerts");
  694. }
  695. });
  696. Template.alertsDashboard.helpers({
  697. "activeAlerts": function() {
  698. return Alerts.find({active: true});
  699. },
  700. "inactiveAlerts": function() {
  701. return Alerts.find({active: false});
  702. }
  703. });
  704. Template.alertsDashboard.events({
  705. "click #calart-create": function() {
  706. Meteor.call("addAlert", $("#calert-description").val(), $("#calert-priority").val().toLowerCase(), function (err, res) {
  707. if (err) {
  708. alert("Error " + err.error + ": " + err.reason);
  709. } else {
  710. $("#calert-description").val("");
  711. }
  712. });
  713. },
  714. "click #ralert-button": function() {
  715. Meteor.call("removeAlerts");
  716. }
  717. });
  718. Template.admin.helpers({
  719. queueCount: function(i) {
  720. var queues = Queues.find({}).fetch();
  721. if (!queues[i]) {
  722. return 0;
  723. }
  724. else {
  725. return queues[i].songs.length;
  726. }
  727. },
  728. users: function(){
  729. Meteor.call("getUserNum", function(err, num){
  730. if(err){
  731. console.log(err);
  732. }
  733. Session.set("userNum", num);
  734. });
  735. return Session.get("userNum");
  736. },
  737. playlists: function() {
  738. var playlists = Playlists.find({}).fetch();
  739. playlists.map(function(playlist) {
  740. if (Rooms.find({type: playlist.type}).count() !== 1) {
  741. return;
  742. } else {
  743. playlist.display = Rooms.findOne({type: playlist.type}).display;
  744. return playlist;
  745. }
  746. });
  747. return playlists;
  748. },
  749. reports: function() {
  750. var reports = Reports.find({}).fetch();
  751. console.log(reports);
  752. }
  753. });
  754. Template.stations.helpers({
  755. queues: function() {
  756. var queues = Queues.find({}).fetch();
  757. queues.map(function(queue) {
  758. if (Rooms.find({type: queue.type}).count() !== 1) {
  759. return;
  760. } else {
  761. queue.display = Rooms.findOne({type: queue.type}).display;
  762. return queue;
  763. }
  764. });
  765. return queues;
  766. },
  767. playlists: function() {
  768. var playlists = Playlists.find({}).fetch();
  769. playlists.map(function(playlist) {
  770. if (Rooms.find({type: playlist.type}).count() !== 1) {
  771. return;
  772. } else {
  773. playlist.display = Rooms.findOne({type: playlist.type}).display;
  774. return playlist;
  775. }
  776. });
  777. return playlists;
  778. }
  779. });
  780. var yt_player = undefined;
  781. var _sound = undefined;
  782. Template.stations.events({
  783. "click .preview-button": function(e){
  784. Session.set("song", this);
  785. },
  786. "click #previewImageButton": function() {
  787. $("#preview-image").attr("src", Session.get("song").img);
  788. },
  789. "click .edit-queue-button": function(e){
  790. Session.set("song", this);
  791. Session.set("genre", $(e.toElement).data("genre"));
  792. Session.set("type", "queue");
  793. $("#type").val(this.type);
  794. $("#mid").val(this.mid);
  795. $("#artist").val(this.artist);
  796. $("#title").val(this.title);
  797. $("#img").val(this.img);
  798. $("#id").val(this.id);
  799. $("#likes").val(this.likes);
  800. $("#dislikes").val(this.dislikes);
  801. $("#duration").val(this.duration);
  802. $("#skip-duration").val(this.skipDuration);
  803. },
  804. "click .edit-playlist-button": function(e){
  805. Session.set("song", this);
  806. Session.set("genre", $(e.toElement).data("genre"));
  807. Session.set("type", "playlist");
  808. $("#type").val(this.type);
  809. $("#mid").val(this.mid);
  810. $("#artist").val(this.artist);
  811. $("#title").val(this.title);
  812. $("#img").val(this.img);
  813. $("#id").val(this.id);
  814. $("#likes").val(this.likes);
  815. $("#dislikes").val(this.dislikes);
  816. $("#duration").val(this.duration);
  817. $("#skip-duration").val(this.skipDuration);
  818. },
  819. "click #rreset_confirm": function(e){
  820. Meteor.call("resetRating");
  821. },
  822. "click .add-song-button": function(e){
  823. var genre = $(e.toElement).data("genre") || $(e.toElement).parent().data("genre");
  824. Meteor.call("addSongToPlaylist", genre, this);
  825. },
  826. "click .deny-song-button": function(e){
  827. var genre = $(e.toElement).data("genre") || $(e.toElement).parent().data("genre");
  828. Meteor.call("removeSongFromQueue", genre, this.mid);
  829. },
  830. "click .remove-song-button": function(e){
  831. var genre = $(e.toElement).data("genre") || $(e.toElement).parent().data("genre");
  832. Meteor.call("removeSongFromPlaylist", genre, this.mid);
  833. },
  834. "click #play": function() {
  835. $("#play").attr("disabled", true);
  836. $("#stop").attr("disabled", false);
  837. var song = Session.get("song");
  838. var id = song.id;
  839. var type = song.type;
  840. var volume = localStorage.getItem("volume") || 20;
  841. if (type === "YouTube") {
  842. if (yt_player === undefined) {
  843. yt_player = new YT.Player("previewPlayer", {
  844. height: 540,
  845. width: 568,
  846. videoId: id,
  847. playerVars: {autoplay: 1, controls: 0, iv_load_policy: 3, showinfo: 0},
  848. events: {
  849. 'onReady': function(event) {
  850. event.target.playVideo();
  851. event.target.setVolume(volume);
  852. },
  853. 'onStateChange': function(event){
  854. if (event.data == YT.PlayerState.PAUSED) {
  855. event.target.playVideo();
  856. }
  857. if (event.data == YT.PlayerState.PLAYING) {
  858. $("#play").attr("disabled", true);
  859. $("#stop").attr("disabled", false);
  860. } else {
  861. $("#play").attr("disabled", false);
  862. $("#stop").attr("disabled", true);
  863. }
  864. }
  865. }
  866. });
  867. } else {
  868. yt_player.loadVideoById(id);
  869. }
  870. $("#previewPlayer").show();
  871. } else if (type === "SoundCloud") {
  872. SC.stream("/tracks/" + song.id, function(sound) {
  873. _sound = sound;
  874. sound.setVolume(volume / 100);
  875. sound.play();
  876. });
  877. }
  878. },
  879. "click #stop": function() {
  880. $("#play").attr("disabled", false);
  881. $("#stop").attr("disabled", true);
  882. if (yt_player !== undefined) {
  883. yt_player.stopVideo();
  884. }
  885. if (_sound !== undefined) {
  886. _sound.stop();
  887. }
  888. },
  889. "click #croom_create": function() {
  890. Meteor.call("createRoom", $("#croom_display").val(), $("#croom_tag").val(), function (err, res) {
  891. if (err) {
  892. alert("Error " + err.error + ": " + err.reason);
  893. } else {
  894. window.location = "/" + $("#croom_tag").val();
  895. }
  896. });
  897. },
  898. "click #get-spotify-info": function() {
  899. var search = $("#title").val();
  900. var artistName = $("#artist").val();
  901. getSpotifyInfo(search, function(data) {
  902. for(var i in data){
  903. for(var j in data[i].items){
  904. if(search.indexOf(data[i].items[j].name) !== -1 && artistName.indexOf(data[i].items[j].artists[0].name) !== -1){
  905. $("#img").val(data[i].items[j].album.images[1].url);
  906. $("#duration").val(data[i].items[j].duration_ms / 1000);
  907. return;
  908. }
  909. }
  910. }
  911. }, artistName);
  912. },
  913. "click #save-song-button": function() {
  914. var newSong = {};
  915. newSong.id = $("#id").val();
  916. newSong.likes = $("#likes").val();
  917. newSong.dislikes = $("#dislikes").val();
  918. newSong.title = $("#title").val();
  919. newSong.artist = $("#artist").val();
  920. newSong.img = $("#img").val();
  921. newSong.type = $("#type").val();
  922. newSong.duration = $("#duration").val();
  923. newSong.skipDuration = $("#skip-duration").val();
  924. if(newSong.skipDuration === undefined){
  925. newSong.skipDuration = 0;
  926. };
  927. if (Session.get("type") === "playlist") {
  928. Meteor.call("updatePlaylistSong", Session.get("genre"), Session.get("song"), newSong, function() {
  929. $('#editModal').modal('hide');
  930. });
  931. } else {
  932. Meteor.call("updateQueueSong", Session.get("genre"), Session.get("song"), newSong, function() {
  933. $('#editModal').modal('hide');
  934. });
  935. }
  936. },
  937. "click .delete-room": function(){
  938. var typeDel = $(this)[0].type;
  939. Meteor.call("deleteRoom", typeDel);
  940. }
  941. });
  942. Template.stations.onCreated(function() {
  943. var tag = document.createElement("script");
  944. tag.src = "https://www.youtube.com/iframe_api";
  945. var firstScriptTag = document.getElementsByTagName('script')[0];
  946. firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  947. });
  948. Template.stations.onRendered(function() {
  949. $("#previewModal").on("hidden.bs.modal", function() {
  950. if (yt_player !== undefined) {
  951. $("#play").attr("disabled", false);
  952. $("#stop").attr("disabled", true);
  953. $("#previewPlayer").hide();
  954. yt_player.loadVideoById("", 0);
  955. yt_player.seekTo(0);
  956. yt_player.stopVideo();
  957. }
  958. if (_sound !== undefined) {
  959. _sound.stop();
  960. $("#play").attr("disabled", false);
  961. $("#stop").attr("disabled", true);
  962. }
  963. });
  964. $(document).ready(function() {
  965. function makeSlider(){
  966. var slider = $("#volume-slider").slider();
  967. var volume = localStorage.getItem("volume") || 20;
  968. $("#volume-slider").slider("setValue", volume);
  969. if (slider.length === 0) {
  970. Meteor.setTimeout(function() {
  971. makeSlider();
  972. }, 500);
  973. } else {
  974. slider.on("slide", function(val) {
  975. localStorage.setItem("volume", val.value);
  976. if (yt_player !== undefined) {
  977. yt_player.setVolume(val.value);
  978. } else if (_sound !== undefined) {
  979. var volume = val.value / 100;
  980. _sound.setVolume(volume);
  981. }
  982. });
  983. }
  984. }
  985. makeSlider();
  986. });
  987. });
  988. Template.playlist.helpers({
  989. playlist_songs: function() {
  990. parts = location.href.split('/');
  991. id = parts.pop();
  992. type = id.toLowerCase();
  993. var data = Playlists.findOne({type: type});
  994. if (data !== undefined) {
  995. data.songs.map(function(song) {
  996. if (Session.get("currentSong") !== undefined && song.mid === Session.get("currentSong").mid) {
  997. song.current = true;
  998. } else {
  999. song.current = false;
  1000. }
  1001. return song;
  1002. });
  1003. return data.songs;
  1004. } else {
  1005. return [];
  1006. }
  1007. }
  1008. });
  1009. Template.playlist.events({
  1010. "keyup #search-playlist": function(){
  1011. console.log($("#search-playlist").val());
  1012. if($("#search-playlist").val().length === 0){
  1013. $(".pl-item").show();
  1014. } else {
  1015. $(".pl-item").hide();
  1016. var input = $("#search-playlist").val().toLowerCase();
  1017. $(".pl-item strong").each(function(i, el){
  1018. if($(el).text().toLowerCase().indexOf(input) !== -1){
  1019. $(el).parent(".pl-item").show();
  1020. }
  1021. })
  1022. $(".pl-item #pl-artist").each(function(i, el){
  1023. if($(el).text().toLowerCase().indexOf(input) !== -1){
  1024. $(el).parent(".pl-item").show();
  1025. }
  1026. })
  1027. }
  1028. }
  1029. })
  1030. Meteor.subscribe("rooms");
  1031. Template.room.onCreated(function () {
  1032. Session.set("reportSong", false);
  1033. Session.set("reportTitle", false);
  1034. Session.set("reportAuthor", false);
  1035. Session.set("reportDuration", false);
  1036. Session.set("reportAudio", false);
  1037. Session.set("reportAlbumart", false);
  1038. Session.set("reportOther", false);
  1039. if (resizeSeekerbarInterval !== undefined) {
  1040. Meteor.clearInterval(resizeSeekerbarInterval);
  1041. resizeSeekerbarInterval = undefined;
  1042. }
  1043. yt_player = undefined;
  1044. _sound = undefined;
  1045. Session.set("videoHidden", false);
  1046. var tag = document.createElement("script");
  1047. tag.src = "https://www.youtube.com/iframe_api";
  1048. var firstScriptTag = document.getElementsByTagName('script')[0];
  1049. firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  1050. var currentSong = undefined;
  1051. var currentSongR = undefined;
  1052. function getTimeElapsed() {
  1053. if (currentSong !== undefined) {
  1054. var room = Rooms.findOne({type: type});
  1055. if (room !== undefined) {
  1056. return Date.now() - currentSong.started - room.timePaused;
  1057. }
  1058. }
  1059. return 0;
  1060. }
  1061. function getSongInfo(songData){
  1062. Session.set("title", songData.title);
  1063. Session.set("artist", songData.artist);
  1064. Session.set("id", songData.id);
  1065. $("#song-img").attr("src", songData.img);
  1066. Session.set("duration", parseInt(songData.duration));
  1067. var d = moment.duration(parseInt(songData.duration), 'seconds');
  1068. $("#time-total").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
  1069. Session.set("timeFormat", d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
  1070. }
  1071. function resizeSeekerbar() {
  1072. if (Session.get("state") === "playing") {
  1073. $("#seeker-bar").width(((getTimeElapsed() / 1000) / Session.get("duration") * 100) + "%");
  1074. }
  1075. }
  1076. function startSong() {
  1077. $("#time-elapsed").text("0:00");
  1078. $("#vote-skip").attr("disabled", false);
  1079. if (currentSong !== undefined) {
  1080. if (_sound !== undefined) _sound.stop();
  1081. if (yt_player !== undefined && yt_player.stopVideo !== undefined) yt_player.stopVideo();
  1082. var volume = localStorage.getItem("volume") || 20;
  1083. $("#media-container").empty();
  1084. yt_player = undefined;
  1085. if (currentSong.type === "SoundCloud") {
  1086. $("#media-container").append('<img src="/soundcloud-image.png" class="embed-responsive-item" />');
  1087. getSongInfo(currentSong);
  1088. SC.stream("/tracks/" + currentSong.id, function(sound){
  1089. _sound = sound;
  1090. sound.setVolume(volume / 100);
  1091. sound.play();
  1092. var interval = setInterval(function() {
  1093. if (sound.getState() === "playing") {
  1094. sound.seek(getTimeElapsed());
  1095. window.clearInterval(interval);
  1096. }
  1097. }, 200);
  1098. Session.set("duration", parseInt(currentSong.duration));
  1099. var d = moment.duration(parseInt(currentSong.duration), 'seconds');
  1100. $("#time-total").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
  1101. resizeSeekerbar();
  1102. });
  1103. } else {
  1104. $("#media-container").append('<div id="player" class="embed-responsive-item"></div>');
  1105. if (yt_player === undefined) {
  1106. yt_player = new YT.Player("player", {
  1107. height: 540,
  1108. width: 960,
  1109. videoId: currentSong.id,
  1110. playerVars: {controls: 0, iv_load_policy: 3, rel: 0, showinfo: 0},
  1111. events: {
  1112. 'onReady': function(event) {
  1113. if(currentSong.skipDuration === undefined){
  1114. currentSong.skipDuration = 0;
  1115. }
  1116. event.target.seekTo(Number(currentSong.skipDuration) + getTimeElapsed() / 1000);
  1117. event.target.playVideo();
  1118. event.target.setVolume(volume);
  1119. resizeSeekerbar();
  1120. },
  1121. 'onStateChange': function(event){
  1122. if (event.data == YT.PlayerState.PAUSED && Session.get("state") === "playing") {
  1123. event.target.seekTo(Number(currentSong.skipDuration) + getTimeElapsed() / 1000);
  1124. event.target.playVideo();
  1125. }
  1126. if (event.data == YT.PlayerState.PLAYING && Session.get("state") === "paused") {
  1127. event.target.seekTo(Number(currentSong.skipDuration) + getTimeElapsed() / 1000);
  1128. event.target.pauseVideo();
  1129. }
  1130. }
  1131. }
  1132. });
  1133. } else {
  1134. yt_player.loadVideoById(currentSong.id);
  1135. }
  1136. getSongInfo(currentSong);
  1137. }
  1138. }
  1139. }
  1140. Session.set("loaded", false);
  1141. Meteor.subscribe("rooms", function() {
  1142. var parts = location.href.split('/');
  1143. var id = parts.pop();
  1144. var type = id.toLowerCase();
  1145. Session.set("type", type);
  1146. if (Rooms.find({type: type}).count() !== 1) {
  1147. window.location = "/";
  1148. } else {
  1149. station_c = Meteor.subscribe(type);
  1150. Session.set("loaded", true);
  1151. minterval = Meteor.setInterval(function () {
  1152. var room = Rooms.findOne({type: type});
  1153. if (room !== undefined) {
  1154. if (room.state === "paused") {
  1155. Session.set("state", "paused");
  1156. if (yt_player !== undefined && yt_player.getPlayerState !== undefined && yt_player.getPlayerState() === 1) {
  1157. yt_player.pauseVideo();
  1158. } else if (_sound !== undefined && _sound.getState().indexOf("playing") !== -1) {
  1159. _sound.pause();
  1160. }
  1161. } else {
  1162. Session.set("state", "playing");
  1163. if (yt_player !== undefined && yt_player.getPlayerState !== undefined && yt_player.getPlayerState() !== 1) {
  1164. yt_player.playVideo();
  1165. } else if (_sound !== undefined && _sound.getState().indexOf("paused") !== -1) {
  1166. _sound.play();
  1167. }
  1168. }
  1169. }
  1170. if (currentSongR === undefined || room.currentSong.started !== currentSongR.started) {
  1171. Session.set("previousSong", currentSong);
  1172. currentSongR = room.currentSong;
  1173. currentSong = room.currentSong.song;
  1174. currentSong.started = room.currentSong.started;
  1175. Session.set("currentSong", currentSong);
  1176. startSong();
  1177. }
  1178. if (currentSong !== undefined) {
  1179. if (room !== undefined) {
  1180. var duration = (Date.now() - currentSong.started - room.timePaused) / 1000;
  1181. var d = moment.duration(duration, 'seconds');
  1182. if (Session.get("state") === "playing") {
  1183. $("#time-elapsed").text(d.minutes() + ":" + ("0" + d.seconds()).slice(-2));
  1184. }
  1185. }
  1186. }
  1187. }, 1000);
  1188. resizeSeekerbarInterval = Meteor.setInterval(function () {
  1189. resizeSeekerbar();
  1190. }, 500);
  1191. }
  1192. });
  1193. });