123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- module.exports = function (io) {
- var app = require('express')();
- // Body parsing
- var bodyParser = require('body-parser');
- app.use(bodyParser.urlencoded({extended: true}));
- app.use(bodyParser.json());
- // Validation
- var expressValidator = require('express-validator');
- app.use(expressValidator());
- // Child process, for spawning youtube-dl
- var child_process = require('child_process');
- // The location of the youtube-dl executable
- var YOUTUBE_DL_LOC = '/usr/bin/youtube-dl'
- // Keep track of music to play, playing, and played
- var playlist = [];
- var playing = 'None';
- var played = [];
- var Player = require('player');
- // Create a player with the proper error handling.
- function playerCreator(song) {
- if (song)
- return new Player(song)
- .on('error', function(err) {playerHandleError(playlist, played)})
- return new Player()
- .on('error', function(err) {playerHandleError(playlist, played)})
- }
- player = playerCreator();
- playerState = 'playing';
- io.on('connection', function(socket){
- io.emit(playerState);
- socket.on('chat message', function(msg){
- io.emit('chat message', msg);
- });
- // TODO handle button when nothing is playing.
- socket.on('pause', function() {
- console.log('pausing');
- io.emit('player-transition', 'Pausing');
- player.pause();
- playerState = 'paused';
- // Player is a high quality plugin, and breaks if you spam
- // pause(). So put a 3 second delay in between
- // transitions.
- // TODO Find a better way to handle this.
- setTimeout(function() {
- io.emit('paused');
- }, 3000);
- });
- socket.on('play', function() {
- console.log('playing');
- io.emit('player-transition', 'Playing');
- player.pause();
- playerState = 'playing';
- setTimeout(function() {
- io.emit('playing');
- }, 3000);
- });
-
- });
- // Player functionality
- // Songs move from playlist (if nothing is playing presently), to playing, to played.
- // TODO check if song already exists in played.
- // event: on error (No next song was found).
- function playerHandleError(playlist, played) {
- // TODO Workaround for a bug in player: wait a couple seconds so the
- // songs don't overlap.
-
- // Move the recently playing song to played.
- played.push(playing);
- if (playlist.length != 0) {
- // Play the next song.
- player = playerCreator(playlist[0]);
- player.play();
- // Remove the added song.
- playing = playlist[0];
- playlist.shift();
- } else {
- // Reset the object, resetting its playlist.
- player = playerCreator();
- playing = 'None';
- }
- }
- // Add a song and start the playlist, if it's empty.
- function playerAddSong(song) {
- if (player.list.length == 0) {
- // If this is the player's first song, start it.
- player = playerCreator(song);
- player.play();
- playing = song;
- } else {
- // Otherwise add it to the queue
- playlist.push(song);
- }
- }
- /* GET home page. */
- app.get('/', function(req, res, next) {
- var playlist_view;
- if(playlist.length) {
- playlist_view = '<p>Playlist:</p><ul>';
- for(var i=0; i < playlist.length; i++) {
- playlist_view +=
- '<li>' +
- playlist[i].replace(/^\.\/downloads\//, '') .replace(/\.mp3$/, '') +
- '</li>';
- }
- playlist_view += '</ul>';
- } else {
- playlist_view = '<p>No songs in playlist.</p>';
- }
- var playing_view = '<p>Now playing: ' + playing.replace(/^\.\/downloads\//, '') .replace(/\.mp3$/, '') + '</p>';
- var played_view;
- if(played.length) {
- played_view = '<p>Played:</p><ul>';
- for(var i=0; i < played.length; i++) {
- played_view +=
- '<li>' +
- played[i].replace(/^\.\/downloads\//, '') .replace(/\.mp3$/, '') +
- '</li>';
- }
- played_view += '</ul>';
- } else {
- played_view = '<p>No played songs.</p>';
- }
- res.render('index', { playlist_view: playlist_view,
- playing_view: playing_view,
- played_view: played_view });
- });
- app.get('/youtube', function(req, res, next) {
- res.render('youtube');
- });
- app.use(expressValidator({
- customValidators: {
- dlSuccess: function(video) {
- // Test if the requested video is available.
- // TODO make this non-blocking so music doesn't stop
- var youtube_dl = child_process.spawnSync(YOUTUBE_DL_LOC, ['-s', video]);
- // DEBUG: for when I forget to change the var
- if(youtube_dl.stderr == null) {
- console.log('Your youtube-dl location is probably invalid.');
- }
- if (youtube_dl.stderr.toString()) {
- return false;
- }
- return true;
- }
- }
- }
- ));
- app.post('/youtube', function(req, res) {
- var video = req.body.video;
-
- req.checkBody('video', 'URL is not valid.').dlSuccess();
-
- var errors = req.validationErrors();
-
- if(errors){
- res.render('youtube', {
- errors:errors
- });
- } else {
- var youtube_dl = child_process.spawn(YOUTUBE_DL_LOC, ['-x', '--audio-format', 'mp3', '-o', 'downloads/%(title)s.%(ext)s', video]);
- youtube_dl.on('close', (code) => {
- console.log('Done getting ' + video);
- var error;
- youtube_dl.stderr.on('data', (data) => {
- error = data;
- console.log(`Error getting video: ${data}`);
- // TODO give error to user when they return to /
- });
- if(!error) {
- var youtube_dl_get_title = child_process.spawnSync(YOUTUBE_DL_LOC, ['--get-title', video]);
- console.log(youtube_dl_get_title.stdout.toString());
- playerAddSong('./downloads/' + youtube_dl_get_title.stdout.toString()
- .replace('\n', '')
- .replace(new RegExp('"', 'g'), '\'')
- + '.mp3');
- }
- res.redirect('/');
- });
- }
- });
- app.get('/file', function(req, res, next) {
- res.render('file');
- });
- // Return the router.
- return app;
- // module.exports = app;
- };
|