app.js 38 KB

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