Browse Source

Worked more on the whole system.

KrisVos130 8 years ago
parent
commit
90d32e656a

+ 1 - 2
backend/index.js

@@ -79,8 +79,7 @@ async.waterfall([
 	if (err && err !== true) {
 		console.error('An error occurred while initializing the backend server');
 		console.error(err);
-	}
-	else {
+	} else {
 		console.log('Backend server has been successfully started');
 	}
 });

+ 1 - 0
backend/logic/actions/index.js

@@ -3,6 +3,7 @@
 module.exports = {
 	apis: require('./apis'),
 	songs: require('./songs'),
+	queueSongs: require('./queueSongs'),
 	stations: require('./stations'),
 	users: require('./users'),
 	news: require('./news')

+ 29 - 5
backend/logic/actions/queueSongs.js

@@ -2,7 +2,23 @@
 
 const db = require('../db');
 const utils = require('../utils');
+const notifications = require('../notifications');
 const async = require('async');
+const config = require('config');
+const request = require('request');
+
+notifications.subscribe("queue.newSong", function(songId) {
+	io.to('admin.queue').emit("event:song.new", { songId });
+});
+
+notifications.subscribe("queue.removedSong", function(songId) {
+	io.to('admin.queue').emit("event:song.removed", { songId });
+});
+
+notifications.subscribe("queue.updatedSong", function(songId) {
+	//TODO Retrieve new Song object
+	io.to('admin.queue').emit("event:song.updated", { songId });
+});
 
 module.exports = {
 
@@ -56,6 +72,7 @@ module.exports = {
 		async.waterfall([
 			// Get YouTube data from id
 			(next) => {
+				console.log(111, id);
 				const youtubeParams = [
 					'part=snippet,contentDetails,statistics,status',
 					`id=${encodeURIComponent(id)}`,
@@ -72,6 +89,7 @@ module.exports = {
 					body = JSON.parse(body);
 
 					//TODO Clean up duration converter
+					console.log(body);
 					let dur = body.items[0].contentDetails.duration;
 					dur = dur.replace("PT", "");
 					let durInSec = 0;
@@ -92,15 +110,15 @@ module.exports = {
 					});
 
 					let newSong = {
-						id: body.items[0].id,
+						_id: body.items[0].id,
 						title: body.items[0].snippet.title,
 						artists: [],
 						genres: [],
 						duration: durInSec,
 						skipDuration: 0,
-						thumbnail: '',
+						thumbnail: 'default.png',
 						explicit: false,
-						requestedBy: '',
+						requestedBy: 'temp',
 						requestedAt: requestedAt
 					};
 
@@ -108,6 +126,7 @@ module.exports = {
 				});
 			},
 			(newSong, next) => {
+				console.log(222);
 				const spotifyParams = [
 					`q=${encodeURIComponent(newSong.title)}`,
 					`type=track`
@@ -141,6 +160,7 @@ module.exports = {
 								});
 								newSong.title = item.name;
 								newSong.explicit = item.explicit;
+								newSong.thumbnail = item.album.images[1].url;
 								break durationArtistLoop;
 							}
 						}
@@ -150,6 +170,7 @@ module.exports = {
 				});
 			},
 			(newSong, next) => {
+				console.log(333);
 				const song = new db.models.queueSong(newSong);
 
 				song.save(err => {
@@ -161,15 +182,18 @@ module.exports = {
 
 					//stations.getStation(station).playlist.push(newSong);
 
-					next(null);
+					next(null, newSong);
 				});
 			}
 		],
-		(err) => {
+		(err, newSong) => {
+			console.log(444, err);
 			if (err) {
 				return cb({ status: 'failure', message: err });
 			}
 
+			//TODO Emit to Redis
+			notifications.emit("queue.newSong", newSong._id);
 			return cb({ status: 'success', message: 'Successfully added that song to the queue.' });
 		});
 	}

+ 49 - 38
backend/logic/actions/stations.js

@@ -12,6 +12,22 @@ const utils = require('../utils');
 
 let stationsLoaded = {};
 
+notifications.subscribe('station.locked', function(stationName) {
+	io.to(`station.${stationName}`).emit("event:station.locked");
+});
+
+notifications.subscribe('station.unlocked', function(stationName) {
+	io.to(`station.${stationName}`).emit("event:station.unlocked");
+});
+
+notifications.subscribe('station.pause', function(stationName) {
+	io.to(`station.${stationName}`).emit("event:station.pause");
+});
+
+notifications.subscribe('station.resume', function(stationName) {
+	io.to(`station.${stationName}`).emit("event:station.resume");
+});
+
 /**
  * Loads a station into the cache, and sets up all the related logic
  *
@@ -133,6 +149,15 @@ module.exports = {
 	 * @return {{ status: String, userCount: Integer }}
 	 */
 	join: (session, stationId, cb) => {
+		let ns = io.io.of("/");
+		if (ns) {
+			for (let id in ns.connected) {
+				console.log(ns.connected[id]);
+				console.log(ns.connected[id].testProp);
+			}
+		}
+
+
 		initializeAndReturnStation(stationId, (err, station) => {
 
 			if (err && err !== true) {
@@ -222,46 +247,32 @@ module.exports = {
 		});
 	},
 
-	addSong: (session, station, song, cb) => {
-
-		if (!session.logged_in) return cb({ status: 'failure', message: 'You must be logged in to add a song' });
-
-		const params = [
-			'part=snippet,contentDetails,statistics,status',
-			`id=${encodeURIComponent(song.id)}`,
-			`key=${config.get('apis.youtube.key')}`
-		].join('&');
-
-		request(`https://www.googleapis.com/youtube/v3/videos?${params}`, (err, res, body) => {
-
-			if (err) {
-				console.error(err);
-				return cb({ status: 'error', message: 'Failed to find song from youtube' });
+	lock: (session, stationId, cb) => {
+		//TODO Require admin
+		initializeAndReturnStation(stationId, (err, station) => {
+			if (err && err !== true) {
+				return cb({ status: 'error', message: 'An error occurred while locking the station' });
+			} else if (station) {
+				// Add code to update Mongo and Redis
+				cb({ status: 'success' });
+			} else {
+				cb({ status: 'failure', message: `That station doesn't exist, it may have been deleted` });
 			}
+		});
+	},
 
-			body = JSON.parse(body);
-
-			const newSong = new db.models.song({
-				id: body.items[0].id,
-				title: body.items[0].snippet.title,
-				duration: utils.convertTime(body.items[0].contentDetails.duration),
-				thumbnail: body.items[0].snippet.thumbnails.high.url
-			});
-
-			// save the song to the database
-			newSong.save(err => {
-
-				if (err) {
-					console.error(err);
-					return cb({ status: 'error', message: 'Failed to save song from youtube to the database' });
-				}
-				//TODO Emit to cache, and listen on cache
-
-				// stations.getStation(station).playlist.push(newSong);
-
-				// cb({ status: 'success', data: stations.getStation(station.playlist) });
-			});
+	unlock: (session, stationId, cb) => {
+		//TODO Require admin
+		initializeAndReturnStation(stationId, (err, station) => {
+			if (err && err !== true) {
+				return cb({ status: 'error', message: 'An error occurred while unlocking the station' });
+			} else if (station) {
+				// Add code to update Mongo and Redis
+				cb({ status: 'success' });
+			} else {
+				cb({ status: 'failure', message: `That station doesn't exist, it may have been deleted` });
+			}
 		});
-	}
+	},
 
 };

+ 12 - 5
backend/logic/actions/users.js

@@ -11,7 +11,7 @@ const utils = require('../utils');
 
 module.exports = {
 
-	login: (session, identifier, password, cb) => {
+	login: (sessionId, identifier, password, cb) => {
 
 		async.waterfall([
 
@@ -32,10 +32,17 @@ module.exports = {
 					if (match) {
 
 						// store the session in the cache
-						let sessionId = utils.guid();
-						cache.hset('sessions', sessionId, cache.schemas.session());
-
-						next(null, { status: 'success', message: 'Login successful', user, sessionId: sessionId });
+						let userSessionId = utils.guid();
+						cache.hset('userSessions', userSessionId, cache.schemas.userSession(user._id), (err) => {
+							if (!err) {
+								cache.hget('sessions', sessionId, (err, session) => {
+									session.userSessionId = userSessionId;
+									cache.hset('sessions', sessionId, session, (err) => {
+										next(null, { status: 'success', message: 'Login successful', user, SID: userSessionId });
+									})
+								})
+							}
+						});
 					}
 					else {
 						next(null, { status: 'failure', message: 'User not found' });

+ 1 - 0
backend/logic/cache/index.js

@@ -12,6 +12,7 @@ const lib = {
 	url: '',
 	schemas: {
 		session: require('./schemas/session'),
+		userSession: require('./schemas/userSession'),
 		station: require('./schemas/station')
 	},
 

+ 2 - 1
backend/logic/cache/schemas/session.js

@@ -6,9 +6,10 @@
  *
  * @returns {{stationId: null, created: number}}
  */
-module.exports = () => {
+module.exports = (userSessionId) => {
 	return {
 		stationId: null,
+		userSessionId,
 		created: Date.now()
 	};
 };

+ 8 - 0
backend/logic/cache/schemas/userSession.js

@@ -0,0 +1,8 @@
+'use strict';
+
+module.exports = (userId) => {
+	return {
+		userId: userId,
+		created: Date.now()
+	};
+};

+ 1 - 1
backend/logic/db/schemas/queueSong.js

@@ -1,5 +1,5 @@
 module.exports = {
-	id: { type: String, unique: true, required: true },
+	_id: { type: String, unique: true, required: true },
 	title: { type: String, required: true },
 	artists: [{ type: String }],
 	genres: [{ type: String }],

+ 3 - 1
backend/logic/db/schemas/station.js

@@ -14,5 +14,7 @@ module.exports = {
 	currentSongIndex: { type: Number, default: 0, required: true },
 	timePaused: { type: Number, default: 0, required: true },
 	playlist: { type: Array, required: true },
-	genres: [{ type: String }]
+	genres: [{ type: String }],
+	privacy: { type: String, enum: ["public", "unlisted", "private"], default: "private" },//Used for Community stations
+	locked: { type: Boolean, default: true }//Used for Official stations
 };

+ 22 - 7
backend/logic/io.js

@@ -18,14 +18,20 @@ module.exports = {
 
 		this.io.use((socket, next) => {
 			let cookies = socket.request.headers.cookie;
-			// set the sessionId for the socket (this will have to be checked every request, this allows us to have a logout all devices option)
-			console.log(utils.cookies.parseCookies(cookies).SID);
-			if (cookies) socket.sessionId = utils.cookies.parseCookies(cookies).SID;
-			return next();
+			let SID = utils.cookies.parseCookies(cookies).SID;
+
+			cache.hget('userSessions', SID, (err, userSession) => {
+				console.log(err, userSession);
+				let sessionId = utils.guid();
+				cache.hset('sessions', sessionId, cache.schemas.session(), (err, session) => {
+					console.log(err, session);
+					socket.sessionId = sessionId;
+					return next();
+				});
+			});
 		});
 
 		this.io.on('connection', socket => {
-
 			socket.join("SomeRoom");
 			console.log("io: User has connected");
 
@@ -35,6 +41,7 @@ module.exports = {
 				// remove the user from their current station (if any)
 				if (socket.sessionId) {
 					//actions.stations.leave(socket.sessionId, result => {});
+					//TODO Delete session
 					delete socket.sessionId;
 				}
 
@@ -73,7 +80,7 @@ module.exports = {
 							actions[namespace][action].apply(null, [session].concat(args).concat([
 								(result) => {
 									// store the session id
-									if (name == 'users.login' && result.user) socket.sessionId = result.user.sessionId;
+									//if (name == 'users.login' && result.user) socket.sessionId = result.user.sessionId;
 									// respond to the socket with our message
 									cb(result);
 								}
@@ -88,7 +95,15 @@ module.exports = {
 				if (err && err !== true) {
 					socket.emit('ready', false);
 				} else if (session) {
-					socket.emit('ready', true);
+					if (!!session.userSessionId) cache.hget('userSessions', session.userSessionId, (err2, userSession) => {
+						if (err2 && err2 !== true) {
+							socket.emit('ready', false);
+						} else if (userSession) {
+							socket.emit('ready', true);
+						} else {
+							socket.emit('ready', false);
+						}
+					});
 				} else {
 					socket.emit('ready', false);
 				}

+ 1 - 1
frontend/App.vue

@@ -64,7 +64,7 @@
 					if (result.status === 'success') {
 						let date = new Date();
 						date.setTime(new Date().getTime() + (2*365*24*60*60*1000));
-						document.cookie = "SID=" + result.sessionId + "; expires="+ date.toGMTString() +"; path=/";
+						document.cookie = "SID=" + result.SID + "; expires="+ date.toGMTString() +"; path=/";
 						Toast.methods.addToast(`You have been successfully logged in`, 2000);
 						setTimeout(location.reload(), 2500);
 					} else {

+ 9 - 6
frontend/components/Admin/Songs.vue → frontend/components/Admin/QueueSongs.vue

@@ -53,16 +53,19 @@
 		},
 		methods: {
 			update (song) {
-				this.socket.emit('songs.update', song);
+				this.socket.emit('queueSongs.update', song);
 			},
-			remove (song, index) {
-				this.songs.splice(index, 1);
-				this.socket.emit('songs.remove', song);
+			remove (songId) {
+				this.socket.emit('queueSongs.remove', songId);
 			}
 		},
 		ready: function() {
-			let socket = this.socket = this.$parent.$parent.socket;
-			socket.emit('songs.index', (data) => this.songs = data);
+			let _this = this;
+			_this.socket = _this.$parent.$parent.socket;
+			_this.socket.emit('queueSongs.index', (data) => {
+				console.log(data);
+				_this.songs = data;
+			});
 		}
 	}
 </script>

+ 4 - 3
frontend/components/Station/Station.vue

@@ -34,6 +34,7 @@
 							</div>
 						</div>
 					</div>
+					<button @click="addSongToQueue('aHjpOzsQ9YI')">ADD CRYSTALIZE!</button>
 					<div class="column is-4-desktop is-12-mobile">
 						<img class="image" id="song-thumbnail" style="margin-top: 10px !important" :src="currentSong.thumbnail" alt="Song Thumbnail" />
 					</div>
@@ -210,10 +211,10 @@
 					local.player.pauseVideo();
 				}
 			},
-			addSongToQueue: function(song) {
-				console.log('add', song)
+			addSongToQueue: function(songId) {
+				console.log('add', songId);
 				let local = this;
-				local.socket.emit('stations.addSong', local.$route.params.id, song, function(data) {
+				local.socket.emit('queueSongs.add', songId, function(data) {
 					if (data) console.log(data);
 				});
 			},

+ 6 - 6
frontend/components/pages/Admin.vue

@@ -3,10 +3,10 @@
 		<main-header></main-header>
 		<div class="tabs is-centered">
 			<ul>
-				<li :class="{ 'is-active': currentTab == 'songs' }" @click="showTab('songs')">
+				<li :class="{ 'is-active': currentTab == 'queueSongs' }" @click="showTab('queueSongs')">
 					<a>
 						<span class="icon is-small"><i class="fa fa-music"></i></span>
-						<span>Songs</span>
+						<span>Queue Songs</span>
 					</a>
 				</li>
 				<li :class="{ 'is-active': currentTab == 'stations' }" @click="showTab('stations')">
@@ -17,7 +17,7 @@
 				</li>
 			</ul>
 		</div>
-		<songs v-if="currentTab == 'songs'"></songs>
+		<queue-songs v-if="currentTab == 'queueSongs'"></queue-songs>
 		<stations v-if="currentTab == 'stations'"></stations>
 	</div>
 </template>
@@ -26,14 +26,14 @@
 	import MainHeader from '../MainHeader.vue'
 	import MainFooter from '../MainFooter.vue'
 
-	import Songs from '../Admin/Songs.vue'
+	import QueueSongs from '../Admin/QueueSongs.vue'
 	import Stations from '../Admin/Stations.vue'
 
 	export default {
-		components: { MainHeader, MainFooter, Songs, Stations },
+		components: { MainHeader, MainFooter, QueueSongs, Stations },
 		data() {
 			return {
-				currentTab: 'songs'
+				currentTab: 'queueSongs'
 			}
 		},
 		methods: {