app.js 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137
  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. playlist_songs: function() {
  371. var data = Playlists.find({type: type}).fetch();
  372. if (data !== undefined && data.length > 0) {
  373. return data[0].songs;
  374. } else {
  375. return [];
  376. }
  377. }
  378. });
  379. Template.admin.helpers({
  380. queues: function() {
  381. return Queues.find({});
  382. }
  383. });
  384. var yt_player = undefined;
  385. var _sound = undefined;
  386. Template.admin.events({
  387. "click .preview-button": function(e){
  388. Session.set("song", this);
  389. },
  390. "click .edit-button": function(e){
  391. Session.set("song", this);
  392. Session.set("genre", $(e.toElement).data("genre"));
  393. $("#type").val(this.type);
  394. $("#artist").val(this.artist);
  395. $("#title").val(this.title);
  396. $("#img").val(this.img);
  397. $("#id").val(this.id);
  398. $("#duration").val(this.duration);
  399. },
  400. "click #add-song-button": function(e){
  401. var genre = $(e.toElement).data("genre") || $(e.toElement).parent().data("genre");
  402. Meteor.call("addSongToPlaylist", genre, this);
  403. },
  404. "click #deny-song-button": function(e){
  405. var genre = $(e.toElement).data("genre") || $(e.toElement).parent().data("genre");
  406. Meteor.call("removeSongFromQueue", genre, this.id);
  407. },
  408. "click #play": function() {
  409. $("#play").attr("disabled", true);
  410. $("#stop").attr("disabled", false);
  411. var song = Session.get("song");
  412. var id = song.id;
  413. var type = song.type;
  414. var volume = localStorage.getItem("volume") || 20;
  415. if (type === "YouTube") {
  416. if (yt_player === undefined) {
  417. yt_player = new YT.Player("previewPlayer", {
  418. height: 540,
  419. width: 568,
  420. videoId: id,
  421. playerVars: {autoplay: 1, controls: 0, iv_load_policy: 3, showinfo: 0},
  422. events: {
  423. 'onReady': function(event) {
  424. event.target.playVideo();
  425. event.target.setVolume(volume);
  426. },
  427. 'onStateChange': function(event){
  428. if (event.data == YT.PlayerState.PAUSED) {
  429. event.target.playVideo();
  430. }
  431. if (event.data == YT.PlayerState.PLAYING) {
  432. $("#play").attr("disabled", true);
  433. $("#stop").attr("disabled", false);
  434. } else {
  435. $("#play").attr("disabled", false);
  436. $("#stop").attr("disabled", true);
  437. }
  438. }
  439. }
  440. });
  441. } else {
  442. yt_player.loadVideoById(id);
  443. }
  444. $("#previewPlayer").show();
  445. } else if (type === "SoundCloud") {
  446. SC.stream("/tracks/" + song.id, function(sound) {
  447. _sound = sound;
  448. sound.setVolume(volume / 100);
  449. sound.play();
  450. });
  451. }
  452. },
  453. "click #stop": function() {
  454. $("#play").attr("disabled", false);
  455. $("#stop").attr("disabled", true);
  456. if (yt_player !== undefined) {
  457. yt_player.stopVideo();
  458. }
  459. if (_sound !== undefined) {
  460. _sound.stop();
  461. }
  462. },
  463. "click #croom_create": function() {
  464. Meteor.call("createRoom", $("#croom").val(), function (err, res) {
  465. if (err) {
  466. alert("Error " + err.error + ": " + err.reason);
  467. } else {
  468. window.location = "/" + $("#croom").val();
  469. }
  470. });
  471. },
  472. "click #find-img-button": function() {
  473. getSpotifyInfo($("#title").val().replace(/\[.*\]/g, ""), function(data) {
  474. if (data.tracks.items.length > 0) {
  475. $("#img").val(data.tracks.items[0].album.images[1].url);
  476. }
  477. }, $("#artist").val());
  478. },
  479. "click #save-song-button": function() {
  480. var newSong = {};
  481. newSong.title = $("#title").val();
  482. newSong.artist = $("#artist").val();
  483. newSong.img = $("#img").val();
  484. newSong.type = $("#type").val();
  485. newSong.duration = $("#duration").val();
  486. Meteor.call("updateQueueSong", Session.get("genre"), Session.get("song"), newSong, function() {
  487. $('#editModal').modal('hide');
  488. });
  489. }
  490. });
  491. Template.admin.onCreated(function() {
  492. var tag = document.createElement("script");
  493. tag.src = "https://www.youtube.com/iframe_api";
  494. var firstScriptTag = document.getElementsByTagName('script')[0];
  495. firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  496. });
  497. Template.admin.onRendered(function() {
  498. $("#previewModal").on("hidden.bs.modal", function() {
  499. if (yt_player !== undefined) {
  500. $("#play").attr("disabled", false);
  501. $("#stop").attr("disabled", true);
  502. $("#previewPlayer").hide();
  503. yt_player.loadVideoById("", 0);
  504. yt_player.seekTo(0);
  505. yt_player.stopVideo();
  506. }
  507. if (_sound !== undefined) {
  508. _sound.stop();
  509. $("#play").attr("disabled", false);
  510. $("#stop").attr("disabled", true);
  511. }
  512. });
  513. $(document).ready(function() {
  514. function makeSlider(){
  515. var slider = $("#volume-slider").slider();
  516. var volume = localStorage.getItem("volume") || 20;
  517. $("#volume-slider").slider("setValue", volume);
  518. if (slider.length === 0) {
  519. Meteor.setTimeout(function() {
  520. makeSlider();
  521. }, 500);
  522. } else {
  523. slider.on("slide", function(val) {
  524. localStorage.setItem("volume", val.value);
  525. if (yt_player !== undefined) {
  526. yt_player.setVolume(val.value);
  527. } else if (_sound !== undefined) {
  528. var volume = val.value / 100;
  529. _sound.setVolume(volume);
  530. }
  531. });
  532. }
  533. }
  534. makeSlider();
  535. });
  536. });
  537. Template.playlist.helpers({
  538. playlist_songs: function() {
  539. var data = Playlists.find({type: type}).fetch();
  540. if (data !== undefined && data.length > 0) {
  541. data[0].songs.map(function(song) {
  542. if (song.title === Session.get("title")) {
  543. song.current = true;
  544. } else {
  545. song.current = false;
  546. }
  547. return song;
  548. });
  549. return data[0].songs;
  550. } else {
  551. return [];
  552. }
  553. }
  554. });
  555. Meteor.subscribe("rooms");
  556. Meteor.subscribe("chat");
  557. Template.room.onCreated(function () {
  558. yt_player = undefined;
  559. _sound = undefined;
  560. Session.set("videoHidden", false)
  561. var tag = document.createElement("script");
  562. tag.src = "https://www.youtube.com/iframe_api";
  563. var firstScriptTag = document.getElementsByTagName('script')[0];
  564. firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
  565. var currentSong = undefined;
  566. var nextSong = undefined;
  567. var afterSong = undefined;
  568. var size = 0;
  569. var artistStr;
  570. var temp = "";
  571. var currentArt;
  572. function getTimeElapsed() {
  573. if (currentSong !== undefined) {
  574. return Date.now() - currentSong.started;
  575. }
  576. return 0;
  577. }
  578. function getSongInfo(songData){
  579. Session.set("title", songData.title);
  580. Session.set("artist", songData.artist);
  581. $("#song-img").attr("src", songData.img);
  582. Session.set("duration", songData.duration);
  583. }
  584. function resizeSeekerbar() {
  585. $("#seeker-bar").width(((getTimeElapsed() / 1000) / Session.get("duration") * 100) + "%");
  586. }
  587. function startSong() {
  588. if (currentSong !== undefined) {
  589. if (_sound !== undefined) _sound.stop();
  590. if (yt_player !== undefined && yt_player.stopVideo !== undefined) yt_player.stopVideo();
  591. var volume = localStorage.getItem("volume") || 20;
  592. $("#media-container").empty();
  593. yt_player = undefined;
  594. if (currentSong.type === "SoundCloud") {
  595. // Change id from visualizer to media-container
  596. $("#player").attr("src", "");
  597. getSongInfo(currentSong);
  598. SC.stream("/tracks/" + currentSong.id, function(sound){
  599. _sound = sound;
  600. sound.setVolume(volume / 100);
  601. startVisualizer(sound._player._html5Audio);
  602. sound.play();
  603. var interval = setInterval(function() {
  604. if (sound.getState() === "playing") {
  605. sound.seek(getTimeElapsed());
  606. window.clearInterval(interval);
  607. }
  608. }, 200);
  609. // Session.set("title", currentSong.title || "Title");
  610. // Session.set("artist", currentSong.artist || "Artist");
  611. Session.set("duration", currentSong.duration);
  612. resizeSeekerbar();
  613. });
  614. } else {
  615. $("#media-container").append('<div id="player" class="embed-responsive-item"></div>');
  616. if (yt_player === undefined) {
  617. yt_player = new YT.Player("player", {
  618. height: 540,
  619. width: 960,
  620. videoId: currentSong.id,
  621. playerVars: {controls: 0, iv_load_policy: 3, rel: 0, showinfo: 0},
  622. events: {
  623. 'onReady': function(event) {
  624. event.target.seekTo(getTimeElapsed() / 1000);
  625. event.target.playVideo();
  626. event.target.setVolume(volume);
  627. resizeSeekerbar();
  628. },
  629. 'onStateChange': function(event){
  630. if (event.data == YT.PlayerState.PAUSED) {
  631. event.target.seekTo(getTimeElapsed() / 1000);
  632. event.target.playVideo();
  633. }
  634. }
  635. }
  636. });
  637. } else {
  638. yt_player.loadVideoById(currentSong.id);
  639. }
  640. // Session.set("title", currentSong.title || "Title");
  641. // Session.set("artist", currentSong.artist || "Artist");
  642. getSongInfo(currentSong);
  643. //Session.set("duration", currentSong.duration);
  644. }
  645. }
  646. }
  647. Meteor.subscribe("history");
  648. Meteor.subscribe("playlists");
  649. Session.set("loaded", false);
  650. Meteor.subscribe("rooms", function() {
  651. var parts = location.href.split('/');
  652. var id = parts.pop();
  653. var type = id.toLowerCase();
  654. if (Rooms.find({type: type}).count() !== 1) {
  655. window.location = "/";
  656. } else {
  657. Session.set("loaded", true);
  658. minterval = Meteor.setInterval(function () {
  659. var data = undefined;
  660. var dataCursorH = History.find({type: type});
  661. var dataCursorP = Playlists.find({type: type});
  662. dataCursorH.forEach(function (doc) {
  663. if (data === undefined) {
  664. data = doc;
  665. }
  666. });
  667. if (data !== undefined && data.history.length > size) {
  668. //currentSong = data.history[data.history.length - 1];
  669. var songArray = Playlists.find({type: type}).fetch()[0].songs;
  670. var historyObj = data.history[data.history.length - 1];
  671. songArray.forEach(function(song) {
  672. if (song.id === historyObj.song.id) {
  673. currentSong = song;
  674. }
  675. });
  676. currentSong.started = historyObj.started;
  677. var songs = dataCursorP.fetch()[0].songs;
  678. songs.forEach(function(song, index) {
  679. if (currentSong.title === song.title) {
  680. if (index + 1 < songs.length) {
  681. nextSong = songs[index + 1];
  682. } else {
  683. nextSong = songs[0];
  684. }
  685. Session.set("title_next", nextSong.title);
  686. Session.set("artist_next", nextSong.artist);
  687. $("#song-img-next").attr("src", nextSong.img);
  688. if (index + 2 < songs.length) {
  689. afterSong = songs[index + 2];
  690. } else if (songs.length === index + 1 && songs.length > 1 ) {
  691. afterSong = songs[1];
  692. } else {
  693. afterSong = songs[0];
  694. }
  695. Session.set("title_after", afterSong.title);
  696. Session.set("artist_after", afterSong.artist);
  697. $("#song-img-after").attr("src",afterSong.img);
  698. }
  699. });
  700. size = data.history.length;
  701. startSong();
  702. }
  703. }, 1000);
  704. Meteor.setInterval(function () {
  705. resizeSeekerbar();
  706. }, 50);
  707. }
  708. });
  709. });
  710. }
  711. if (Meteor.isServer) {
  712. Meteor.startup(function() {
  713. reCAPTCHA.config({
  714. privatekey: '6LcVxg0TAAAAAI2fgIEEWHFxwNXeVIs8mzq5cfRM'
  715. });
  716. });
  717. Meteor.users.deny({update: function () { return true; }});
  718. Meteor.users.deny({insert: function () { return true; }});
  719. Meteor.users.deny({remove: function () { return true; }});
  720. function getSongDuration(query, artistName){
  721. var duration;
  722. var search = query;
  723. query = query.toLowerCase().split(" ").join("%20");
  724. var res = Meteor.http.get('https://api.spotify.com/v1/search?q=' + query + '&type=track');
  725. for(var i in res.data){
  726. for(var j in res.data[i].items){
  727. if(search.indexOf(res.data[i].items[j].name) !== -1 && artistName.indexOf(res.data[i].items[j].artists[0].name) !== -1){
  728. duration = res.data[i].items[j].duration_ms / 1000;
  729. return duration;
  730. }
  731. }
  732. }
  733. }
  734. function getSongAlbumArt(query, artistName){
  735. var albumart;
  736. var search = query;
  737. query = query.toLowerCase().split(" ").join("%20");
  738. var res = Meteor.http.get('https://api.spotify.com/v1/search?q=' + query + '&type=track');
  739. for(var i in res.data){
  740. for(var j in res.data[i].items){
  741. if(search.indexOf(res.data[i].items[j].name) !== -1 && artistName.indexOf(res.data[i].items[j].artists[0].name) !== -1){
  742. albumart = res.data[i].items[j].album.images[1].url
  743. return albumart;
  744. }
  745. }
  746. }
  747. }
  748. //var room_types = ["edm", "nightcore"];
  749. var songsArr = [];
  750. function getSongsByType(type) {
  751. if (type === "edm") {
  752. return [
  753. {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"},
  754. {id: "aHjpOzsQ9YI", title: "Crystallize", artist: "Lindsey Stirling", duration: getSongDuration("Crystallize", "Lindsey Stirling"), type: "youtube", img: "https://i.scdn.co/image/b0c1ccdd0cd7bcda741ccc1c3e036f4ed2e52312"}
  755. ];
  756. } else if (type === "nightcore") {
  757. 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"}];
  758. } else {
  759. 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"}];
  760. }
  761. }
  762. Rooms.find({}).fetch().forEach(function(room) {
  763. var type = room.type;
  764. if (Playlists.find({type: type}).count() === 0) {
  765. if (type === "edm") {
  766. Playlists.insert({type: type, songs: getSongsByType(type)});
  767. } else if (type === "nightcore") {
  768. Playlists.insert({type: type, songs: getSongsByType(type)});
  769. } else {
  770. Playlists.insert({type: type, songs: getSongsByType(type)});
  771. }
  772. }
  773. if (History.find({type: type}).count() === 0) {
  774. History.insert({type: type, history: []});
  775. }
  776. if (Playlists.find({type: type}).fetch()[0].songs.length === 0) {
  777. // Add a global video to Playlist so it can proceed
  778. } else {
  779. var startedAt = Date.now();
  780. var playlist = Playlists.find({type: type}).fetch()[0];
  781. var songs = playlist.songs;
  782. if (playlist.lastSong === undefined) {
  783. Playlists.update({type: type}, {$set: {lastSong: 0}});
  784. playlist = Playlists.find({type: type}).fetch()[0];
  785. songs = playlist.songs;
  786. }
  787. var currentSong = playlist.lastSong;
  788. addToHistory(songs[currentSong], startedAt);
  789. function addToHistory(song, startedAt) {
  790. History.update({type: type}, {$push: {history: {song: song, started: startedAt}}});
  791. }
  792. function skipSong() {
  793. songs = Playlists.find({type: type}).fetch()[0].songs;
  794. if (currentSong < (songs.length - 1)) {
  795. currentSong++;
  796. } else currentSong = 0;
  797. Playlists.update({type: type}, {$set: {lastSong: currentSong}});
  798. songTimer();
  799. addToHistory(songs[currentSong], startedAt);
  800. }
  801. function songTimer() {
  802. startedAt = Date.now();
  803. Meteor.setTimeout(function() {
  804. skipSong();
  805. }, songs[currentSong].duration * 1000);
  806. }
  807. songTimer();
  808. }
  809. });
  810. Accounts.onCreateUser(function(options, user) {
  811. var username;
  812. if (user.services) {
  813. if (user.services.github) {
  814. username = user.services.github.username;
  815. } else if (user.services.facebook) {
  816. username = user.services.facebook.first_name;
  817. } else if (user.services.password) {
  818. username = user.username;
  819. }
  820. }
  821. user.profile = {username: username, usernameL: username.toLowerCase(), rank: "default"};
  822. return user;
  823. });
  824. ServiceConfiguration.configurations.remove({
  825. service: "facebook"
  826. });
  827. ServiceConfiguration.configurations.insert({
  828. service: "facebook",
  829. appId: "1496014310695890",
  830. secret: "9a039f254a08a1488c08bb0737dbd2a6"
  831. });
  832. ServiceConfiguration.configurations.remove({
  833. service: "github"
  834. });
  835. ServiceConfiguration.configurations.insert({
  836. service: "github",
  837. clientId: "dcecd720f47c0e4001f7",
  838. secret: "375939d001ef1a0ca67c11dbf8fb9aeaa551e01b"
  839. });
  840. Meteor.publish("history", function() {
  841. return History.find({})
  842. });
  843. Meteor.publish("playlists", function() {
  844. return Playlists.find({})
  845. });
  846. Meteor.publish("rooms", function() {
  847. return Rooms.find({});
  848. });
  849. Meteor.publish("queues", function() {
  850. return Queues.find({});
  851. });
  852. Meteor.publish("chat", function() {
  853. return Chat.find({});
  854. });
  855. Meteor.publish("userProfiles", function() {
  856. //console.log(Meteor.users.find({}, {profile: 1, createdAt: 1, services: 0, username: 0, emails: 0})).fetch();
  857. return Meteor.users.find({}, {fields: {profile: 1, createdAt: 1}});
  858. });
  859. Meteor.publish("isAdmin", function() {
  860. return Meteor.users.find({_id: this.userId, "profile.rank": "admin"});
  861. });
  862. Meteor.methods({
  863. createUserMethod: function(formData, captchaData) {
  864. var verifyCaptchaResponse = reCAPTCHA.verifyCaptcha(this.connection.clientAddress, captchaData);
  865. if (!verifyCaptchaResponse.success) {
  866. console.log('reCAPTCHA check failed!', verifyCaptchaResponse);
  867. throw new Meteor.Error(422, 'reCAPTCHA Failed: ' + verifyCaptchaResponse.error);
  868. } else {
  869. console.log('reCAPTCHA verification passed!');
  870. Accounts.createUser({
  871. username: formData.username,
  872. email: formData.email,
  873. password: formData.password
  874. });
  875. }
  876. return true;
  877. },
  878. sendMessage: function(type, message) {
  879. if (Chat.find({type: type}).count() === 0) {
  880. Chat.insert({type: type, messages: []});
  881. }
  882. Chat.update({type: type}, {$push: {messages: {message: message, userid: "Kris"}}})
  883. },
  884. addSongToQueue: function(type, songData) {
  885. type = type.toLowerCase();
  886. if (Rooms.find({type: type}).count() === 1) {
  887. if (Queues.find({type: type}).count() === 0) {
  888. Queues.insert({type: type, songs: []});
  889. }
  890. if (songData !== undefined && Object.keys(songData).length === 5 && songData.type !== undefined && songData.title !== undefined && songData.title !== undefined && songData.artist !== undefined && songData.img !== undefined) {
  891. songData.duration = getSongDuration(songData.title, songData.artist);
  892. songData.img = getSongAlbumArt(songData.title, songData.artist);
  893. Queues.update({type: type}, {$push: {songs: {id: songData.id, title: songData.title, artist: songData.artist, duration: songData.duration, img: songData.img, type: songData.type}}});
  894. return true;
  895. } else {
  896. throw new Meteor.error(403, "Invalid data.");
  897. }
  898. } else {
  899. throw new Meteor.error(403, "Invalid genre.");
  900. }
  901. },
  902. updateQueueSong: function(genre, oldSong, newSong) {
  903. newSong.id = oldSong.id;
  904. Queues.update({type: genre, "songs": oldSong}, {$set: {"songs.$": newSong}});
  905. return true;
  906. },
  907. removeSongFromQueue: function(type, songId) {
  908. type = type.toLowerCase();
  909. Queues.update({type: type}, {$pull: {songs: {id: songId}}});
  910. },
  911. addSongToPlaylist: function(type, songData) {
  912. type = type.toLowerCase();
  913. if (Rooms.find({type: type}).count() === 1) {
  914. if (Playlists.find({type: type}).count() === 0) {
  915. Playlists.insert({type: type, songs: []});
  916. }
  917. 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) {
  918. Playlists.update({type: type}, {$push: {songs: {id: songData.id, title: songData.title, artist: songData.artist, duration: songData.duration, img: songData.img, type: songData.type}}});
  919. Queues.update({type: type}, {$pull: {songs: {id: songData.id}}});
  920. return true;
  921. } else {
  922. throw new Meteor.error(403, "Invalid data.");
  923. }
  924. } else {
  925. throw new Meteor.error(403, "Invalid genre.");
  926. }
  927. },
  928. createRoom: function(type) {
  929. var userData = Meteor.users.find(Meteor.userId());
  930. if (Meteor.userId() && userData.count !== 0 && userData.fetch()[0].profile.rank === "admin") {
  931. if (Rooms.find({type: type}).count() === 0) {
  932. Rooms.insert({type: type}, function(err) {
  933. if (err) {
  934. throw err;
  935. } else {
  936. if (Playlists.find({type: type}).count() === 1) {
  937. if (History.find({type: type}).count() === 0) {
  938. History.insert({type: type, history: []}, function(err3) {
  939. if (err3) {
  940. throw err3;
  941. } else {
  942. startStation();
  943. return true;
  944. }
  945. });
  946. } else {
  947. startStation();
  948. return true;
  949. }
  950. } else {
  951. Playlists.insert({type: type, songs: getSongsByType(type)}, function (err2) {
  952. if (err2) {
  953. throw err2;
  954. } else {
  955. if (History.find({type: type}).count() === 0) {
  956. History.insert({type: type, history: []}, function(err3) {
  957. if (err3) {
  958. throw err3;
  959. } else {
  960. startStation();
  961. return true;
  962. }
  963. });
  964. } else {
  965. startStation();
  966. return true;
  967. }
  968. }
  969. });
  970. }
  971. }
  972. });
  973. } else {
  974. throw "Room already exists";
  975. }
  976. } else {
  977. return false;
  978. }
  979. function startStation() {
  980. var startedAt = Date.now();
  981. var songs = Playlists.find({type: type}).fetch()[0].songs;
  982. var currentSong = 0;
  983. addToHistory(songs[currentSong], startedAt);
  984. function addToHistory(song, startedAt) {
  985. History.update({type: type}, {$push: {history: {song: song, started: startedAt}}});
  986. }
  987. function skipSong() {
  988. songs = Playlists.find({type: type}).fetch()[0].songs;
  989. if (currentSong < (songs.length - 1)) {
  990. currentSong++;
  991. } else currentSong = 0;
  992. songTimer();
  993. addToHistory(songs[currentSong], startedAt);
  994. }
  995. function songTimer() {
  996. startedAt = Date.now();
  997. Meteor.setTimeout(function() {
  998. skipSong();
  999. }, songs[currentSong].duration * 1000);
  1000. }
  1001. songTimer();
  1002. }
  1003. }
  1004. });
  1005. }
  1006. /*Router.waitOn(function() {
  1007. Meteor.subscribe("isAdmin", Meteor.userId());
  1008. });*/
  1009. /*Router.onBeforeAction(function() {
  1010. /*Meteor.autorun(function () {
  1011. if (admin.ready()) {
  1012. this.next();
  1013. }
  1014. });*/
  1015. /*this.next();
  1016. });*/
  1017. Router.route("/", {
  1018. template: "home"
  1019. });
  1020. Router.route("/terms", {
  1021. template: "terms"
  1022. });
  1023. Router.route("/privacy", {
  1024. template: "privacy"
  1025. });
  1026. Router.route("/about", {
  1027. template: "about"
  1028. });
  1029. Router.route("/admin", {
  1030. waitOn: function() {
  1031. return Meteor.subscribe("isAdmin", Meteor.userId());
  1032. },
  1033. action: function() {
  1034. var user = Meteor.users.find({}).fetch();
  1035. if (user[0] !== undefined && user[0].profile !== undefined && user[0].profile.rank === "admin") {
  1036. this.render("admin");
  1037. } else {
  1038. this.redirect("/");
  1039. }
  1040. }
  1041. });
  1042. Router.route("/vis", {
  1043. template: "visualizer"
  1044. });
  1045. Router.route("/:type", {
  1046. template: "room"
  1047. });
  1048. Router.route("/u/:user", {
  1049. template: "profile"
  1050. });